简体   繁体   English

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

[英]Multithreaded Socket Server - receive data

I have a simple TCP server, which uses asynchronous sockets. 我有一个简单的TCP服务器,它使用异步套接字。 The challenge I'm facing is this: 我面临的挑战是:

I have the following TCP server class: 我有以下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;
         }
}

Here's the full code for OnDataRecieved function: 这是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 is set to 10. If I send 100 bytes to server, onDataRecieve will execute 10 times. max_buffer_size设置为10。如果我向服务器发送100字节,则onDataRecieve将执行10次。

I have 3 problems: 我有3个问题:

1 I need to 'collect' all 100 bytes and then pass it to another function that will check for commands in the received data. 1我需要“收集”所有100个字节,然后将其传递给另一个函数,该函数将检查接收到的数据中的命令。 Client adds 4 byte 'packet end identifier' at the end of the packet, because the data size is not always known beforehand. 客户端在数据包的末尾添加了4个字节的“数据包末尾标识符”,因为数据大小并不总是事先已知的。 How/where can I define this temporary buffer, so onDataRecieve would fill it up, if end is found, pass the data to command identification function? 我如何/在哪里定义此临时缓冲区,以便onDataRecieve可以将其填满,如果找到结尾,则将数据传递给命令识别功能?

2 Client might send me a lot of data from different threads (on same connection). 2客户端可能从不同的线程(在同一连接上)向我发送了许多数据。 I need a way to have multiple temporary buffers for each packet received, so I can wait until they fill up and pass the buffer whichever gets filled up first to command identification function and then clear/remove the buffer. 我需要一种为收到的每个数据包设置多个临时缓冲区的方法,因此我可以等到它们填满并将缓冲区中的任一个传递给命令识别功能后再清除/删除该缓冲区。

For example: 例如:

  1. Client (Thread/Packet #1)->Server (incomplete data, thread hangs for some reason) 客户端(线程/数据包#1)->服务器(数据不完整,线程由于某种原因挂起)
  2. Client (Thread/Packet #2)->Server (complete data, buffer gets passed to command id funct) 客户端(线程/数据包2)->服务器(完整的数据,缓冲区被传递给命令id函数)
  3. Client (Thread/Packet #1)->Server (the rest of the data for 1st packet arrive, buffer passed to command id func) 客户端(线程/数据包#1)->服务器(第一个数据包的其余数据到达,缓冲区传递给命令id func)

3 I need to be able to access this buffer from outside (public) so I can start using that buffer from another class while it's filling up. 3我需要能够从外部(公共)访问此缓冲区,以便可以在其他类填满时开始使用该缓冲区。

I hope that makes sense. 我希望这是有道理的。 How can I accomplish this? 我该怎么做?

  1. I believe that needs to either be in OnDataReceived or call off to another class via a delegate or reference to another class or interface. 我认为需要要么在OnDataReceived中,要么通过委托或对另一个类或接口的引用来调用另一个类。 If you call to another class then the callback function should take in the bytes that were just received and process them. 如果调用另一个类,则回调函数应接收刚刚接收到的字节并进行处理。 The important thing here is any necessary synchronization between threads which is why I think it needs to be executed from within OnDataReceived. 这里重要的是线程之间任何必要的同步,这就是为什么我认为需要从OnDataReceived内部执行它的原因。 Also I notice you are decoding characters during each call to OnDataReceived. 我也注意到您在每次调用OnDataReceived时都在解码字符。 That is probably best to do once you have a full packet, unless you are for sure only ever sending single-byte characters (ASCII), otherwise you might try to decode a character that has been split across sends. 除非确定只能发送单字节字符(ASCII),否则最好在拥有完整的数据包后再执行此操作,否则,您可能会尝试解码在发送过程中拆分的字符。

  2. Each thread in the client needs to have its own connection or needs to make sure it sends its whole packet at once within a proper lock. 客户端中的每个线程都需要具有自己的连接,或者需要确保在适当的锁内立即发送其整个数据包。 If each thread has its own connection, then you need a buffer per connection on the server. 如果每个线程都有自己的连接,则服务器上每个连接都需要一个缓冲区。 If you only have one connection on the client, then there is no need for multiple buffers on the server. 如果客户端上只有一个连接,则服务器上不需要多个缓冲区。

  3. This is a good spot for a blocking queue. 这是阻塞队列的好地方。 This is the CLR version: http://msdn.microsoft.com/en-us/library/dd267312.aspx . 这是CLR版本: http : //msdn.microsoft.com/en-us/library/dd267312.aspx You would want to use it with Concurrent Queue, http://msdn.microsoft.com/en-us/library/dd267265.aspx . 您可能希望将其与并发队列( http://msdn.microsoft.com/zh-cn/library/dd267265.aspx)一起使用。 The tcp_server class would place the packet in the queue when it is fully received and then another thread(s) could be blocking on reading from the queue and process any packets that get placed on the queue. tcp_server类将在完全接收到数据包时将其放入队列中,然后另一个线程可能会在从队列中读取数据时阻塞并处理放置在队列中的所有数据包。

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

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