Есть ли параметр, который я могу использовать для предотвращения объединения нескольких TCP-пакетов в один буфер внутри обратного вызова Socket.BeginReceive
?Socket.BeginReceive слияние TCP-пакетов
Реакция вашего коленного рефлектора будет заключаться в том, что я ничего не могу сделать, чтобы предотвратить разделение и слияние данных TCP, но это не то, что я прошу; Я могу отчетливо видеть, что отдельные пакеты принимаются в Wireshark, и моя единственная проблема - латентность, т. Е. Обрабатывать сегмент, как только он поступит. Это не значит, что я не знаю, как обрабатывать сегмент split/merged, но это означает, что я хочу избежать задержки.
Мой код выглядит следующим образом:
void WaitForData(ISocketInfo soc)
{
if (socket != null && socket.Connected)
socket.BeginReceive(buffer, 0, buffer.Length,
SocketFlags.None, OnPacketReceived, socket);
}
void OnPacketReceived(IAsyncResult asyn)
{
try
{
var socket = (ISocketInfo)asyn.AsyncState;
numberOfBytesReceived = socket.EndReceive(asyn);
if (numberOfBytesReceived > 0)
{
_queue.Enqueue(buffer, 0, numberOfBytesReceived);
OnNewDataReceived();
}
WaitForData(socketInfo);
}
catch (SocketException ex)
{
Log.Warn("Socket error while receiving packet", ex);
Close();
}
}
Когда я анализирую эти пакеты в WireShark, я могу увидеть отдельные пакеты TCP поступают каждые 50 мс, каждый из них (скажем) 100 байт. Но иногда в моем приложении есть задержка в 100 мс, а методы OnPacketReceived
- 200 байт.
Поскольку WireShark подтверждает, что это не проблема с ОС/сетью, что может быть проблемой здесь? OnPacketReceived
просто срабатывает в фоновом потоке, поэтому он не блокирует метод, и программа на самом деле не потребляет много CPU.
(Update)
Похоже, я не передать достаточно мой вопрос четко. Моя проблема заключается не в том, как анализировать данные, если они разделены по сегментам. Мой протокол хорошо определен (т. Е. START_COOKIE, LENGTH, DATA, CRC), и я вставляю данные в байтовый FIFO, как только я его получу (вызов _queue.Enqueue
внутри фрагмента выше), поэтому я могу легко проанализировать его асинхронно.
Вопрос, если я вижу пакет нет. 1 (100 байт) при + 50 мс в Wireshark и номер пакета. 2 (100 байт) на + 100 мс в Wireshark, и мое приложение не блокирует метод OnPacketReceived
и не потребляет процессор, почему .NET, каждый раз в то время, вызывает OnPacketReceived
при + 100 мс и объединяет два пакета в один?
Возможно, здесь проблема? _ Здесь нет проблем. TCP - бесконечный поток ** **, а поведение, которое вы описываете, является стандартным ** и ожидается **. Это зависит от вашей программы, чтобы иметь дело с частичными «сообщениями», и несколько «сообщений» получаются сразу. Либо с префиксом byte lengh, разделителями сообщений, либо комбинацией этих вещей. –
[This] (http://stackoverflow.com/questions/16001434/async-tcp-server-message-framing-advice/16001812#16001812) ответ дает немного больше информации. – HABO
@Idle_Mind: Я думаю, вы неправильно поняли вопрос. Я все равно размещаю все данные в буфер FIFO, и я могу легко разобрать его, формат четко определен. Но возникает вопрос: если Wireshark показывает ** два фактических отдельных TCP-пакета **, принимаемых сетевой картой, почему .NET создает дополнительную задержку и объединяет два пакета в один буфер? Меня беспокоит латентность, а не разбор. Во-вторых, TCP не является «бесконечным потоком», это протокол для передачи (потенциально) бесконечного потока данных в сегментах. – Lou