如何在RAD Studio中使用System.Net.Socket的TSocket库编写跨平台异步套接字服务器
如何在RAD Studio中使用System.Net.Socket的TSocket库编写跨平台异步套接字服务器
我之前在RAD Studio里折腾System.Net.Socket的TSocket库,想写个跨平台的异步套接字服务器,结果踩了个小坑——RAD Studio自带的文档大部分时候都挺靠谱的,各种场景的例子也全,但偏偏在TSocket做服务器端的实现上,只给了个干巴巴的步骤框架,根本没说具体怎么把这些步骤串起来、调用对应的方法。
官方文档里是这么写的:
要将套接字用作服务器套接字:
- 将套接字绑定到本地适配器。
- 配置套接字以开始监听传入连接。
- 接受传入连接。
- 与远程套接字交换数据:接收来自远程套接字的数据。
- 向远程套接字发送数据。
- 关闭套接字。
就这几句,谁看了不懵?具体怎么调用TSocket的方法?这些步骤之间怎么衔接?我折腾了好一阵,才理清了单连接的实现方式,下面就给大家唠唠。
单连接解决方案
单连接的实现其实就是把官方给的步骤,对应到TSocket的具体方法上,一步步衔接起来:
1. 初始化并绑定套接字
首先得创建TSocket实例,指定地址族、套接字类型和协议,然后绑定到本地的IP和端口上。比如:
var ServerSocket: TSocket; LocalAddr: TIPEndPoint; begin // 创建TCP套接字实例 ServerSocket := TSocket.Create(AF_INET, SOCK_STREAM, IPPROTO_TCP); // 绑定到本地所有网卡的12345端口 LocalAddr := TIPEndPoint.Create('0.0.0.0', 12345); try ServerSocket.Bind(LocalAddr); except // 处理绑定异常,比如端口被占用 ServerSocket.DisposeOf; raise; end; end;
2. 开始监听连接
绑定成功后,调用Listen()方法设置等待队列长度,开始监听客户端的连接请求:
// 设置等待队列长度为5,最多允许5个等待连接的客户端 ServerSocket.Listen(5);
3. 接受客户端连接
接下来调用Accept()方法(异步场景可以用AcceptAsync())来获取客户端的套接字实例,拿到之后就可以和客户端收发数据了:
var ClientSocket: TSocket; RemoteEndPoint: TIPEndPoint; begin RemoteEndPoint := TIPEndPoint.Create; try // 同步接受连接,异步场景建议用AcceptAsync搭配回调 ClientSocket := ServerSocket.Accept(RemoteEndPoint); ShowMessage('客户端已连接:' + RemoteEndPoint.ToString); finally RemoteEndPoint.DisposeOf; end; end;
4. 收发数据与关闭连接
拿到客户端套接字后,就可以用Receive()/ReceiveAsync()接收数据,用Send()/SendAsync()发送数据,完成通信后记得关闭套接字释放资源:
var Buffer: array[0..1023] of Byte; BytesReceived: Integer; Response: string; begin try // 接收客户端数据 BytesReceived := ClientSocket.Receive(@Buffer, Length(Buffer), 0); if BytesReceived > 0 then begin Response := '收到你的消息啦:' + TEncoding.UTF8.GetString(Buffer, 0, BytesReceived); // 发送响应给客户端 ClientSocket.Send(TEncoding.UTF8.GetBytes(Response), Length(Response), 0); end; finally // 关闭客户端套接字 ClientSocket.Shutdown(TSocketShutdown.Both); ClientSocket.DisposeOf; // 关闭服务器套接字(单连接场景下通信完成后关闭,多连接则保持监听) ServerSocket.Shutdown(TSocketShutdown.Both); ServerSocket.DisposeOf; end; end;
单连接的核心流程就是这样,异步场景下只需要把同步方法换成对应的Async方法,搭配回调或者TTask来处理后续逻辑就行,整体思路是一致的。
备注:内容来源于stack exchange,提问作者Andre Van Zuydam
相关产品推荐
相关产品推荐

