.NET高级面试指南专题七【Socket&WebSocket】

.NET高级面试指南专题七【Socket&WebSocket】_第1张图片

Socket(套接字)是一种在计算机网络中实现通信的一种机制,它提供了一种标准的接口,使不同计算机上的程序能够通过网络进行数据交换。Socket允许在网络中的不同设备之间建立连接,进行双向的数据传输。
Socket通常用于实现客户端-服务器模型,其中一个程序充当服务器,等待其他程序(客户端)连接并进行通信。这种模型是许多网络应用的基础,如网页浏览器与服务器之间的通信、即时通讯软件等。

一般来说,Socket通信的基本流程如下:

服务器程序创建一个Socket并绑定到一个特定的端口,然后开始监听客户端的连接请求。
客户端程序创建一个Socket,并尝试连接到服务器的IP地址和端口。 一旦连接建立,数据可以在服务器和客户端之间进行双向传输。

.NET高级面试指南专题七【Socket&WebSocket】_第2张图片
Socket其实并不是一个协议,而是为了方便使用TCP或UDP而抽象出来的一层,是位于应用层和传输控制层之间的一组接口。

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

当两台主机通信时,必须通过Socket连接,Socket则利用TCP/IP协议建立TCP连接。TCP连接则更依靠于底层的IP协议,IP协议的连接则依赖于链路层等更低层次。

.NET高级面试指南专题七【Socket&WebSocket】_第3张图片
一个简单的C# Socket代码示例
展示了一个基本的服务器和客户端通信。这个例子使用了同步的阻塞方式,真实的应用中可能需要考虑使用异步编程以提高性能。

服务器端代码:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

class Server
{
    static void Main()
    {
        TcpListener server = null;

        try
        {
            // 设置IP地址和端口
            IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
            int port = 12345;

            // 创建TcpListener对象
            server = new TcpListener(ipAddress, port);

            // 开始监听
            server.Start();
            Console.WriteLine("等待客户端连接...");

            // 接受连接请求
            TcpClient client = server.AcceptTcpClient();
            Console.WriteLine("客户端已连接");

            // 获取网络流
            NetworkStream stream = client.GetStream();

            // 发送和接收数据
            byte[] data = new byte[256];
            int bytesRead;

            while ((bytesRead = stream.Read(data, 0, data.Length)) != 0)
            {
                string message = Encoding.ASCII.GetString(data, 0, bytesRead);
                Console.WriteLine($"接收到消息: {message}");

                // 回复客户端
                string response = "服务器已收到消息";
                byte[] responseData = Encoding.ASCII.GetBytes(response);
                stream.Write(responseData, 0, responseData.Length);
            }

            // 关闭连接
            client.Close();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"发生异常: {ex.Message}");
        }
        finally
        {
            // 停止监听
            server.Stop();
        }
    }
}

客户端代码:

using System;
using System.Net.Sockets;
using System.Text;

class Client
{
    static void Main()
    {
        try
        {
            // 设置服务器的IP地址和端口
            TcpClient client = new TcpClient("127.0.0.1", 12345);
            Console.WriteLine("连接到服务器");

            // 获取网络流
            NetworkStream stream = client.GetStream();

            // 发送数据
            string message = "Hello, server!";
            byte[] data = Encoding.ASCII.GetBytes(message);
            stream.Write(data, 0, data.Length);
            Console.WriteLine($"发送消息: {message}");

            // 接收服务器的响应
            data = new byte[256];
            int bytesRead = stream.Read(data, 0, data.Length);
            string response = Encoding.ASCII.GetString(data, 0, bytesRead);
            Console.WriteLine($"服务器响应: {response}");

            // 关闭连接
            client.Close();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"发生异常: {ex.Message}");
        }
    }
}

WebSocket

WebSocket是一种在单个TCP连接上进行全双工通信的通信协议,它使得客户端和服务器之间可以实时地进行双向数据传输。WebSocket通常用于实现实时的Web应用程序,如在线聊天、实时协作编辑和实时通知等。

WebSocket出现的原因,哪些因素触发产生WebSocket

以前网站上的即时通讯是很常见的,比如网页的QQ,聊天系统等。按照以往的技术能力通常是采用轮询、Comet技术解决。
HTTP协议是非持久化的,单向的网络协议,在建立连接后只允许浏览器向服务器发出请求后,服务器才能返回相应的数据。当需要即时通讯时,通过轮询在特定的时间间隔(如1秒),由浏览器向服务器发送Request请求,然后将最新的数据返回给浏览器。这样的方法最明显的缺点就是需要不断的发送请求,而且通常HTTP
request的Header是非常长的,为了传输一个很小的数据 需要付出巨大的代价,是很不合算的,占用了很多的宽带。

下面是WebSocket的一些关键特点和工作原理:

特点:

  • 全双工通信: WebSocket允许客户端和服务器之间进行双向实时通信,而不需要每次通信都创建新的连接。

  • 低延迟: 由于使用了单个TCP连接,WebSocket相对于一些传统的轮询技术来说,具有更低的延迟。

  • 轻量级: WebSocket协议相对简单,数据帧的头部开销小,降低了通信的开销。

  • 协议标准化: WebSocket协议已经被标准化,有相关的RFC文档(RFC 6455),这使得不同平台和语言之间能够进行兼容性的实现。

