Создайте буфер и извлеките из него ваши протокольные сообщения.Если буфер не содержит полное сообщение, то recv (), пока он не будет.Вот простая реализация C для буферизации сокета (слегка протестированная, компилируется на MS VS2008):
#include <winsock2.h>
#include <string.h>
typedef struct buffsock {
SOCKET s;
char* buf;
size_t maxlen;
size_t curlen;
} buffsock_t;
void buffsock_init(buffsock_t* bs,SOCKET s,size_t maxlen)
{
bs->s = s;
bs->buf = malloc(maxlen);
bs->maxlen = maxlen;
bs->curlen = 0;
}
void buffsock_free(buffsock_t* bs)
{
free(bs->buf);
bs->buf = NULL;
bs->maxlen = 0;
bs->curlen = 0;
bs->s = INVALID_SOCKET;
}
/* Attempt to fill internal buffer.
* Returns 0 if socket closed.
* Returns number of additional bytes in buffer otherwise.
*/
int buffsock_fill(buffsock_t* bs)
{
int bytes;
bytes = recv(bs->s,bs->buf + bs->curlen,bs->maxlen - bs->curlen,0);
if(bytes == SOCKET_ERROR)
return -1;
bs->curlen += bytes;
return bytes;
}
/* Return up to <bytes> from buffered socket.
* If return value 0 socket was closed.
* If return value >0 and <bytes socket received partial message.
*/
int buffsock_bytes(buffsock_t* bs,size_t bytes,void* msg)
{
while(bs->curlen < bytes)
{
int result;
result = buffsock_fill(bs);
if(result == -1)
return -1; /* error on socket */
if(result == 0)
break;
}
if(bytes > bs->curlen)
bytes = bs->curlen;
memcpy(msg,bs->buf,bytes);
bs->curlen -= bytes;
memmove(bs->buf,bs->buf + bytes,bs->curlen);
return bytes;
}
/* Implmementation of a protocol with two big-endian bytes indicating
* msg size followed by <size> bytes of message.
* Returns -1 if error on socket.
* Returns -2 if partial message recv'd (shouldn't happen as long as
* internal buffer is bigger than max message size).
* Returns -3 if user buffer not big enough to hold message.
* Returns size of message otherwise.
*/
int get_protocol_message(buffsock_t* bs,void* msg,size_t maxlen)
{
int bytes;
u_short len;
bytes = buffsock_bytes(bs,sizeof(u_short),&len);
if(bytes == 0)
return 0; /* socket closed, no more messages */
if(bytes == -1)
return -1; /* error on socket */
if(bytes < sizeof(u_short))
return -2; /* partial message */
len = ntohs(len);
if(len > maxlen)
return -3; /* message exceeds user buffer */
bytes = buffsock_bytes(bs,len,msg);
if(bytes < len)
return -2; /* partial message */
return bytes;
}
Используйте это так:
int len;
char msg[256];
buffsock_t bs;
/* open a socket */
buffsock_init(&bs,sock,1024);
len = get_protocol_message(&bs,msg,sizeof(msg));
Ключ TCP / IP не имеетконцепция границ сообщения, поэтому recv () может возвращать от 1 до количества запрошенных байтов.Полученный буфер может содержать несколько или даже частичные сообщения.
Этот код просто добавляет полученные данные в буфер.Протокол запрашивает байты из буфера, а буфер заполняется из сокета.при удалении байтов оставшиеся буферизованные данные смещаются в начало буфера.
В этом случае запрашиваются два байта, преобразуются в длину, а затем запрашиваются остальные байты.Если запрос не может быть удовлетворен, будет получено больше данных.
Надеюсь, это поможет.