Более быстрый способ взаимодействия с помощью TcpClient?

Я пишу клиент-серверное приложение на C #, и оно отлично работает. Пока все работает и все довольно надежно. Моя проблема в том, что я сталкиваюсь с некоторыми задержками при отправке пакетов через соединение.

На стороне клиента я делаю следующее:

NetworkStream ns = tcpClient.GetStream();

// Send packet

byte[] sizePacket = BitConverter.GetBytes(request.Length);
byte[] requestWithHeader = new byte[sizePacket.Length + request.Length];
sizePacket.CopyTo(requestWithHeader, 0);
request.CopyTo(requestWithHeader, sizePacket.Length);

ns.Write(requestWithHeader, 0, requestWithHeader.Length);

// Receive response

ns.Read(sizePacket, 0, sizePacket.Length);
int responseLength = BitConverter.ToInt32(sizePacket, 0);
byte[] response = new byte[responseLength];

int bytesReceived = 0;
while (bytesReceived < responseLength)
{
  int bytesRead = ns.Read(response, bytesReceived, responseLength - bytesReceived);
  bytesReceived += bytesRead;
}

(Не учитываю некоторые исключения и т. Д.) Сервер делает обратное, то есть блокирует на NetworkStream.Read () до тех пор, пока он не получит весь запрос, затем обработает его и отправит ответ с помощью Write ().

Необработанная скорость Write () / Read () не является проблемой (т.е. отправка больших пакетов является быстро), но отправка нескольких небольших пакетов один за другим без закрытия соединения может быть ужасно медленной (задержки 50-100 мс). Странно то, что эти задержки проявляются в соединениях LAN с типичным временем пинга <1 мс, но они не возникают, если сервер работает на localhost, даже если время пинга будет фактически таким же (по крайней мере, разница не должна быть порядка 100 мс). Для меня это имело бы смысл, если бы я заново открывал соединение для каждого пакета, вызывая много рукопожатий, но это не так. Это как если бы сервер, переходящий в состояние ожидания, выбрасывает его из синхронизации с клиентом, а затем он немного спотыкается, восстанавливая то, что по сути является потерянным соединением.

Итак, я делаю это неправильно? Есть ли способ сохранить соединение между TcpServer и TcpClient синхронизированным, чтобы сервер всегда был готов к приему данных? (И наоборот: иногда обработка запроса от клиента занимает несколько мсек, а затем клиент не кажется готовым к получению ответа от сервера, пока у него не появится несколько минут для пробуждения после блокировки на Read () . )

9
задан user7116 26 May 2011 в 13:43
поделиться