【问题标题】:Multithreaded Socket Server - receive data多线程 Socket 服务器 - 接收数据
【发布时间】:2012-02-17 01:54:36
【问题描述】:

我有一个简单的 TCP 服务器,它使用异步套接字。我面临的挑战是:

我有以下 TCP 服务器类:

 public class tcp_server {
         const int max_clients = 300;
         const int max_buffer_size = 10;

         public AsyncCallback pfnWorkerCallBack;
         private Socket m_mainSocket;
         private Socket[] m_workerSocket = new Socket[max_clients];
         private int m_clientCount = 0;

          ... 

         public void OnClientConnect(IAsyncResult asyn) { }
         public void WaitForData(System.Net.Sockets.Socket soc, int socket_id) { }
         public void OnDataReceived(IAsyncResult asyn)

         public class SocketPacket
         {
            public System.Net.Sockets.Socket m_currentSocket;
            public byte[] dataBuffer = new byte[max_buffer_size];
            public int socket_id = -1;
         }
}

这是 OnDataRecieved 函数的完整代码:

    public void OnDataReceived(IAsyncResult asyn)
    {
        try
        {
            SocketPacket socketData = (SocketPacket)asyn.AsyncState; // cast

            int iRx = 0;
            iRx = socketData.m_currentSocket.EndReceive(asyn);

            char[] chars = new char[iRx + 1];
            System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
            int charLen = d.GetChars(socketData.dataBuffer, 0, iRx, chars, 0);

            WaitForData(socketData.m_currentSocket, socketData.socket_id);
        }
        catch (ObjectDisposedException)
        {
            log("OnDataReceived: Socket has been closed\n");
        }
        catch (SocketException se)
        {
            log(se.Message);
        }
    }

ma​​x_buffer_size 设置为 10。如果我向服务器发送 100 个字节,onDataRecieve 将执行 10 次。

我有 3 个问题:

1 我需要“收集”所有 100 个字节,然后将其传递给另一个函数,该函数将检查接收到的数据中的命令。客户端在数据包末尾添加 4 个字节的“数据包结束标识符”,因为数据大小并不总是事先知道的。我如何/在哪里可以定义这个临时缓冲区,所以 onDataRecieve 会填满它,如果找到 end ,将数据传递给命令识别函数?

2 客户端可能会从不同线程(在同一连接上)向我发送大量数据。我需要一种方法来为每个收到的数据包设置多个临时缓冲区,这样我就可以等到它们填满并将缓冲区先填满的那个传递给命令识别功能,然后清除/删除缓冲区。

例如:

  1. 客户端(线程/数据包#1)->服务器(数据不完整,线程由于某种原因挂起)
  2. 客户端(线程/数据包#2)->服务器(完整数据,缓冲区被传递到命令 ID 函数)
  3. 客户端(线程/数据包#1)->服务器(第一个数据包的其余数据到达,缓冲区传递给命令 id func)

3我需要能够从外部(公共)访问此缓冲区,以便在其他类填满时开始使用该缓冲区。

我希望这是有道理的。我怎样才能做到这一点?

【问题讨论】:

  • 谁能给我指出正确的方向。我找不到任何这样做的例子。

标签: c# asynchronous


【解决方案1】:
  1. 我认为需要在 OnDataReceived 中或通过委托或对另一个类或接口的引用调用另一个类。如果你调用另一个类,那么回调函数应该接收刚刚接收到的字节并处理它们。这里重要的是线程之间任何必要的同步,这就是为什么我认为它需要从 OnDataReceived 中执行。我还注意到您在每次调用 OnDataReceived 期间都在解码字符。一旦你有一个完整的数据包,这可能是最好的做法,除非你确定只发送单字节字符(ASCII),否则你可能会尝试解码一个已被拆分的字符。

    李>
  2. 客户端中的每个线程都需要有自己的连接,或者需要确保它在适当的锁内一次发送整个数据包。如果每个线程都有自己的连接,那么服务器上的每个连接都需要一个缓冲区。如果客户端只有一个连接,那么服务器上就不需要多个缓冲区。

  3. 这是一个阻塞队列的好地方。这是 CLR 版本:http://msdn.microsoft.com/en-us/library/dd267312.aspx。您可能希望将它与并发队列 @9​​87654322@ 一起使用。 tcp_server 类会在数据包被完全接收时将其放入队列中,然后另一个线程可能会阻塞从队列中读取数据并处理任何放入队列中的数据包。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-24
    • 1970-01-01
    • 2017-03-12
    • 2017-10-10
    • 2014-01-22
    • 2021-07-30
    • 2019-02-20
    相关资源
    最近更新 更多