У меня есть приложение, которое отправляет сообщения, которые заканчиваются новой строкой через сокет TCP, используя TCPClient, и он находится в сети NetworkStream.
Данные транслируются примерно в 28k каждые 100 мс из потока данных реального времени для мониторинга.
Я удалил ненужный код, это в основном то, как мы читаем данные:
TcpClient socket; // initialized elsewhere
byte[] bigbuffer = new byte[0x1000000];
socket.ReceiveBufferSize = 0x1000000;
NetworkStream ns = socket.GetStream();
int end = 0;
int sizeToRead = 0x1000000;
while (true)
{
bytesRead = ns.Read(bigbuffer, end, sizeToRead);
sizeToRead -= bytesRead;
end += bytesRead;
// check for newline in read buffer, and if found, slice it up, and return
// data for deserialization in another thread
// circular buffer
if (sizeToRead == 0)
{
sizeToRead = 0x1000000;
end = 0;
}
}
Симптом, который мы наблюдали, несколько прерывисто, основываясь на количестве данных, которые мы отправляли назад, заключается в том, что будет "отставание" от записей, где данные, которые мы читаем из потока, постепенно становятся старше и старше по сравнению с то, что мы доставляем (через несколько минут потоковой передачи, отставание составляет порядка 10 секунд), до тех пор, пока в конце концов все это не будет достигнуто одним большим выстрелом, и цикл повторяется.
Мы исправили его с помощью maxing out sizeToRead и (независимо от того, требуется ли это, я не уверен, но мы все равно это сделали), удалил набор ReceiveBufferSize, установленный на TcpClient, и сохранил его по умолчанию 8192 (меняя только ReceiveBufferSize не исправил его).
int sizeForThisRead = sizeToRead > 8192 ? 8192 : sizeToRead;
bytesRead = ns.Read(bigBuffer, end, sizeForThisRead);
Я подумал, что, возможно, это было взаимодействие с nagle и delayed ack, но wirehark показал, что данные поступают очень хорошо, основываясь на временных меток и просматривая данные (это временная метка, а серверные и клиентские часы синхронизируются в пределах второй).
Мы выводим журналы после ns.Read, и, несомненно, проблема связана с вызовом Read, а не с десериализационным кодом.
Так что это заставляет меня поверить, что если вы установите TcpClient ReceiveBufferSize действительно большим, и в своем вызове Read на нем, который находится в сети NetworkStream, pass bytesToRead будет намного больше байтов, чем ожидалось, там будет тайм-аут в Read вызывать ожидание появления этих байтов, но он все равно не возвращает все в потоке? Каждый последующий вызов в этом цикле истекает до тех пор, пока 1 мегабайт не будет заполнен, после чего, когда "end" получит reset обратно в 0, он вдыхает все, что осталось в потоке, заставляя все это догнать - но это должно Это не так, потому что логика для меня похожа на то, что она должна полностью очистить поток на следующей итерации (поскольку следующий размер будет доступен в буфере).
Или, может быть, это то, о чем я не думаю, что я не могу синтезировать, но, возможно, эти умные души здесь могут что-то придумать.
Или, может быть, это ожидаемое поведение - если да, то почему?