工作原理:

  • 握手阶段: 在建立WebSocket连接之前,客户端首先通过HTTP发送一个特殊的请求,包含WebSocket版本信息和一些其他头部信息。服务器在接收到这个请求后,如果支持WebSocket,就会响应一个类似的包含协议升级请求的HTTP响应。

  • 建立连接: 客户端和服务器之间的握手成功后,连接从HTTP协议升级到WebSocket协议。此时,客户端和服务器可以在同一个TCP连接上发送和接收WebSocket数据帧。

  • 双向数据传输: 一旦连接建立,客户端和服务器可以在任何时候通过发送WebSocket数据帧来实时交换信息。数据帧可以是文本、二进制等。

  • 关闭连接: 当通信结束时,任何一方都可以发送一个特殊的帧(Close Frame)来关闭WebSocket连接。另一方接收到该帧后也发送一个带有关闭码的响应帧,然后双方都关闭连接。

WebSocket在实时性要求较高的应用场景中非常有用,因为它提供了一种高效、低延迟的双向通信方式,适用于Web应用中需要实时性和即时通信的各种情境。

在C#中,可以使用.NET Core的System.Net.WebSockets库来实现WebSocket通信。以下是一个简单的C# WebSocket服务器和客户端的代码示例:
服务器端代码:

using System;
using System.Net;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

class WebSocketServer
{
    public static async Task StartServerAsync(string ipAddress, int port)
    {
        HttpListener listener = new HttpListener();
        listener.Prefixes.Add($"http://{ipAddress}:{port}/");
        listener.Start();
        Console.WriteLine($"WebSocket server listening on http://{ipAddress}:{port}/");

        while (true)
        {
            HttpListenerContext context = await listener.GetContextAsync();
            if (context.Request.IsWebSocketRequest)
            {
                ProcessWebSocketRequest(context);
            }
            else
            {
                context.Response.StatusCode = 400;
                context.Response.Close();
            }
        }
    }

    private static async void ProcessWebSocketRequest(HttpListenerContext context)
    {
        WebSocket webSocket = await context.AcceptWebSocketAsync(null);

        Console.WriteLine("WebSocket connection established");

        byte[] buffer = new byte[1024];
        WebSocketReceiveResult result;

        do
        {
            result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);

            if (result.MessageType == WebSocketMessageType.Text)
            {
                string receivedMessage = Encoding.UTF8.GetString(buffer, 0, result.Count);
                Console.WriteLine($"Received message: {receivedMessage}");

                // Echo the message back to the client
                await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), WebSocketMessageType.Text, true, CancellationToken.None);
            }
        }
        while (!result.CloseStatus.HasValue);

        await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
        Console.WriteLine("WebSocket connection closed");
    }

    static void Main()
    {
        StartServerAsync("127.0.0.1", 8080).Wait();
    }
}

客户端代码:

using System;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

class WebSocketClient
{
    public static async Task StartClientAsync(string serverUri)
    {
        using (ClientWebSocket webSocket = new ClientWebSocket())
        {
            await webSocket.ConnectAsync(new Uri(serverUri), CancellationToken.None);
            Console.WriteLine("Connected to WebSocket server");

            Task receiveTask = ReceiveMessageAsync(webSocket);

            // Sending a sample message
            string message = "Hello, server!";
            byte[] messageBytes = Encoding.UTF8.GetBytes(message);
            await webSocket.SendAsync(new ArraySegment<byte>(messageBytes), WebSocketMessageType.Text, true, CancellationToken.None);

            // Keep the application running
            Console.ReadLine();
        }
    }

    private static async Task ReceiveMessageAsync(ClientWebSocket webSocket)
    {
        byte[] buffer = new byte[1024];

        while (webSocket.State == WebSocketState.Open)
        {
            WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);

            if (result.MessageType == WebSocketMessageType.Text)
            {
                string receivedMessage = Encoding.UTF8.GetString(buffer, 0, result.Count);
                Console.WriteLine($"Received message: {receivedMessage}");
            }
        }
    }

    static void Main()
    {
        StartClientAsync("ws://127.0.0.1:8080").Wait();
    }
}

WebSocket 和Socket的区别
WebSocket和Socket是两种不同的通信机制,有一些关键的区别:

  1. 协议层次: WebSocket: 是一种在应用层实现的协议,建立在HTTP协议之上。它通过HTTP协议的握手阶段升级到WebSocket协议,实现了全双工通信。
    Socket: 是一种通用的套接字编程接口,可以在应用层之下的传输层(通常是TCP或UDP)直接进行数据交换。
  2. 双向通信: WebSocket: 支持全双工通信,允许客户端和服务器之间同时进行数据的发送和接收。 Socket: 也支持全双工通信,但需要在编程中明确实现。
  3. 协议解析: WebSocket: 使用标准的WebSocket协议,帧格式和握手机制都被协议规范明确定义。 Socket: 在传输层(TCP或UDP)上,应用程序需要自行定义通信协议和数据格式。
  4. 通信开销: WebSocket: 握手阶段的开销相对较大,但一旦建立连接,数据帧的头部相对较小,通信开销较低。 Socket: 不需要握手,但需要应用程序自行管理通信协议,可能会有较大的通信开销。
  5. 应用场景: WebSocket: 适用于Web应用中需要实时性和即时通信的场景,如在线聊天、实时协作编辑等。 Socket: 更通用,适用于各种应用场景,包括文件传输、远程控制等。
  6. 跨域支持:
    WebSocket: 由于WebSocket协议是在HTTP协议上升级而来,因此支持跨域通信。
    Socket: 在一些环境中可能需要专门的处理来支持跨域通信。

总体而言,WebSocket是一种高层次的通信协议,针对实时性和双向通信进行了优化,适用于Web应用中。Socket是一种通用的套接字编程接口,可以灵活地实现各种通信需求,但需要应用程序自行管理通信协议。选择WebSocket还是Socket取决于具体的应用需求和环境。

你可能感兴趣的:(.NET高级面试指南,.net,面试,websocket)