プロジェクト内の 2 つのシステムを TCP 通信と統合する必要があります - カスタム プロトコルが開発されました。
プロトコルを介して送信されるメッセージは次のようになります。
MsgLength - 10 positions (in chars, not bytes)
MessageType - 20 positions
Message Number - 9 positions
Timestamp - 19 positions
version - 2 positions
Body - variable (depending on first field)
私はソケットプログラミングを検討していますが、完全なメッセージが到着するのを待つための最良の方法は何だろうと思っています。おそらく、バイト数を残りの文字数に変換する必要があります。ソケット API はバイトでのみ機能するためです。
すべてのヒント、コード サンプル、ブログ投稿は大歓迎です :-)
編集:これは私のコードの最初のバージョンです。複数のクライアントが同時に接続できるため、非同期メソッドを使用しています。
private static void Listen()
{
while (true)
{
//TcpClient client = _listener.AcceptTcpClient();
allDone.Reset();
_listener.BeginAcceptTcpClient(new AsyncCallback(AcceptCallback), _listener);
allDone.WaitOne();
}
}
public static void AcceptCallback(IAsyncResult ar)
{
// Signal the main thread to continue.
allDone.Set();
// Get the socket that handles the client request.
//TcpListener listener = (TcpListener)ar.AsyncState;
TcpClient handler = _listener.EndAcceptTcpClient(ar);
// Create the state object.
StateObject state = new StateObject();
state.client = handler;
handler.GetStream().BeginRead(state.buffer, 0, StateObject.BufferSize, new AsyncCallback(ReadCallback), state);
}
public static void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
Encoding enc = Encoding.GetEncoding("ISO-8859-1");
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
TcpClient handler = state.client;
int bytesRead = handler.GetStream().EndRead(ar);
state.TotalHeaderBytesRead += bytesRead;
if (bytesRead == 60)
{
string header = enc.GetString(state.buffer);
Header h = HeaderParser.Parse(header);
//todo read the body
byte[] bodyBuffer = new byte[((HeaderPlaPo)h).Length - 60];
state.buffer = bodyBuffer;
handler.GetStream().BeginRead(state.buffer, 0, bodyBuffer.Length, new AsyncCallback(ReadBodyCallback), state);
Logger.Log(string.Format("received header {0}", header), System.Diagnostics.TraceLevel.Info);
}
else
{
// Not all data of header received. Get more.
handler.GetStream().BeginRead(state.buffer, 0, StateObject.BufferSize - state.TotalHeaderBytesRead, new AsyncCallback(ReadHeaderCallback), state);
}
}
public static void ReadBodyCallback(IAsyncResult ar)
{
Encoding enc = Encoding.GetEncoding("ISO-8859-1");
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
TcpClient handler = state.client;
int bytesRead = handler.GetStream().EndRead(ar);
int bytesRead = handler.GetStream().EndRead(ar);
state.TotalBodyBytesRead += bytesRead;
if (state.buffer.Length == state.TotalBodyBytesRead)
{ //すべての文字列を受け取りました body = enc.GetString(state.buffer); Logger.Log(string.Format("受信した本文 {0}", body), System.Diagnostics.TraceLevel.Info); } else { handler.GetStream().BeginRead(state.buffer, bytesRead, state.buffer.Length - state.TotalBodyBytesRead, ReadBodyCallback, state); } }
public class StateObject { // クライアント ソケット。public TcpClient クライアント = null; // 受信バッファのサイズ。public static int BufferSize = 60; // 受信バッファ。public byte[] buffer = new byte[BufferSize]; // 受信データ文字列 public StringBuilder sb = new StringBuilder(); //ヘッダー public ヘッダー ヘッダー; public Body ボディ; public Int32 TotalBodyBytesRead; public Int32 TotalHeaderBytesRead; }
このコードは、データを送信して接続を閉じるクライアントに対して機能しますが、接続されたクライアントを使用して複数回送信すると、データが読み取られません -> 完全な本文を読み取った後に接続を閉じる必要がありますか?