2

ネットワーク化されたインスタンス間で文字列を渡すC#アプリに取り組んでいます。

コードは現在非同期ソケットを使用しており、これまでのところすべてがうまく機能しています(localhost)。

ただし、実際のインターフェイスを通過するときにパケットが分割およびマージされる場合、バッファリングの問題が発生することが予想されます。

クライアント:

Socket sock;
// Snip init and connect

string msg1 = "Hello\nWorld";
byte[] data1 = System.Text.Encoding.UTF8.GetBytes(msg1);
sock.Send(data1);

string msg2 = "Foo\nBar\nBaz";
byte[] data2 = System.Text.Encoding.UTF8.GetBytes(msg2);
sock.Send(data2);

私はこのようなものを使いますが、不足しているビットに対するエレガントな解決策を見つけることができません:

サーバ:

Socket sock;
MemoryStream ms = new MemoryStream();
Queue<string> strings = new Queue<string>();
// Snip init and receive connection
sock.BeginReceive(buffer, 0, MaxSize, SocketFlags.None, new AsyncCallback(OnReceived), null);

void OnReceived(IAsyncResult result) {
  // Snip sanity stuff
  int bytesReceived = sock.EndReceive(result);

  // Here is where I'd need some help...
  ms.Write(buffer, 0, bytesReceived);
  ms.Flush();
  for (;;) {
    StreamReader sr = new StreamReader(ms);
    if (sr.HasAStringTerminationCharacter) { // <-- How?
      string currentString = sr.ReadUntilTermination(); // <-- How?
      strings.Enqueue(currentString);
    }
    else
      break;
  }
  sock.BeginReceive(buffer, 0, MaxSize, SocketFlags.None, new AsyncCallback(OnReceived), null);
}
4

1 に答える 1

0

Encoding.GetBytes() は文字列終了データの前または後に追加しないため、代わりに BinaryReader/BinaryWriter を使用しました。これは、コンテンツの前に文字列の長さをエンコードします。

変更されたクライアントは次のとおりです。

Socket sock;
// Snip init and connect
sock.Send(ToBinary("Hello\nWorld"));
sock.Send(ToBinary("Foo\nBar\nBaz"));

byte[] ToBinary(string s) {
  var ms = new MemoryStream();
  var bw = new BinaryWriter(ms);
  bw.Write(s);
  bw.Flush();
  ms.Flush();
  return ms.ToArray();
}

サーバ:

Socket sock;
MemoryStream ms = new MemoryStream();
Queue<string> strings = new Queue<string>();
// Snip init and receive connection
sock.BeginReceive(buffer, 0, MaxSize, SocketFlags.None, new AsyncCallback(OnReceived), null);

void OnReceived(IAsyncResult result) {
  // Snip sanity stuff
  int bytesReceived = sock.EndReceive(result);

  ms.Write(buffer, 0, bytesReceived);
  ms.Flush();
  long endPos = ms.Position;

  ms.Seek(0, SeekOrigin.Begin);
  long readPos = ms.Position;
  var bw = new BinaryReader(ms);

  for (;;) {
    try {
      string currentString = bw.ReadString();
      strings.Enqueue(currentString);
      readPos = stream.Position;
    }
    catch (EndOfStreamException) {
      long unusedBytes = endPos - readPos;
      var remaining = new MemoryStream();
      remaining.Write(stream.GetBuffer(), (int) readPos, (int) unusedBytes);
      ms = remaining;
      break;
    }
  }
  sock.BeginReceive(buffer, 0, MaxSize, SocketFlags.None, new AsyncCallback(OnReceived), null);
}

分割およびマージされたデータを正しく処理すると思います。

于 2012-11-08T15:33:59.277 に答える