无法从C#.NET插座正确读取数据 [英] Unable to read data correctly from .Net socket in C#
问题描述
我在C#中的客户端和服务器类使用socket通讯。服务器看起来是这样的:
I have a client and server class in C# that uses socket communication. The Server looks like this:
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();
}
}
他们一起工作如下:
They work together as follows:
- 服务器启动
- 客户端连接
- 服务器发送自定义的数据包发送到客户端它的罪耗
我用下面的数据结构来包装在服务器端我的发送数据发送给客户端:
I use the following 'data structure' to package my transmission data on the server side to send to the client:
{[DATA_LENGTH_IN_BYTES][PAYLOAD_BYTES]}
在客户端,我解析的前4个字节(的sizeof(int)的)来确定有效载荷的长度,然后解析净荷本身。这工作我第一次做,但之后的 DataAvailable
成员的NetworkStream
是假的,我不能解析有效载荷的其余部分。
On the client side, I parse the first 4 bytes (sizeof(int)) to determine the payload length and then parse the payload itself. This works the first time I do it but after that the DataAvailable
member of the NetworkStream
is false and I can't parse the rest of the payload.
为什么 DataAvailable
假的?我是很新,这样的东西在C# - ?!我在快到了错误的方式完全
Why is DataAvailable
false? I'm pretty new to doing this stuff in C# - am I approaching it the wrong way entirely?
由于提前
推荐答案
下面是我对结算解决方案:
Here is the solution I settled on:
服务器:
public class Listener
{
private TcpListener _listener;
private TcpClient _client;
public void Start()
{
_listener = new TcpListener(IPAddress.Loopback, 17999);
_listener.Start();
_listener.BeginAcceptTcpClient(new AsyncCallback(AcceptTcpClientCallback), _listener);
}
private void AcceptTcpClientCallback(IAsyncResult ar)
{
try
{
Debug.WriteLine("Accepted tcp client callback");
_client = _listener.EndAcceptTcpClient(ar);
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
}
}
public void Write(string data)
{
try
{
NetworkStream ns = _client.GetStream();
byte[] buffer = Encoding.ASCII.GetBytes(data);
ns.Write(buffer, 0, buffer.Length);
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
}
}
}
而客户端:
And the client:
public class Client
{
private TcpClient _client;
private byte[] _buffer;
public void Start()
{
try
{
_client = new TcpClient();
_client.BeginConnect(IPAddress.Loopback, 17999, new AsyncCallback(ConnectCallback), _client);
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
}
}
private void ConnectCallback(IAsyncResult ar)
{
try
{
NetworkStream ns = _client.GetStream();
_buffer = new byte[_client.ReceiveBufferSize];
ns.BeginRead(_buffer, 0, _buffer.Length, new AsyncCallback(ReadCallback), null);
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
}
}
private void ReadCallback(IAsyncResult ar)
{
try
{
NetworkStream ns = _client.GetStream();
int read = ns.EndRead(ar);
string data = Encoding.ASCII.GetString(_buffer, 0, read);
var res = data.Split(new [] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var r in res)
{
Debug.WriteLine(r); // process messages
}
ns.BeginRead(_buffer, 0, _buffer.Length, ReadCallback, _client);
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
}
}
}
如果从服务器的消息客户端的形成如下:
Where messages from the server to the client are formed as follows:
string message = "This is a message" + "\r\n";
_listener.Send(message);
我喜欢这种替代它的简单。它的很多短(至少对我来说)更容易管理。
I like this alternative for its simplicity. Its a lot shorter and (to me at least) much easier to manage.
心连心
这篇关于无法从C#.NET插座正确读取数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!