私はC#ソケットクラスを使用して、短い接続でサーバーとの間でTCPメッセージを送受信しています。疑似コード(いくつかの誤った許容論理を除外して明確にする)は以下の通りです。TCPのパッケージがMTUより大きい場合に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();
}
}
(メッセージのサイズが1つのMTUよりも大きくなったときにのみ - 1500バイト)私は、短い接続により当社のサーバーから複数回、同じメッセージを要求するために、このクラスを使用していた、と次のようなものが発生しました。
- 「スリープ(50)は」回(90%)のほとんどが、私は特に言うには、「totalLen」は正しかった、間違った「データ」を受信しますが、「データ」、コメントアウトされた場合間違っていました。
- 「スリープ(50)」を「スリープ(10)」に変更した場合、約半分の時間が間違った「データ」を受信し、「totalLen」も常に正しくなりました。
- 「スリープ(50)」を使用すると、間違った「データ」が受信されることがあります。
私たちのサーバーが適切なデータを送信し、クライアントがTCPレイヤーで適切なデータを受信することを保証できます(使用したポートを通じてすべてのメッセージを監視するWireSharkを使用しました)。なぜ私のC#コードが正しいデータを得ることができないのかを答えるのに役立つ人はいますか?私は常に正しいデータとデータの長さになるだろう。また
、私はwhileループを判断する代わりに、Socket.Receive()の戻り値のmSocket.Availableを使用する場合、...
を使用することができますか?あなたはゼロをたくさん得ますか?またはごみですか?そして、ByteStreamWriterはどこから来たのですか?それはBinaryWriterですか? – rene
あなたはTCPがどのように動作するかを本当に理解していません。 TCPはメッセージを最大サイズ〜1500バイトのデータグラムに分割します。ネットライブラリはタイマーを使用して、データグラムをさらに分割したり組み合わせたりすることができます。 TCPはキープアライブとして使用される0バイトのメッセージも送信し、接続が終了しないようにします。したがって、メッセージを送信する際には、メッセージごとにターミネータが必要です。あなたは3つの技術を組み合わせて使用することができます:1)ASCII:メッセージ3の先頭に長さを追加)ASCIIまたはバイナリ::固定長のメッセージ「'\」2)ASCIIまたはバイナリのような固定された文字で終了します。最後までメッセージを読む必要がある – jdweng
@rene申し訳ありませんが、私は非常に明確に表現していません。間違ったデータはガベージを意味し、ガベージは常に2番目のTCPデータグラムの最初のバイトから正確に開始されます。 ByteStreamWriterは非常にシンプルなBinaryWriterです。期待通りに動作することを保証できます。 –