C# 当我的插座断开连接时,为什么我要接收数据?
我的插座有问题。 基本上,我有几个监听器可以在我电脑上的所有可用端口上进行监听。当一个套接字连接到其中一个监听器时,我打开一个新的套接字连接来处理该连接,我的监听器就会返回到监听状态 然而,当客户端断开连接时,我会继续接收空数据。 正如您在下面的代码中所看到的,我放置了一个Console.WriteLine来检查所接收消息的长度。 当连接关闭时,它显示了超过100行的C# 当我的插座断开连接时,为什么我要接收数据?,c#,sockets,asynchronous,C#,Sockets,Asynchronous,我的插座有问题。 基本上,我有几个监听器可以在我电脑上的所有可用端口上进行监听。当一个套接字连接到其中一个监听器时,我打开一个新的套接字连接来处理该连接,我的监听器就会返回到监听状态 然而,当客户端断开连接时,我会继续接收空数据。 正如您在下面的代码中所看到的,我放置了一个Console.WriteLine来检查所接收消息的长度。 当连接关闭时,它显示了超过100行的charLen:0。意思是它收到了一些东西,但我不知道它从哪里来 然后我还将在WaitData-方法中收到一个System.Obj
charLen:0
。意思是它收到了一些东西,但我不知道它从哪里来
然后我还将在WaitData
-方法中收到一个System.ObjectDisposedException
错误
ClientSocketClass tmpClient = (ClientSocketClass)asyn.AsyncState;
try
{
// END THE BeginReceive() ASYNCHRONOUS CALL BY CALLING THE EndReceive() METHOD FOR THAT SOCKET
// THIS WILL RETURN THE NUMBER OF CHARACTER WHICH HAS BEEN RECEIVED BY THE CLIENT
int byteMessage = tmpClient.Socket.EndReceive(asyn);
char[] chars = new char[byteMessage + 1];
// EXTRACT THE CHARACTERS INTO A BUFFER
System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
int charLen = d.GetChars(tmpClient.BufferSize, 0, byteMessage, chars, 0);
Console.WriteLine("charlen: " + charLen.ToString());
// START WAITING AGAIN FOR NEW DATA FROM THE CLIENT
WaitForData(tmpClient);
Array.Resize(ref chars, charLen);
// PROCESS THE CURRENT MESSAGE
string tempData = new string(chars).Replace("\0", string.Empty);
// LOG THE RECEPTION OF NEW DATA
string log = string.Format("{0}{1}Received: {2}", DateTime.Now.ToString("HH:mm:ss.fff"), "\t", tempData);
Log(LoggingType.Data, LoggingLevel.Debug, log);
// ADD THE MESSAGE TO THE MESSAGE QUEUE
if (MessageQueue != null)
{
if (tempData != null && tempData != string.Empty)
{
MessageQueue.Add(tempData);
}
}
}
catch (ObjectDisposedException)
{
// THIS CODE WILL BE EXECUTED IF THE SOCKET WAS DISCONNECTED
if (tmpClient != null)
{
// GET THE ID OF THE CLIENT
int clientId = tmpClient.Id;
// REMOVE THE CLIENT FROM THE CONNECTED CLIENTS LISTS
removeClient(clientId);
string log = string.Format("{0}{1}Client {2} disconnected", DateTime.Now.ToString("HH:mm:ss.fff"), "\t", clientId);
Log(LoggingType.Status, LoggingLevel.Notification, log);
}
return;
}
下面是WaitForData方法:
public void WaitForData(ClientSocketClass selectedClient)
{
try
{
if (pfnWorkerCallBack == null)
{
// SPECIFY THE CALL BACK FUNCTION WHICH SHOULD BE RUN
// WHEN DATA IS RECEIVED FROM THE CLIENT
pfnWorkerCallBack = new AsyncCallback(OnDataReceived);
}
// START RECEIVING THE MESSAGE INTO THE DATA BUFFER
selectedClient.Socket.BeginReceive(selectedClient.BufferSize, 0, selectedClient.BufferSize.Length, SocketFlags.None, pfnWorkerCallBack, selectedClient);
}
catch (SocketException ex)
{
string log = string.Format("{0}\t<WaitForData>\tAn error occured while waiting for data: {1}{2}", DateTime.Now.ToString("HH:mm:ss.fff"), ex.Message, Environment.NewLine);
Log(LoggingType.Error, LoggingLevel.Debug, log);
}
}
该类在BindingList中使用,BindingList显示在DataGridView中,以显示连接的客户端。但是我只显示了Id和IP地址,因此我在StackOverflow()上找到了答案 我没有意识到的是WaitForData实际上生成了一个循环,当我接收NULL时,我需要跳出这个循环 因此,只要添加下面的代码,问题就解决了
if (byteMessage <= 0)
{
// LEAVE THE LOOP
return;
}
if(byteMessage接收零字节表示传输结束。在此之后,您不应尝试接收更多字节。OnDataReceived的代码在哪里?请使用cmd.exe>Netstat-a检查客户端和服务器上的连接状态,以查看是否断开连接。连接应仅从客户端(而不是服务器)关闭如果客户端和服务器同时尝试关闭,则存在竞争条件,此时连接可能会半开半关。连接是TCP,需要对每条消息进行确认(包括打开和关闭)。如果客户端和服务器同时关闭,其中一个ACK将不会发生,因为连接的一侧已关闭。显示的第一个代码是onDataReceived。我只是从客户端关闭。服务器不会断开连接,它只会在之后进行清理,并将客户端从connectedClients-list中删除。同时,我我在SO()上发现了一个类似的问题,但我不确定如何在代码中实现它。
if (byteMessage <= 0)
{
// LEAVE THE LOOP
return;
}
public void OnDataReceived(IAsyncResult asyn)
{
ClientSocketClass tmpClient = (ClientSocketClass)asyn.AsyncState;
try
{
// END THE BeginReceive() ASYNCHRONOUS CALL BY CALLING THE EndReceive() METHOD FOR THAT SOCKET
// THIS WILL RETURN THE NUMBER OF CHARACTER WHICH HAS BEEN RECEIVED BY THE CLIENT
int byteMessage = tmpClient.Socket.EndReceive(asyn);
// READ THE CONTENT
string tmpContent = Encoding.UTF8.GetString(tmpClient.BufferSize, 0, byteMessage);
// CHECK IF WE HAVE REACHED THE END OF THE RECEIVED MESSAGE
if (byteMessage <= 0)
{
// LEAVE THE LOOP
return;
}
// START WAITING AGAIN FOR NEW DATA FROM THE CLIENT
WaitForData(tmpClient);
// PROCESS THE CURRENT MESSAGE
string tempData = tmpContent.Replace("\0", string.Empty);
// LOG THE RECEPTION OF NEW DATA
string log = string.Format("{0}{1}Received: {2}", DateTime.Now.ToString("HH:mm:ss.fff"), "\t", tempData);
Log(LoggingType.Data, LoggingLevel.Debug, log);
// ADD THE MESSAGE TO THE MESSAGE QUEUE
if (MessageQueue != null)
{
if (tempData != null && tempData != string.Empty)
{
MessageQueue.Add(tempData);
}
}
}
catch (ObjectDisposedException)
{
// THIS CODE WILL BE EXECUTED IF THE SOCKET WAS DISCONNECTED
if (tmpClient != null)
{
// GET THE ID OF THE CLIENT
int clientId = tmpClient.Id;
// REMOVE THE CLIENT FROM THE CONNECTED CLIENTS LISTS
removeClient(clientId);
string log = string.Format("{0}{1}Client {2} disconnected", DateTime.Now.ToString("HH:mm:ss.fff"), "\t", clientId);
Log(LoggingType.Status, LoggingLevel.Notification, log);
}
return;
}
}