gpt4 book ai didi

c - 接收多个 TCP 段

转载 作者:行者123 更新时间:2023-11-30 14:57:43 25 4
gpt4 key购买 nike

我有一个作业,其中 TCP 客户端以以下形式将数据发送到 TCP 服务器:

IP_地址\0端口\0消息\n

现在,当我通过这样的终端发送一些数据时,服务器(IP 地址 10.0.2.15)可以正常接收数据包:

printf "127.0.0.1\0004444\000Some message\n" | nc -N 10.0.2.15 3333

但是,作业的第二部分是读取来自多个段的数据包:

(printf "127.0.0.1"; sleep 0.3; printf "\0004444\000"; sleep 0.3; \
printf "It works"; sleep 0.5; printf "\n") | nc -N 10.0.2.15 3333

我应该如何在服务器上实现读取功能,以便在可能的情况下将所有段存储到缓冲区中?

最佳答案

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);
}

关于c - 接收多个 TCP 段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43707396/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com