在 C# 中使用套接字






4.73/5 (59投票s)
本文展示了如何使用套接字发送消息
引言
如今,套接字的使用越来越广泛。它们提供了一种简单的方法来交换网络数据。例如,它用于在用户之间交换消息。您可以更进一步地传输文件,玩“分布式”游戏以及多个程序之间的通信。由于其强大的功能,套接字正成为开发人员必须学习的技术。
由于套接字基于客户端/服务器架构,因此此应用程序由服务器和客户端组成。服务器将保留一个端口号。然后它将监听任何即将到来的客户端。然后客户端将尝试连接到服务器。连接成功后,就可以交换文本消息了。完成后,连接将关闭。
使用代码
要在 .NET 应用程序中使用套接字,我们必须添加以下using
语句
using System.Net;
using System.Net.Sockets;
现在我们可以创建一个套接字对象
Socket sListener;
服务器编程
让我们创建一个点击事件,该事件将使创建的套接字能够设置其IpEndPoint
和协议类型。
但在那之前,套接字需要权限才能工作,因为它将使用一个封闭的端口号。将出现一个窗口,要求允许发送数据。
permission = new SocketPermission(NetworkAccess.Accept,
TransportType.Tcp, "", SocketPermission.AllPorts);
由于套接字使用网络传输数据,因此它使用协议。在这种情况下最广为人知的是 UDP(快速但不可靠)和 TCP(可靠但不快)。发送消息时建议使用可靠性。这就是我使用 TCP 的原因。
sListener = new Socket(ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
套接字需要一个地址。它是IpEndPoint
类型。每个套接字都通过 IP 地址(用于定位主机机器)和端口号(用于识别机器内部哪个程序正在使用套接字)来标识。
IPHostEntry ipHost = Dns.GetHostEntry("");
IPAddress ipAddr = ipHost.AddressList[0];
ipEndPoint = new IPEndPoint(ipAddr, 4510);
现在我们将我们的套接字与IpEndPoint
关联
sListener.Bind(ipEndPoint);
为了使我们的套接字可以使用,让我们开始监听所选端口号 (4510)。您可以选择其他端口号。但是客户端必须知道这一点。监听将通过此按钮的事件处理。
将套接字置于侦听状态,并指定可以连接到它的客户端套接字数量。
sListener.Listen(10);
服务器将开始异步操作以接受尝试。套接字的强大功能之一是使用异步编程模型。由于它,我们的程序可以在套接字执行操作时继续运行。
AsyncCallback aCallback = new AsyncCallback(AcceptCallback);
sListener.BeginAccept(aCallback, sListener);
如果客户端有任何连接尝试,则将执行以下代码
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
要开始异步接收数据,我们需要一个Byte
类型的数组用于接收到的数据、缓冲区中的零基位置以及要接收的字节数。
handler.BeginReceive(buffer, 0, buffer.Length,
SocketFlags.None, new AsyncCallback(ReceiveCallback), obj);
如果客户端发送任何消息,服务器将尝试获取它。由于套接字以二进制类型发送数据,因此需要将其转换为字符串类型。还需要知道的是,服务器甚至客户端都不知道消息的长度或侦听所有消息所需的时间。这就是为什么我们使用特殊的字符串“<Client Quit>”放在消息的末尾来表示文本消息在此处结束。要接收数据,调用BeginReceive
byte[] buffernew = new byte[1024];
obj[0] = buffernew;
obj[1] = handler;
handler.BeginReceive(buffernew, 0, buffernew.Length,
SocketFlags.None, new AsyncCallback(ReceiveCallback), obj);
接收客户端消息后,服务器可能想要回复。但它必须将字符串消息str
转换为字节数据,因为套接字只处理字节。
byte[] byteData = Encoding.Unicode.GetBytes(str);
服务器现在将异步地向已连接的套接字发送数据
handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
使用异步编程模型构建此示例时,不会出现应用程序或界面阻塞的风险。它看起来像我们正在使用多个线程。
编写代码后,您希望通过用户界面处理不同的方法。因此,您可能会有这样的 UI
客户端编程
客户端将尝试连接到服务器。但它必须知道服务器的地址。
在创建SocketPermission
用于套接字访问限制并使用匹配的IpEndPoint
创建套接字后,我们必须建立与远程服务器主机的连接
senderSock.Connect(ipEndPoint);
在这里,我们需要注意的是,创建的IpEndPoint
不会用于标识客户端。但它将用于标识服务器套接字。
为了发送消息,客户端添加“<Client Quit>”来标记消息的结尾,并且必须像服务器一样将文本消息转换为二进制格式。之后,套接字将通过调用Send
方法(该方法将二进制消息作为参数)来发送消息。
byte[] msg = Encoding.Unicode.GetBytes(theMessageToSend + "<Client Quit>");
int bytesSend = senderSock.Send(msg);
为了接收来自服务器的数据,它将字节数组转换为字符串,并继续读取数据,直到数据不可用为止。
String theMessageToReceive = Encoding.Unicode.GetString(bytes, 0, bytesRec);
while (senderSock.Available > 0)
{
bytesRec = senderSock.Receive(bytes);
theMessageToReceive += Encoding.Unicode.GetString(bytes, 0, bytesRec);
}
要关闭连接,我们应该使用Socket.Shutdown(SocketShutdown.Both)
和Socket.Close()
。
将事件与按钮点击匹配后,客户端用户界面将如下所示
结论
我在这里提供了一个示例应用程序,易于使用,并且易于集成到您的项目中。因此,给自己一个机会尝试利用套接字的功能来构建更丰富、更强大的软件。