Вы также можете использовать
DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);
, чтобы убедиться, что у вас есть конечные 0.
См. Протокол управления передачей :
TCP обеспечивает надежную, упорядоченную доставку потока байтов из программы на одном компьютере в другую программу на другом компьютере.
blockquote>«Поток» означает отсутствие границы сообщения с точки зрения приемника. Вы можете получить одно 1000-байтовое сообщение или одну тысячу сообщений в 1 байт в зависимости от того, что находится внизу, и как часто вы вызываете чтение / выбор.
Изменить: Позвольте мне пояснить с точки зрения приложения. Нет, TCP не гарантирует, что одно чтение даст вам все 1000 байтов (или 1 МБ или 1 ГБ), которые отправитель мог отправить. Таким образом, протокол выше TCP обычно содержит заголовок с фиксированной длиной с общей длиной содержимого в нем. Например, вы всегда можете отправить 1 байт, который указывает общую длину содержимого в байтах, которая поддерживает до 255 байт.
Как указываются другие ответы, TCP является протоколом stream - каждый отправленный байт будет приниматься (один раз и в том же порядке), но нет внутренних «границ сообщений» - все ли байты отправляются в одном вызове .send
или несколько, они все равно могут приниматься одним или несколькими вызовами .receive
.
Итак, если вам нужны «границы сообщений», вам необходимо наложить их сверху потока TCP, IOW, по существу, на уровне приложения. Например, если вы знаете, что байты, которые вы отправляете, никогда не будут содержать \0
, строки с нулевым завершением работают нормально; различные методы «экранирования» позволяют отправлять строки байтов, которые не подчиняются таким ограничениям. (Для этого существуют существующие протоколы, но ни один из них не является широко распространенным или широко распространенным).
Протокол управления передачей гарантирует успешную доставку всех пакетов, требуя подтверждения успешной доставки каждого пакета отправителю получателем. По этому определению приемник всегда будет получать полезную нагрузку в кусках, когда размер полезной нагрузки превышает MTU (максимальная единица передачи) .
Для получения дополнительной информации см. Передача Протокол управления .
Это зависит от установленного MTU (Maximum transfer unit). Если ваше установившееся соединение (однажды рукопожатие) относится к MTU размером 512 байт, вам понадобятся два или более TCP-пакетов для отправки 1000 байт.
Единственное, что гарантирует уровень TCP, заключается в том, что получатель получит:
Нет никаких гарантий относительно того, как байты могут быть разделены на «пакеты». Все, что вы могли бы прочитать о MTU, фрагментации пакетов, максимальном размере сегмента или любом другом, находящемся ниже уровня сокетов TCP, не имеет значения. TCP предоставляет службу потока только .
Что касается вашего вопроса, это означает, что получатель может получить первые 500 байт, а затем следующие 500 байт. Или, получатель может получать данные по одному байту за раз, если это то, что он просит. Именно по этой причине функция recv()
принимает параметр, указывающий, сколько данных в возвращает , вместо того, чтобы сообщать вам , насколько большой пакет .
В своем сообщении вы определяете, сколько байтов должно содержать ваше сообщение. Например, в вашем случае это 1000. Ниже приведен код C # и его запуск для достижения того же. Метод возвращает 1000 байтов. Код прерывания - 0 байт; вы можете настроить это в соответствии с вашими потребностями.
Использование:
strMsg = ReadData(thisTcpClient.Client, 1000, out bDisconnected);
Ниже приведен метод:
string ReadData(Socket sckClient, int nBytesToRead, out bool bShouldDisconnect)
{
bShouldDisconnect = false;
byte[] byteBuffer = new byte[nBytesToRead];
Array.Clear(byteBuffer, 0, byteBuffer.Length);
int nDataRead = 0;
int nStartIndex = 0;
while (nDataRead < nBytesToRead)
{
int nBytesRead = sckClient.Receive(byteBuffer, nStartIndex, nBytesToRead - nStartIndex, SocketFlags.None);
if (0 == nBytesRead)
{
bShouldDisconnect = true;
//0 bytes received; assuming disconnect signal
break;
}
nDataRead += nBytesRead;
nStartIndex += nBytesRead;
}
return Encoding.Default.GetString(byteBuffer, 0, nDataRead);
}
Сообщите нам, что это не помогите вам (0: Удачи.
TCP гарантирует, что они получат все 1000 байтов, но не обязательно в порядке (хотя это будет выглядеть так, как и в приложении), и не обязательно все сразу (если вы сами не создадите пакет и не сделаете это).
Тем не менее, для пакета размером до 1000 байт есть вероятность, что он отправит один пакет, если вы сделаете это за один вызов send
, хотя для больших передач он не может.
В принципе, насколько это касается TCP, это гарантирует, что данные, отправленные с одного конца на другой, будут отправлены в том же порядке. Теперь обычно вам нужно иметь внутренний буфер, который продолжает цикл, пока не получит 1000-байтовый «пакет». Поскольку команда recv, как было упомянуто, возвращает, сколько фактически было получено. Поэтому обычно вам нужно будет выполнить протокол поверх TCP, чтобы вы могли отправлять данные с соответствующей скоростью. Потому что, если вы отправляете () все данные за один проход через него, будет перегружать лежащий сетевой стек и который вызовет осложнения. Поэтому обычно в протоколе отправляется крошечный пакет подтверждения, чтобы подтвердить, что отправлен пакет из 1000 байтов.
Да, есть возможность для получения пакетов по частям. Надеюсь, что эта статья msdn и следующий пример (взятый из статьи в msdn для быстрого просмотра) были бы полезны для вас, если вы используете сокеты Windows.
void CChatSocket::OnReceive(int nErrorCode)
{
CSocket::OnReceive(nErrorCode);
DWORD dwReceived;
if (IOCtl(FIONREAD, &dwReceived))
{
if (dwReceived >= dwExpected) // Process only if you have enough data
m_pDoc->ProcessPendingRead();
}
else
{
// Error handling here
}
}
IP-пакеты могут быть фрагментированы во время повторной передачи.
Таким образом, машина назначения может принимать несколько пакетов, которые будут повторно собраны стеком TCP / IP. В зависимости от используемого сетевого API - данные будут переданы вам либо повторно собранными, либо в RAW-пакетах.