C# 套接字
最后修改于 2023 年 7 月 5 日
在本文中,我们将展示如何在 C# 中使用 Socket。
网络协议
TCP/IP 是一组协议,设备使用它通过互联网和大多数本地网络进行通信。TCP 更加可靠,具有广泛的错误检查,并且需要更多资源。它被 HTTP、SMTP 或 FTP 等服务使用。UDP 的可靠性要差得多,错误检查有限,并且需要的资源更少。它被 VoIP 等服务使用。
Socket(套接字)
在编程中,套接字(Socket) 是在网络上运行的两个程序之间通信的端点。在 .NET 中,Socket
类为网络通信提供了一组丰富的方法和属性。它允许我们执行同步和异步数据传输。
C# UDP Socket 示例
UDP 是一种通信协议,它在网络上传输独立的包,不保证到达,也不保证传递顺序。Quote of the Day (QOTD) 是使用 UDP 的一项服务。
using System.Text; using System.Net; using System.Net.Sockets; string server = "djxmmx.net"; int port = 17; byte[] data = new byte[0]; IPHostEntry hostEntry = Dns.GetHostEntry(server); var ipe = new IPEndPoint(hostEntry.AddressList[0], port); using var socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp); socket.ReceiveTimeout = 5000; socket.SendTimeout = 2000; socket.SendTo(data, ipe); byte[] data2 = new byte[1024]; EndPoint remote = (EndPoint)ipe; int n = socket.ReceiveFrom(data2, ref remote); Console.WriteLine($"Message size: {n}"); Console.WriteLine($"Messaged received from: {remote}"); Console.WriteLine(Encoding.ASCII.GetString(data2, 0, n));
该程序创建一个客户端程序,连接到 QOTD 服务。
string server = "djxmmx.net"; int port = 17;
这是可以找到 QOTD 服务的服务器和端口。请注意,此类服务通常是短期的。
byte[] data = new byte[0];
我们向服务器发送一条空消息。
IPHostEntry hostEntry = Dns.GetHostEntry(server);
Dns.GetHostEntry
将主机名或 IP 地址解析为 IPHostEntry 实例。 这是用于 Internet 主机地址信息的 .NET 容器类。
using var socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp);
创建一个 Socket
。 我们传递寻址方案、套接字类型和协议类型。
socket.ReceiveTimeout = 5000; socket.SendTimeout = 2000;
我们设置接收和发送数据的超时时间。
socket.SendTo(data, ipe);
我们使用 SendTo
将数据(在本例中为空)发送到终结点。
byte[] data2 = new byte[1024];
在这里,我们将存储响应消息。
int n = socket.ReceiveFrom(data2, ref remote);
ReceiveFrom
方法将数据报接收到数据缓冲区中并存储终结点。 它返回接收到的字节数。
Console.WriteLine($"Message size: {n}"); Console.WriteLine($"Messaged received from: {remote}"); Console.WriteLine(Encoding.ASCII.GetString(data2, 0, n));
我们打印消息大小、删除地址以及接收到的数据。
$ dotnet run Message size: 73 Messaged received from: [2001:470:e312:10::10]:17 "Take what you can, give nothing back..." - Pirates Of The Caribbean
C# Socket HTTP HEAD 请求
HEAD 请求是一种 HTTP GET 请求,但不包含消息正文。请求/响应的头部包含元数据,例如 HTTP 协议版本或内容类型。
using System.Text; using System.Net; using System.Net.Sockets; string server = "webcode.me"; int port = 80; var request = "HEAD / HTTP/1.0\r\n\r\n"; byte[] bReq = Encoding.ASCII.GetBytes(request); byte[] bRec = new byte[8192]; IPHostEntry hostEntry = Dns.GetHostEntry(server); var ipe = new IPEndPoint(hostEntry.AddressList[0], port); using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.Connect(ipe); if (socket.Connected) { Console.WriteLine("Connection established"); } else { Console.WriteLine("Connection failed"); return; } socket.Send(bReq, bReq.Length, 0); int n = socket.Receive(bRec, bRec.Length, 0); Console.WriteLine(Encoding.ASCII.GetString(bRec, 0, n));
在代码示例中,我们向 webcode.me 发送 HEAD 请求。
string server = "webcode.me"; int port = 80;
这是服务器名称和端口号。
string request = "HEAD / HTTP/1.0\r\n\r\n";
head 请求通过 HEAD
命令发出,后跟资源 URL 和 HTTP 协议版本。 请注意,\r\n
字符是通信过程的强制组成部分。 详细信息在 RFC 7231 文档中进行了描述。
using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
HTTP 协议(HTTP/0.9 到 HTTP/2)是基于 TCP 的。
if (socket.Connected)
我们可以通过 Connected
属性检查是否已成功连接。
socket.Send(bReq, bReq.Length, 0);
我们使用 Send
发送数据。
int n = socket.Receive(bRec, bRec.Length, 0); Console.WriteLine(Encoding.ASCII.GetString(bRec, 0, n));
我们接收并打印标头数据。
$ dotnet run Connection established HTTP/1.1 200 OK Server: nginx/1.6.2 Date: Wed, 21 Sep 2022 17:43:39 GMT Content-Type: text/html Content-Length: 394 Last-Modified: Sun, 23 Jan 2022 10:39:25 GMT Connection: close ETag: "61ed305d-18a" Accept-Ranges: bytes
C# Socket HTTP GET 请求
HTTP GET 方法请求指定资源的表示。使用 GET 的请求应该只检索数据。
using System.Text; using System.Net; using System.Net.Sockets; string server = "webcode.me"; int port = 80; string request = $"GET / HTTP/1.1\r\nHost: {server} \r\nConnection: Close\r\n\r\n"; Byte[] bReq = Encoding.ASCII.GetBytes(request); Byte[] bRec = new Byte[1024]; IPHostEntry hostEntry = Dns.GetHostEntry(server); var ipe = new IPEndPoint(hostEntry.AddressList[0], port); using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.Connect(ipe); if (socket.Connected) { Console.WriteLine("Connection established"); } else { Console.WriteLine("Connection failed"); return; } socket.Send(bReq, bReq.Length, 0); int n = 0; var sb = new StringBuilder(); do { n = socket.Receive(bRec, bRec.Length, 0); sb.Append(Encoding.ASCII.GetString(bRec, 0, n)); } while (n > 0); Console.WriteLine(sb);
该示例使用 GET 请求读取 webcode.me 的主页。
string request = $"GET / HTTP/1.1\r\nHost: {server} \r\nConnection: Close\r\n\r\n";
我们向 Socket 写入了一个简单的 GET 请求。
do { n = socket.Receive(bRec, bRec.Length, 0); sb.Append(Encoding.ASCII.GetString(bRec, 0, n)); } while (n > 0);
由于我们无法确定响应的大小,因此我们使用 do/while
循环以块的形式读取响应。
来源
在本文中,我们介绍了如何在 C# 中使用 Socket。
作者
列出所有 C# 教程。