Я исследовал это много часов и попробовал много разных вещей, чтобы понять это, но я застрял.Я пытаюсь создать асинхронный сокет, к которому будет доступ из нескольких потоков.Это имеет тенденцию работать нормально, пока у меня нет нескольких потоков, которые пытаются отправить близко к одному и тому же времени.При отправке нет ошибок, единственная проблема - когда EndReceive () пытается прочитать данные, он возвращает 0 байтов и ошибка сокета - «success».Я читал, что это означает, что это было изящное завершение работы, и у сервера больше нет данных для отправки, но тип сервера, к которому я подключаюсь, никогда не должен был отправлять все данные, это не тот тип сервера.Всегда должны быть данные, которые нужно прочитать, и они не должны закрываться.
Потоки, которые я использовал для отправки, где несколько System.Threading.Timers, но я читал, что они не совсем потокобезопасны.Я также пытался с System.Timers.Timer, но это был тот же результат.Я также пытался использовать только 1 поток для отправки большого количества пакетов одновременно, спящих в течение 100 мс между ними, и я получу тот же результат.
Для получения кода ниже.Для отправки я попробовал просто обычную блокировку Send, а также BeginSend, и это не имело значения.
void Receive()
{
try
{
if (_datacb == null)
_datacb = new AsyncCallback(OnRecvData);
byte[] buffer = new byte[FBufferSize];
FSocket.BeginReceive(buffer, 0, FBufferSize, SocketFlags.None, _datacb, buffer);
}
catch (SocketException ex)
{
OnSocketError(ex);
}
}
void OnRecvData(IAsyncResult ar)
{
try
{
SocketError err;
int bytesRead = FSocket.EndReceive(ar, out err);
if (bytesRead == 0)
{
throw new SocketException();
}
byte[] buffer = ar.AsyncState as byte[];
FReceived.AddBytes(buffer, bytesRead);
ByteBuffer message = FReceived.GetNextMessage();
while (message != null)
{
Process(message);
message = FReceived.GetNextMessage();
}
}
catch (SocketException ex)
{
OnSocketError(ex);
}
Receive();
}
Я думал, что это может быть сервер, который просто отключает сокет для слишком быстрой отправки, но у меня фактически есть блокирующая версия, которую я сделал в VS2008, и я смог использовать 50 различных таймеров, которые отправляли 1 пакет каждую секунду, и я не был отключен.Я попробовал почти тот же код в VS2010, и bytesRead был 0. Я также пробовал код сокета asyc в VS2008 просто чтобы посмотреть, происходит ли что-то странное, но в VS2008 он все еще дает мне bytesRead == 0. Для кода блокировки, который не 'Отключите меня:
tcpClient = new TcpClient(host, 443);
networkStream = tcpClient.GetStream();
mReader = new BinaryReader(networkStream);
mWriter = new BinaryWriter(networkStream);
receiveMessage = new Thread(new ThreadStart(ReceiveMessages));
receiveMessage.Start();
private void ReceiveMessages()
{
while (true)
{
if ((tcpClient != null) && (tcpClient.Connected))
{
if (tcpClient.Available >= 4)
{
if (!isConnected) isConnected = true;
try
{
ByteBuffer message = new ByteBuffer();
message.AddBytes(mReader.ReadBytes(4));
int mSize = message.ReadInt();
message.AddBytes(mReader.ReadBytes(mSize - 4));
processor.Process(message);
}
catch (Exception ex)
{
Print("Recv Msg: " + ex.Message);
}
}
Thread.Sleep(1);
}
}
Отправка:
mWriter.Write(send);
mWriter.Flush();
Не слишком доволен, потому что он использует много процессора.Я пробовал другие способы сделать блокировку сокетов, как это, без использования большого количества процессора, но они также имеют тенденцию отключаться.