C# 异步套接字,读取所有缓冲区
我有一个客户端,它将从不同的线程向服务器发送大量数据 数据包使用以下格式: 数据包标识 内容 _数据包_指示器的结束_ 我有以下OnDataReceived功能:C# 异步套接字,读取所有缓冲区,c#,sockets,asynchronous,C#,Sockets,Asynchronous,我有一个客户端,它将从不同的线程向服务器发送大量数据 数据包使用以下格式: 数据包标识 内容 _数据包_指示器的结束_ 我有以下OnDataReceived功能: public void OnDataReceived(IAsyncResult asyn) { SocketPacket socketData = (SocketPacket)asyn.AsyncState; int iRx = 0; iRx
public void OnDataReceived(IAsyncResult asyn)
{
SocketPacket socketData = (SocketPacket)asyn.AsyncState;
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);
MessageBox.Show("Incoming data: " + socketData.dataBuffer.Length.ToString() + " from socket(" + socketData.socket_id + ")");
char[] PACKET_END_IDENTIFIER = { (char)2, (char)1, (char)2, (char)1 };
for (int i = 0; i < iRx; i++)
{
GLOBAL_BUFFER.Add(chars[iRx]);
}
if (PacketEndReached(chars, PACKET_END_IDENTIFIER))
{
// done reading the data
PROCESS_PACKET(GLOBAL_BUFFER);
}
WaitForData(socketData.m_currentSocket, socketData.socket_id);
}
如您所见,全局缓冲区定义为“全局”。如果客户端发送需要10秒发送的数据包_1,同时发送需要2秒发送数据的数据包_2,则数据包会混淆。我需要分别收集每个数据包的数据只需使用
字典
替换当前的全局缓冲区
将不同的数据包ID数据存储到不同的列表中
我强烈推荐您一个完美的套接字框架,您无需编写任何套接字代码,它将显著提高您的开发效率 如果可能的话,我建议允许每个客户端线程都有自己的服务器连接。这样做将有助于Winsock堆栈区分来自每个线程的消息,并避免消息之间的任何数据包泄漏。这将有效地让您受益于堆栈的能力,即在将消息(和消息分段)作为完整消息传递给应用程序之前,能够破译哪些消息(和消息分段)要分组在一起 您描述的消息设计虽然非常原始,但只有在您将线程分离到不同的连接(或以其他方式保证一次只从客户端发送一条消息)的情况下才能(可靠地)工作。您在通信中使用了一种非常原始的消息框架技术,它将帮助您确定消息边界,但失败的原因是
socketData.m_currentSocket.EndReceive(asyn)
只会告诉您在引发事件时收到的字节数(不一定是消息中的总字节数)。与其依赖它来告诉您已经读取了多少字节,我建议您从异步处理程序中的循环增量读取传入消息,读取非常小的消息段,直到它发现您的消息结束字节序列。这样做将告诉您的事件何时停止读取并将数据传递给其他对象进行处理
我通常处理消息框架的方式是,在消息之前有一个引人注目的标记(一些在消息中很少出现的值),然后是消息的长度(根据味道进行编码,我个人使用二进制编码以提高效率)、消息内容,最后是消息末尾的第二个引人注目的标记。抢眼器充当协议中消息中断的逻辑队列,消息长度明确地告诉服务器要等待多少字节。通过这种方式,您可以保证接收到所需的字节数(如果没有,这是一个问题,因此丢弃和/或抛出异常),并且它在消息之间提供了一个非常明确的边界,您可以对消息进行编码,这允许间歇性的抽查和验证。谢谢!我在哪里定义它?我用我现在的课程更新了我的问题。我认为这是个坏主意,原因有二:1。如果应用程序组织得当,TCP/IP将为您处理大部分多路复用。2.建议一个库来进一步混淆socket消息从开发人员到(显然)不了解其工作原理的人的工作原理,只会导致无知。毫无疑问,OP将不得不维护和调试他们的代码,混淆他们的细节将把它变成一个黑匣子,他们也无法处理。你说你的客户端正在从多个线程发送数据。每个线程是否都有自己的连接,或者您的客户端代码是否处理通过单个连接发送多个数据流所需的漏斗?所有线程都使用到服务器的单个连接。实际上我不确定这是不是最好的方法。我使用单一连接的唯一原因是,在线/离线时更容易跟踪“在线客户端”。最后一个问题(可能),您是否可以控制所使用的协议,或者是否使用第三方或其他固定协议?我撒谎了,还有一个问题:您的线程是否都发送相同格式的数据(出于相同的解释和原因,目的相同)或者他们执行不同的操作,需要传输不同格式的消息?是的,我使用我自己的。基本上,“协议”是唯一的\u id+内容+数据包\u结束\u指示器。
public partial class TCP_SERVER
{
const int MAX_CLIENTS = 3000;
const int MAX_SOCKET_BUFFER_SIZE = 10;
public AsyncCallback pfnWorkerCallBack;
private Socket m_mainSocket;
private Socket[] m_workerSocket = new Socket[MAX_CLIENTS];
private int m_clientCount = 0;
public GLOBAL_BUFFER;
public void StartServer(int listen_port)
public void OnClientConnect(IAsyncResult asyn)
public void ProcessIncomingData(char[] INCOMING_DATA, int CLIENT_ID)
public void OnDataReceived(IAsyncResult asyn)
}