C# TCP socket發送大數據包時,接收端和發送端數據不一致 服務端接收Receive不完全
服務器端:
public static ManualResetEvent allDone = new ManualResetEvent(false); IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), port); Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); listener.Bind(localEndPoint); listener.Listen(30); while (true) { allDone.Reset(); listener.BeginAccept(new AsyncCallback(AcceptCallback), listener); allDone.WaitOne(); }
public static void AcceptCallback(IAsyncResult ar) { try { if (IsListening) { allDone.Set(); Socket listener = (Socket)ar.AsyncState; Socket handler = listener.EndAccept(ar); StateObject state = new StateObject(); state.workSocket = handler; handler.BeginReceive(state.headbuffer, 0, StateObject.HeadBufferSize, 0, new AsyncCallback(ReceiveHead), state); } } catch (System.Exception ex) { log.ErrorFormat("AcceptCallback異常,原因:{0}", ex.Message); } } private static void ReceiveHead(IAsyncResult ar) { try { StateObject state = (StateObject)ar.AsyncState; Socket handler = state.workSocket; int bytesRead = handler.EndReceive(ar); uint length = ByteTouint(state.headbuffer, 3, 4); state.length = (int)length - state.headbuffer.Length; state.bodybuffer = new byte[length - state.headbuffer.Length]; handler.BeginReceive(state.bodybuffer, 0, state.bodybuffer.Length, 0, new AsyncCallback(ReadCallback), state); } catch (System.Exception ex) { log.ErrorFormat("ReceiveHead異常,原因:{0}", ex.Message + ex.StackTrace); } }
public static void ReadCallback(IAsyncResult ar) { StateObject state = (StateObject)ar.AsyncState; Socket handler = state.workSocket; int bytesRead = handler.EndReceive(ar); //接收的字節在state.bodybuffer里,下面開始處理 }
已知接收長度的話可以把ReceiveHead函數去掉,直接進入ReadCallback里。
加入ReceiveHead是因為協議一般在開頭幾個固定的字節里有后面數據包的長度,所以先接收頭,再根據解析出的數據包長度接收后面的。
StateObject定義如下,可以不要headbuffer HeadBufferSize
public class StateObject { public Socket workSocket = null; public const int HeadBufferSize = 7; public byte[] headbuffer = new byte[HeadBufferSize]; public byte[] bodybuffer; public int length; }
客戶端發送數據 C# 的TCP Socket (同步方式)