无法从C#.NET插座正确读取数据 [英] Unable to read data correctly from .Net socket in C#

查看:221
本文介绍了无法从C#.NET插座正确读取数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