在本文中,我们展示了如何在C#中使用套接字。
网络协议
TCP/IP是设备用来通过Internet和大多数本地网络进行通信的一套协议。TCP更可靠,具有广泛的错误检查,并且需要更多资源。它由HTTP、SMTP或FTP等服务使用。UDP的可靠性低得多,错误检查有限,并且需要的资源较少。它被VoIP等服务使用。
套接字
在编程中,套接字是网络上运行的两个程序之间通信的端点。在.NET中,Socket类为网络通信提供了一组丰富的方法和属性。它允许我们执行同步和异步数据传输。
C#UDP套接字示例
UDP是一种通过网络传输独立数据包的通信协议,不保证到达且不保证交付顺序。使用UDP的一项服务是每日报价(QOTD)。
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#套接字HTTPHEAD请求
HEAD请求是没有消息正文的HTTPGET请求。请求/响应的标头包含元数据,例如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字符是通信过程的必需部分。RFC7231文档中描述了详细信息。
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#套接字HTTPGET请求
HTTPGET方法请求指定资源的表示。使用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";
我们向套接字写入一个简单的GET请求。
do
{
n = socket.Receive(bRec, bRec.Length, 0);
sb.Append(Encoding.ASCII.GetString(bRec, 0, n));
}
while (n > 0);
由于我们无法确定响应的大小,因此我们使用do/while循环来分块读取响应。
在本文中,我们使用了C#中的套接字。
列出所有C#教程。
