我正在使用C#套接字類通過短連接向/從我們的服務器發送/接收TCP消息。僞代碼(排除一些錯誤的容錯邏輯來說明)如下。當TCP包大於MTU時,C#Socket.Receive()出現故障
class MyTCPClient {
private Socket mSocket;
MyTCPClient() {
mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
void Connect(ipEndpoint, sendTimeOut, receiveTimeOut) {
mSocket.Connect(ipEndpoint);
mSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, sendTimeOut);
mSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, receiveTimeOut);
}
void Send(msg) {
mSocket.Send(msg);
}
void Receive(data) {
ByteStreamWriter bsw = new ByteStreamWriter();
int totalLen = 0;
while (true) {
byte[] temp = new byte[1024];
int len = mSocket.Receive(temp, SocketFlags.None);
System.Threading.Thread.Sleep(50); // This is the weirdest part
if (len <= 0) break;
totalLen += len;
bsw.WriteBytes(temp);
}
byte[] buff = bsw.GetBuffer();
data = new byte[totalLen];
Array.Copy(buff, 0, data, 0, totalLen);
}
~MyTCPClient() {
mSocket.Close();
}
}
我用這個類從我們的服務器幾次通過短的連接請求相同的消息,並且下面的事情發生(僅當消息大小是大於一個MTU - 1500個字節)。如果「睡眠(50)」被註釋掉,大部分時間(90%)我收到錯誤的「數據」,具體來說,「totalLen」是正確的,但是「數據」錯了。
另外,如果我用mSocket.Available代替Socket.Receive()的返回值來判斷while循環,我總是會得到正確的數據和數據長度...
是什麼*錯誤的數據*是什麼意思?你得到很多零?或垃圾?那個ByteStreamWriter從哪裏來?那是一個BinaryWriter嗎? – rene
您不太瞭解TCP如何運作。 TCP將消息分解爲最大大小爲1500字節的數據報。網絡庫使用定時器,因此數據報可以進一步拆分或組合。 TCP還會發送零字節的消息,用作保持活動狀態,以便連接不會關閉。因此,在發送消息時,您必須爲每條消息設置一個終止符。您可以使用3種技術的組合:1)ASCII:以固定字符終止,如'\'2)Ascii或Binary:將消息的長度添加到消息的開頭3)Ascii或Binary:固定長度的消息。接收需要閱讀消息,直到找到結尾 – jdweng
@rene對不起,我沒有表達得很清楚。錯誤的數據意味着垃圾,垃圾每次都從第二個TCP數據報的第一個字節開始。 ByteStreamWriter是一個非常簡單的BinaryWriter,我可以保證它按預期工作。 –