У меня проблема с сокетами. В основном у меня есть несколько слушателей, которые прослушивают все доступные порты на моем p c. Когда сокет подключается к одному из слушателей, я открываю новое Socket-соединение для обработки этого соединения, и мой слушатель возвращается к прослушиванию.
Однако, когда клиент отключается, я продолжаю получать пустые данные. Как видно из кода ниже, я добавил Console.WriteLine, чтобы проверить длину полученного сообщения. Когда соединение закрывается, оно показывает мне более 100 строк с charLen: 0
. Это значит, что он что-то получает, но я не знаю, откуда он приходит.
И тогда я также получу ошибку System.ObjectDisposedException
в WaitData
-методе
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);
}
}
Теперь я начинаю думать, что что-то не так в работе с данными в OnDataReceived
. Я комбинировал различные учебники, которые нашел в Интернете, чтобы получить этот код, который сам по себе работает, только когда клиент отключается, я получаю эту ошибку.
Я надеюсь, что кто-то знает, почему.
Чтобы завершить, ниже вы найдете ClientSocketClass, который я использую для организации своих подключенных клиентов.
public class ClientSocketClass
{
private int tmpId;
private string tmpIp;
private byte[] tmpBuffer;
public event PropertyChangedEventHandler PropertyChanged;
public int Id
{
get { return tmpId; }
set
{
tmpId = value;
this.NotifyPropertyChanged("Id");
}
}
public string Ip
{
get { return tmpIp; }
set
{
tmpIp = value;
this.NotifyPropertyChanged("Ip");
}
}
[Browsable(false)]
public Socket Socket { get; set; }
[Browsable(false)]
public byte[] BufferSize
{
get { return tmpBuffer; }
set
{
tmpBuffer = value;
this.NotifyPropertyChanged("BufferSize");
}
}
private void NotifyPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}
Этот класс используется в BindingList, который отображается в DataGridView, чтобы показать подключенные клиенты. Но я показываю только Id и IP-адрес, поэтому [Browsable(false)]