public class TcpClient { public event Action<byte[]> OnReveive = delegate { }; private ManualResetEvent sendDone = new ManualResetEvent(false); private ManualResetEvent receiveDone = new ManualResetEvent(false); /// <summary> /// 有可能涉及到返回数据一个 byte[] 装不下的情况,所以设计了一个 List 来拼数据 /// </summary> List<byte[]> bufferList = new List<byte[]>(); int bufferLength = 1024; Socket _ClientSocket; IPEndPoint _EndPoint; public TcpClient(string ipAddress, int port) { _ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPAddress ip = IPAddress.Parse(ipAddress); _EndPoint = new IPEndPoint(ip, port); } public bool Connect() { _ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); _ClientSocket.Connect(_EndPoint); return _ClientSocket.Connected; } public bool Close() { // 关闭Socket连接 _ClientSocket.Shutdown(SocketShutdown.Both); _ClientSocket.Close(); return !_ClientSocket.Connected; } public TcpClient(byte[] ipAddress, int port) { IPAddress ip = new IPAddress(ipAddress); _EndPoint = new IPEndPoint(ip, port); } /// <summary> /// 发送信息 /// </summary> /// <remarks> /// 无法在send时,同步接收数据返回, 调用 Receive 并不会马上向 buff 中填数据, /// 调用 receive 后马上返回 buffer,数据是不正确的<br/> /// 虽然用了异步的发送和接收,但是由于加锁的缘故,这是个同步方法<br/> /// 不枷锁的receive,数据可能会乱序 /// </remarks> /// <param name="data"></param> public void Send(byte[] data) { if (!_ClientSocket.Connected) Connect(); _ClientSocket.BeginSend(data, 0, data.Length, 0, new AsyncCallback(SendCallback), _ClientSocket); sendDone.WaitOne(); // 接收数据 byte[] receiveBuffer = new byte[bufferLength]; bufferList.Add(receiveBuffer); _ClientSocket.BeginReceive(bufferList.Last(), 0, bufferList.Last().Length, 0, new AsyncCallback(ReceiveCallback), _ClientSocket); receiveDone.WaitOne(); } /// <summary> /// 发送的回调 /// </summary> /// <remarks> /// 这里可以用来处理发送信息,发送失败可以在这里重新发送 /// </remarks> /// <param name="ar"></param> private void SendCallback(IAsyncResult ar) { try { Socket clientSocket = (Socket)ar.AsyncState; int bytesSent = clientSocket.EndSend(ar); sendDone.Set(); } catch (Exception ex) { throw; } } /// <summary> /// receive的回调 /// </summary> /// <param name="ar"></param> private void ReceiveCallback(IAsyncResult ar) { try { Socket? clientSocket =ar.AsyncState as Socket; int bytesReceiveCount = clientSocket?.EndReceive(ar) ?? 0; if (bytesReceiveCount < bufferLength) { // bytesReceiveCount 小于 buffer 的长度,说明数据已经完整获取 // 把最后一个buffer 按 bytesReceiveCount 裁剪一下,丢弃多余的部分 // 再把 bufferList 里所有的 buffer 拼接一下,通过回调函数返回,然后放开接收锁 bufferList[bufferList.Count - 1] = bufferList.Last().Take(bytesReceiveCount).ToArray(); OnReveive?.Invoke(bufferList.SelectMany(b => b).ToArray()); bufferList.Clear(); receiveDone.Set(); } else { // bytesReceiveCount 等于 buffer 长度,有可能有数据未获取 // 再重新receive 一遍,获取后面的 buffer byte[] newBuffer = new byte[bufferLength]; bufferList.Add(newBuffer); clientSocket?.BeginReceive(bufferList.Last(), 0, bufferList.Last().Length, 0, new AsyncCallback(ReceiveCallback), clientSocket); } } catch (Exception ex) { throw; } } }
标签:TcpClient,Socket,bufferList,new,byte,public,ClientSocket From: https://www.cnblogs.com/cchong005/p/17532468.html