Я пишу базовый сервер TCP/IP для приема сообщений от существующего клиента. В настоящее время я могу получать сообщения с одним и несколькими буферами. Проблема возникает, когда клиент отправляет множество сообщений. Вместо того, чтобы отправлять каждое сообщение в виде единого сообщения, он ожидает, что поток будет открыт, и все сообщения в наборе будут отправляться друг за другом до того, как поток снова закроется. Я закодированы для этого в отредактированной фрагменте ниже:NetworkStream.DataAvailable slow to update
private void AcceptMessage(IAsyncResult ar)
{
String receivedMessage = "";
// Only run if the server is listening. Otherwise, an exception will be thrown.
if (isListening)
{
ASCIIEncoding encoder = new ASCIIEncoding();
try
{
TcpListener listener = (TcpListener)ar.AsyncState;
using (TcpClient client = listener.EndAcceptTcpClient(ar))
using (NetworkStream stream = client.GetStream())
{
int bytesRead;
int totalBytes = 0;
stream.ReadTimeout = ReadTimeout;
do
{
byte[] receivedBytes = new byte[BufferSize];
StringBuilder message = new StringBuilder();
bytesRead = 0;
do
{
try
{
if (stream.CanRead)
bytesRead = stream.Read(receivedBytes, 0, BufferSize);
}
catch (...Exception Handling...)
if (bytesRead == 0)
break;
message.Append(encoder.GetString(receivedBytes, 0, bytesRead));
totalBytes += bytesRead;
} while (bytesRead == BufferSize); // Allow for multiple buffers in a single message
byte[] ack = encoder.GetBytes(GetAck(message.ToString(), ackNak, status, statusMessage));
stream.Write(ack, 0, ack.Length);
...Message Processing...
} while (stream.DataAvailable); // Allow for multiple messages
}
}
catch (...Error Handling...)
finally { ...Cleanup...}
}
}
Проблема возникает на втором while (stream.DataAvailable);
Когда происходит проверка, DataAvailable показывает ложные при передаче набора сообщений, но если я ставлю перерыв на следующей строке , это покажет правду. Другими словами, он проверяет, доступны ли данные до его доступности. Я мог бы исправить это, добавив задержку в одну секунду, прежде чем проверять, есть ли больше сообщений, но в 99 из 100 случаев это было бы ненужной задержкой. Поскольку клиент может отправлять только одно сообщение (или набор сообщений) за раз, он может добавить значительное количество времени на прием сообщений во время занятости.
Есть ли лучший способ определить, есть ли еще ожидающие сообщения (без модификаций клиента)? Благодаря!
EDIT
Я изменил код, чтобы включить предложения. Я добавил тайм-аут и изменил первую проверку с stream.DataAvailable
на bytesRead == BufferSize
. У меня нет доступа к ПО клиента, поэтому я не могу добавить передачу МНВ. Я также не гарантирую, будет ли отправлено несколько сообщений в одном потоке или нескольких отдельных потоках. Я до сих пор не понял, как узнать, есть ли еще ожидающие сообщения. Я не могу оставить поток открытым, потому что это блокирует следующую передачу.
Я отметил Элгонзо как ответ, потому что он помог с большинством аспектов моего вопроса. Он по-прежнему не ответил, как определить, ожидаются ли сообщения, что может быть невозможно, но мой менеджер решил, что, как только соединение будет открыто, мы должны оставить его открытым как выделенное соединение. Это работает, поскольку наши слушатели общаются только с одним устройством по внутренней защищенной сети с постоянным трафиком. Мы добавляем тайм-аут, чтобы отключиться, если на какое-то время неактивно.
Существует мало правильных вариантов использования доступных, и это не один из них. Вы должны либо блокировать, либо читать, пока не получите то, что вам нужно, или используйте async или non-blocking I/O ditto. – EJP