多线程套接字服务器-接收数据

本文关键字:数据 套接字 服务器 多线程 | 更新日期: 2023-09-27 18:24:58

我有一个简单的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;
         }
}

以下是OnDataRecived函数的完整代码:

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

max_buffer_size设置为10。若我向服务器发送100个字节,onDataRecieve将执行10次。

我有3个问题:

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

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

例如:

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

3我需要能够从外部(公共)访问这个缓冲区,这样我就可以在缓冲区填满时从另一个类开始使用它。

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

多线程套接字服务器-接收数据

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

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

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