繁体   English   中英

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

[英]Multithreaded Socket Server - receive data

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

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

我有3个问题:

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

2客户端可能从不同的线程(在同一连接上)向我发送了许多数据。 我需要一种为收到的每个数据包设置多个临时缓冲区的方法,因此我可以等到它们填满并将缓冲区中的任一个传递给命令识别功能后再清除/删除该缓冲区。

例如:

  1. 客户端(线程/数据包#1)->服务器(数据不完整,线程由于某种原因挂起)
  2. 客户端(线程/数据包2)->服务器(完整的数据,缓冲区被传递给命令id函数)
  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/zh-cn/library/dd267265.aspx)一起使用。 tcp_server类将在完全接收到数据包时将其放入队列中,然后另一个线程可能会在从队列中读取数据时阻塞并处理放置在队列中的所有数据包。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM