recv() 返回的字节数可以少至 1 字节,多至请求的字节数。 TCP 是字节流,没有消息的概念,必须在应用程序代码中处理。
接收者必须知道需要多少字节,然后循环读取,直到它读取了那么多字节,不管它需要多少次读取。
但是,在这种情况下,接收方不知道消息的确切长度,因为发送方在发送消息本身之前并没有发送消息长度,所以唯一可用的选项是接收方从套接字读取逐字节直到遇到终止的\n。
例如:
int readLine(int socket, char **line)
{
int r, len = 0, cap = 256;
char b;
*line = NULL;
char *outline = (char*) malloc(cap);
if (!outline) return -2;
do
{
r = recv(socket, &b, 1, 0);
if (r <= 0)
{
free(outline);
return r;
}
if (b == '\n')
break;
if (len == cap)
{
cap += 256;
char *newline = (char*) realloc(outline, cap);
if (!newline)
{
free(outline);
return -2;
}
outline = newline;
}
outline[len] = b;
++len;
}
while (true);
if ((len > 0) && (line[len-1] == '\r'))
--len;
if (len == cap)
{
char *newline = (char*) realloc(outline, cap + 1);
if (!newline)
{
free(outline);
return -2;
}
outline = newline;
}
outline[len] = '\0';
*line = outline;
return 1;
}
char *line;
int r;
do
{
r = readLine(cliSock, &line);
if (r <= 0)
{
if (r == 0)
printf("client disconnected\n");
else if (r == -2)
printf("memory error\n");
else
printf("read error\n");
break;
}
// process line as needed...
free(line);
}
while (true);
或者,您可以使用中间缓冲区来帮助您在读取之间缓存数据并更有效地从套接字中获取数据:
char *buffer;
int buflen, bufcap;
int readLine(int socket, char **line)
{
char *ptr;
int r, idx = 0;
*line = NULL;
do
{
ptr = memchr(buffer + idx, '\n', buflen - idx);
if (ptr)
{
int total = ((ptr + 1) - buffer);
int len = (total - 1);
if ((len > 0) && (buffer[len-1] == '\r'))
--len;
*line = (char*) malloc(len + 1);
if (*line == NULL)
return -2;
memcpy(*line, buffer, len);
(*line)[len] = '\0';
if (total < buflen)
memmove(buffer, buffer + total, buflen - total);
buflen -= total;
break;
}
if (buflen == bufcap)
{
int newcap = bufcap + 256;
char *newbuffer = (char*) realloc(buffer, newcap);
if (!newbuffer)
return -2;
buffer = newbuffer;
bufcap = newcap;
}
r = recv(socket, buffer + buflen, bufcap - buflen, 0);
if (r <= 0)
return r;
buflen += r;
}
while (true);
return 1;
}
buflen = 0;
bufcap = 256;
buffer = (char*) malloc(bufcap);
if (buffer)
{
char *line;
int r;
do
{
r = readLine(cliSock, &line);
if (r <= 0)
{
if (r == 0)
printf("client disconnected\n");
else if (r == -2)
printf("memory error\n");
else
printf("read error\n");
break;
}
// process line as needed...
free(line);
}
while (true);
free(buffer);
}