ソケット通信を使用する C# のクライアントとサーバー クラスがあります。サーバーは次のようになります。
public class AsyncTcpServer
{
private Socket _server_socket;
private Socket _client_socket;
private byte[] _receive_buffer;
private byte[] _send_buffer;
private NetworkStream _ns;
public void Start()
{
try
{
_server_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_server_socket.Bind(new IPEndPoint(IPAddress.Any, 17999));
_server_socket.Listen(0);
_server_socket.BeginAccept(new AsyncCallback(BeginAccept), null);
}
catch(Exception e)
{
Debug.Print(e.Message);
}
}
private void BeginAccept(IAsyncResult ar)
{
try
{
_client_socket = _server_socket.EndAccept(ar);
_receive_buffer = new byte[_client_socket.ReceiveBufferSize];
_send_buffer = new byte[_client_socket.ReceiveBufferSize];
_ns = new NetworkStream(_client_socket);
_client_socket.BeginReceive(_receive_buffer, 0, _receive_buffer.Length, SocketFlags.None, new AsyncCallback(RecieveCallback), null);
}
catch(Exception e)
{
Debug.Print(e.Message);
}
}
private void RecieveCallback(IAsyncResult ar)
{
try
{
string text = Encoding.ASCII.GetString(_receive_buffer);
Debug.Print("Server Received: " + text);
}
catch (Exception e)
{
Debug.Print("Unexpected exception: " + e.Message);
}
}
public void Send(byte [] bytes)
{
try
{
_ns.Write(bytes, 0, bytes.Length);
}
catch (Exception e)
{
Debug.Print("Unexpected exception: " + e.Message);
}
}
}
クライアントは次のようになります。
public class AsyncTcpClient
{
private Socket _client_socket;
private byte[] _buffer;
private const int HEADER_SIZE = sizeof(int);
public void Start()
{
_client_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_client_socket.BeginConnect(new IPEndPoint(IPAddress.Loopback, 17999), new AsyncCallback(ConnectCallback), null);
}
private void ConnectCallback(IAsyncResult ar)
{
try
{
_client_socket.EndConnect(ar);
_buffer = new byte[_client_socket.ReceiveBufferSize];
StartReceive();
byte[] buffer = Encoding.ASCII.GetBytes("Connected!");
_client_socket.Send(buffer);
}
catch (Exception e)
{
Debug.Print(e.Message);
}
}
private void StartReceive(int offset = 0)
{
try
{
_client_socket.BeginReceive(_buffer, offset, _buffer.Length, SocketFlags.None, new AsyncCallback(RecieveCallback), null);
}
catch (Exception e)
{
Debug.Print(e.Message);
}
}
private void RecieveCallback(IAsyncResult ar)
{
try
{
int bytes_processed = 0;
int bytes_read = _client_socket.EndReceive(ar);
if (bytes_read > 0)
{
NetworkStream ns = new NetworkStream(_client_socket);
while (ns.DataAvailable && (bytes_processed < bytes_read))
{
byte[] len_bytes = new byte[HEADER_SIZE];
ns.Read(len_bytes, 0, HEADER_SIZE);
int current_chunk_size = BitConverter.ToInt32(len_bytes, 0);
if (current_chunk_size > 0)
{
byte[] data_buff = new byte[current_chunk_size];
ns.Read(data_buff, 0, current_chunk_size);
string s = Encoding.ASCII.GetString(data_buff);
bytes_processed += (HEADER_SIZE + current_chunk_size);
Debug.WriteLine(s);
}
}
}
StartReceive();
}
catch (Exception e)
{
Debug.Print(e.Message);
}
StartReceive();
}
}
これらは次のように連携します。
- サーバーの起動
- クライアント接続
- サーバーは、消費のためにカスタムパケットをクライアントに送信します
次の「データ構造」を使用して、サーバー側で送信データをパッケージ化し、クライアントに送信します。
{[DATA_LENGTH_IN_BYTES][PAYLOAD_BYTES]}
クライアント側では、最初の 4 バイト (sizeof(int)) を解析してペイロードの長さを判断し、ペイロード自体を解析します。これは初めて実行するときに機能しますが、その後のDataAvailable
メンバーNetworkStream
は false であり、残りのペイロードを解析できません。
なぜDataAvailable
偽ですか?私は C# でこのようなことを行うのはかなり初めてです - 完全に間違った方法でアプローチしていますか?
前もって感謝します!