C# Socket可否实现类似串口DataReceived的数据接收触发事件
C# Socket 实现自动触发数据接收事件的方案
可以实现,Socket本身没有内置类似串口的DataReceived事件,但我们可以通过封装异步接收逻辑+自定义事件的方式完全复刻串口组件的使用体验。
实现步骤
1. 定义自定义事件参数类
用来传递接收到的数据、远端地址等信息,和串口的SerialDataReceivedEventArgs作用一致:
public class SocketDataReceivedEventArgs : EventArgs { /// <summary> /// 本次接收到的字节数据 /// </summary> public byte[] ReceivedData { get; } /// <summary> /// 发送数据的远端节点地址 /// </summary> public EndPoint RemoteEndPoint { get; } public SocketDataReceivedEventArgs(byte[] data, EndPoint remoteEndPoint) { ReceivedData = data; RemoteEndPoint = remoteEndPoint; } }
2. 封装Socket监听类,内置异步接收和事件触发逻辑
public class SocketListenerWrapper { private readonly Socket _socket; private readonly byte[] _receiveBuffer; /// <summary> /// 数据接收事件,有新数据到达时自动触发 /// </summary> public event EventHandler<SocketDataReceivedEventArgs> DataReceived; /// <summary> /// 构造函数,传入已经完成连接的Socket实例 /// </summary> /// <param name="socket">已连接的Socket</param> /// <param name="bufferSize">接收缓冲区大小,默认1024字节</param> public SocketListenerWrapper(Socket socket, int bufferSize = 1024) { _socket = socket ?? throw new ArgumentNullException(nameof(socket)); _receiveBuffer = new byte[bufferSize]; // 自动启动异步监听 StartAsyncReceive(); } private void StartAsyncReceive() { // 启动异步接收,不会阻塞主线程 _socket.BeginReceive( buffer: _receiveBuffer, offset: 0, size: _receiveBuffer.Length, socketFlags: SocketFlags.None, callback: ReceiveAsyncCallback, state: null); } private void ReceiveAsyncCallback(IAsyncResult ar) { try { int receivedLength = _socket.EndReceive(ar); if (receivedLength <= 0) { // 对端主动断开连接,可自行扩展断开事件通知 return; } // 拷贝本次接收到的有效数据 byte[] validData = new byte[receivedLength]; Array.Copy(_receiveBuffer, validData, receivedLength); // 触发数据接收事件 OnDataReceived(new SocketDataReceivedEventArgs(validData, _socket.RemoteEndPoint)); // 重启下一次异步接收,实现持续监听 StartAsyncReceive(); } catch (SocketException) { // 连接异常断开,可自行扩展异常事件通知 } } protected virtual void OnDataReceived(SocketDataReceivedEventArgs e) { DataReceived?.Invoke(this, e); } }
3. 调用方式(和串口组件用法完全一致)
// 示例:先创建并连接Socket var clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); clientSocket.Connect("127.0.0.1", 8888); // 实例化封装类 var socketWrapper = new SocketListenerWrapper(clientSocket); // 订阅数据接收事件 socketWrapper.DataReceived += SocketWrapper_DataReceived; // 事件处理方法,有新数据时自动执行 private void SocketWrapper_DataReceived(object sender, SocketDataReceivedEventArgs e) { string content = Encoding.UTF8.GetString(e.ReceivedData); Console.WriteLine($"收到来自[{e.RemoteEndPoint}]的数据:{content}"); }
注意事项
- 事件默认在Socket异步回调的线程触发,和串口
DataReceived行为一致,如果是在WinForm/WPF等UI程序中操作界面控件,需要主动调度到UI线程执行。 - 可以根据业务需求在封装类中补充粘包拆包、异常通知、主动关闭连接等扩展逻辑。
- UDP场景下也可以用相同的思路封装
BeginReceiveFrom异步回调逻辑,实现UDP数据接收的自动事件通知。
内容的提问来源于stack exchange,提问作者Andys
相关产品推荐
相关产品推荐

