无法从 C# 中的 .Net 套接字正确读取数据

2023-12-31

我有一个使用套接字通信的 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是假的,我无法解析其余的有效负载。

Why is DataAvailable错误的?我对用 C# 做这些事情还很陌生 - 我是否完全以错误的方式处理它?

提前致谢!


这是我确定的解决方案:

Server:

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);
            }
        }

    }

和客户:

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);
            }            
        }
    }

从服务器到客户端的消息形成如下:

string message = "This is a message" + "\r\n";
_listener.Send(message);

我喜欢这个替代方案,因为它很简单。它更短并且(至少对我来说)更容易管理。

HTH

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无法从 C# 中的 .Net 套接字正确读取数据 的相关文章

随机推荐

  • Firebase UID 是否始终为 28 个字符?

    我正在为我的 Firebase 项目创建安全规则并想添加UIDstring length 28按照我的数据库规则 我所有的用户 UID 都是 28 个字符 但我想检查它们是否可以更长或更短 Thanks 一位 Firebase 开发人员有这
  • 绘制我自己的标题栏

    我正在我的 WinForm 应用程序中绘制标题栏的一部分 工作正常 将公司名称置于居中并以橙色显示 这是在表单代码中执行此操作的代码 using System Runtime InteropServices DllImport user32
  • C# - 向 IP 地址和端口发送和接收 TCP/IP 消息

    我有以下代码将 TCP IP 消息发送到特定的 IP 地址和端口 public bool sendTCPMessage string ip address string port string transaction id string c
  • 使用 python 进行二维 FFT 会导致频率略有偏移

    我知道关于在 python 中使用快速傅立叶变换 FFT 方法存在几个问题 但不幸的是它们都不能帮助我解决我的问题 我想使用python计算给定二维信号f的快速傅里叶变换 即f x y Python 文档帮助很大 解决了 FFT 带来的一些
  • 在 Retrofit 中序列化查询参数

    想象一下以下请求 POST recipes create void createRecipe Query recipe Recipe recipe Callback
  • SQLAlchemy 可以与 Google Cloud SQL 一起使用吗?

    我查看了 Google Cloud SQL 的文档和各种搜索 但我不知道是否可以将 SQLAlchemy 与 Google Cloud SQL 一起使用 如果可以 连接 URI 应该是什么 我正在寻找使用 Flask SQLAlchemy
  • 编写包含字符串并可在常量中使用的 Rust 结构类型

    我正在开始使用 Rust 我想要一个包含 除其他外 字符串的结构 derive Clone Debug struct Foo string field str won t compile but suppose String or Box
  • 两个key可以指向memcache中的同一个数据吗

    我正在使用 PHP 和 Memcache 我想要多个键指向相同的数据 datawallright memcache gt get wads wall gt getIdwall 这就是我检索数据的方式 如果没有数据 我会进行一些 MySql
  • 使用php杀死Linux中的用户进程

    我正在尝试编写一个 php 脚本来杀死 redhat 机器中的用户 我知道有可能 而且非常不安全 让apache能够以root身份执行操作 但我需要能够从网页上杀死任何用户 是否有人有任何好的工作脚本或给我指出一个地方找到更多信息吗 我可以
  • 如何绕过字符串在文本文件中执行加法

    我将 csv 文件转换为文本文件 我想在文本文件中添加数字 当我运行我的代码时出现错误 假设错误代码我想编写逻辑来绕过我的字符串并仅添加数值 import csv csv file Annual Budget csv txt file an
  • CWnd::CreateDlgIndirect 离开 m_hWnd==NULL

    我正在处理的对话框未显示 使用 CWnd CreateDlgIndirect LPCDLGTEMPLATE lpDialogTemplate CWnd pParentWnd HINSTANCE hInst 对 CreateDlgIndire
  • Ubuntu - Anaconda 2020.02 - 命名空间 Gtk 不可用

    这是在 Ubuntu 16 04 LTS 上 我遇到了与这个问题相同的问题 ValueError 命名空间 Gtk 不可用 https stackoverflow com questions 56823857 valueerror name
  • 保持帐户登录

    我们有一个内部控制面板 办公室的所有员工都全天登录 包括客户服务 我希望对其进行设置 以便在会话到期之前让您保持登录状态 1 小时 如何在 PHP ini 中更改此设置 在我明白将保持会话打开直到浏览器窗口关闭之前我做了一个更改 但它没有坚
  • 使用 plt.plot 与 plt.hist 的彩色图像直方图差异 [Python]

    我使用下面的代码使用两种方法生成彩色图像的直方图 方法一 使用cv2 calcHist 函数计算频率 使用 plt plot 生成频率的线图 方法 2 使用plt hist 函数计算并生成直方图 我添加了bin 250以便2个直方图一致 观
  • 如何在 Python 中将 Excel 工作表另存为 HTML?

    我正在与这个图书馆合作XlsxWriter https pypi python org pypi XlsxWriter 我打开了一本工作簿并在其中写了一些内容 考虑官方的例子 http xlsxwriter readthedocs org
  • ERR_BAD_SSL_CLIENT_AUTH_CERT

    我们在浏览大多数 https 网站时开始遇到问题 示例包括 https technet microsoft com https technet microsoft com https mail google com https mail g
  • 是否可以使用 addEventListener 调用类方法?

    只是我一直想知道的事情 在第二个参数中 addEventListener方法 您可以调用 自定义 类方法 而不是函数吗 即像下面这样的东西会起作用吗 var object new ClassName document getElementB
  • UIScrollView 滚动时重绘内容?

    我知道有一个属性或方法可以使scrollview uiview 在滚动时调用drawRect 方法 由于性能原因 默认情况下处于禁用状态 但我需要启用它 我不记得该方法的名称 因此我无法寻找它 有人知道我在寻找什么吗 提前致谢 我建议使用s
  • QTreeWidget 内的 QT 可点击小部件(可能是按钮)?

    我有一个基本上是 QTreeWidget 的表 我想在其中放置一个可点击的小部件 可能是一个按钮 每行都是一个 QTreeWidgetItem 但我不知道如何使用 QTreeWidgetItem setData 添加按钮 这是对 Qt 文档
  • 无法从 C# 中的 .Net 套接字正确读取数据

    我有一个使用套接字通信的 C 客户端和服务器类 服务器看起来像这样 public class AsyncTcpServer private Socket server socket private Socket client socket