Читайте также:
|
|
Большинство протоколов с установлением соединения являются потоковыми. Важно учитывать, что при использовании любой функции отправки или приема данных через потоковый сокет нет гарантии, что вы прочитаете или запишете весь запрошенный объем данных. Скажем, требуется отправить 2048 байт из символьного буфера функцией send:
char sendbuff[2048];
int nBytes = 2048;
// Заполнение буфера sendbuff 2048 байтами данных
// Присвоение s значения действительного потокового сокета соединения
ret = send(s, sendbuff, nBytes, 0);
Возможно, функция send сообщит об отправке менее 2048 байт. Переменная ret будет содержать количество переданных байт, поскольку система выделяет определенное количество буферного пространства на отправку и прием сообщений для каждого сокета. При отправке данных внутренние буферы удерживают их до момента отправки непосредственно по проводу. Причиной неполной отправки может быть, например, передача большого количества данных, при этом все буферы слишком быстро заполнятся.
В TCP/IP также существует так называемый размер окна. Принимающая сторона регулирует его, указывая количество данных, которое способна принять. При переполнении данными получатель может задать нулевой размер окна, чтобы справиться с поступившими данными. Это приведет к приостановке отправки данных, пока размер окна не станет больше 0. В нашем случае размер буфера может оказаться равным 1024 байтам, следовательно, потребуется повторно отправить оставшиеся 1024 байта. Отправку всего содержимого буфера обеспечит следующий фрагмент программы:
char sendbuff[2048];
int nBytes = 2048, nLeft, idx;
// Заполнение буфера sendbuff 2048 байтами данных
// Присвоение s значения действительного потокового сокета соединения
nLeft = nBytes;
idx = 0;
while (nLeft > 0)
{
ret = send(s, &sendbuff[idx], nLeft, 0);
if (ret == SOCKET_ERROR)
{
// Ошибка
}
nLeft -= ret;
idx += ret;
Все, сказанное далее справедливо и для приема данных на потоковом сокете, но для нас это не очень важно. Приложение не знает, сколько данных оно в очередной раз прочтет на потоковом сокете. Если вам нужно отправить дискретные сообщения по потоковому протоколу, это не составит труда. Например, если у всех сообщений одинаковый размер (512 байт), то прочитать их можно так:
char recvbuff[1024];
int ret, nLeft, idx;
while (nLeft > 0)
{
ret = recv(s, &recvbuff[idx], nLeft, 0);
if (ret == SOCKET_ERROR)
{
// Ошибка
}
idx += ret;
nLeft -= ret;
}
Ситуация несколько усложнится, если размер сообщений будет варьироваться. Тогда потребуется реализовать собственный протокол, сообщающий получателю о размере поступающего сообщения. Пусть первые 4 байта сообщения указывают его размер в виде целого числа. Преобразовав их в число при чтении, приемник узнает длину сообщения.
Дата добавления: 2014-12-19; просмотров: 89 | Поможем написать вашу работу | Нарушение авторских прав |