多线程套接字服务器-接收数据
本文关键字:数据 套接字 服务器 多线程 | 更新日期: 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)->服务器(数据不完整,线程由于某种原因挂起)
- 客户端(线程/数据包#2)->服务器(完整数据,缓冲区传递给命令id funct)
- 客户端(线程/数据包#1)->服务器(第一个数据包的其余数据到达,缓冲区传递给命令id func)
3我需要能够从外部(公共)访问这个缓冲区,这样我就可以在缓冲区填满时从另一个类开始使用它。
我希望这是有道理的。我怎样才能做到这一点?
-
我认为它需要在OnDataReceived中,或者通过委托或引用另一个类或接口来调用另一个类别。如果您调用另一个类,那么回调函数应该接收刚刚接收到的字节并进行处理。这里重要的是线程之间任何必要的同步,这就是为什么我认为它需要在OnDataReceived中执行。此外,我注意到您在每次调用OnDataReceived时都在解码字符。这可能是最好的做法,一旦你有一个完整的数据包,除非你确定只发送单字节字符(ASCII),否则你可能会尝试解码一个已经在发送中分割的字符。
-
客户端中的每个线程都需要有自己的连接,或者需要确保在适当的锁内同时发送整个数据包。如果每个线程都有自己的连接,那么服务器上的每个连接都需要一个缓冲区。如果客户端上只有一个连接,那么服务器上就不需要多个缓冲区。
-
这是阻塞队列的好位置。这是CLR版本:http://msdn.microsoft.com/en-us/library/dd267312.aspx.您可能希望将其与并发队列一起使用,http://msdn.microsoft.com/en-us/library/dd267265.aspx.tcp_server类会在数据包被完全接收时将其放入队列中,然后另一个线程可能会阻止从队列中读取数据,并处理放入队列中的任何数据包。