【问题标题】:How to send and receive newline character over sockets in a client server model?如何在客户端服务器模型中通过套接字发送和接收换行符?
【发布时间】:2017-01-08 18:07:49
【问题描述】:

我正在尝试在 Linux 中学习客户端服务器模型,并且我已经设置了两个 C 文件,即 server.c 和 client.c。这些是我似乎有问题的代码 sn-ps。

server.c 代码 sn-p

char* message = "<query>\n";
write(client_socket_filedescriptor, message, sizeof(message));

client.c 代码 sn-p

char* message = "<query>\n";
read(socket_filedescriptor, buffer, sizeof(buffer));
printf("%s", buffer);
printf("\n\n");
printf("%s", message);

现在,当我运行我的服务器,然后当我运行我的客户端时,我希望 printf 语句打印相同的字符串 &lt;query&gt;\n,但我不断得到 buffer 和 message 变量的不同输出。

当我运行客户端代码时,输​​出看起来有点像这样。

Output image

如您所见,这两个字符串是不同的。我正在尝试模拟典型的 TCP 握手,并且我想确保这两个字符串相同,然后客户端将开始使用该服务器编写或执行某些操作。但我有这个微不足道的问题。谁能告诉我如何解决它?我打算使用 strcmp 来比较缓冲区和消息变量,但就目前而言,strcmp 不会返回 0,因为它们毕竟是不同的字符串。

【问题讨论】:

  • sizeof(message) --> strlen(message)+1
  • 所以你的意思是我应该把sizeof(message)改成strlen(message)?如果是这样,我收到一个错误,因为读取调用只读取第一个字符。
  • 是的,你需要改变它——sizeof(message) 给出的是指针的大小,而不是它所指向的大小。如果您仍然遇到错误,那么显然您的程序中还有其他错误。例如,假设read 将始终接收整个消息是一个常见错误。 read 必须始终在循环中调用,并检查其返回值以确定读取了多少字节。如果您需要进一步的帮助,请提供minimal reproducible example。

标签: c linux sockets client-server


【解决方案1】:

您忽略了read() 返回的计数。它可以是 -1(表示错误)或零(表示流结束)或正数(表示接收了多少字节)。您不能假设 read() 会填满缓冲区,或者单个 send() 或 write() 对应于单个 recv() 或 read()。

详细说明:

write(client_socket_filedescriptor, message, sizeof(message));

您只发送四个字节,即指针的大小。而且您忽略了返回值。应该是

int count = write(client_socket_filedescriptor, message, strlen(message));
if (count == -1)
    perror("write"); // or better

char* message = "<query>\n";

read(socket_filedescriptor, buffer, sizeof(buffer));

应该是这样的

int count = read(socket_filedescriptor, buffer, sizeof(buffer));
if (count == -1)
    perror("read"); // or better
else if (count == 0)
    ; // end of stream: the peer has disconnected: close the socket and stop reading
else

回到你的代码:

printf("%s", buffer);

应该是这样的

printf("%.*s", count, buffer);

我打算用strcmp()

您应该计划使用strncmp(),上面的count 作为长度参数。在任何情况下,您都不能假设输入以 null 结尾,除非您 (a) 确保发送 null,但您不是,并且 (b) 编写一个读取循环,当您读取它时停止。

【讨论】:

  • 您提供的 printf 语句将缓冲区和消息变量打印为相同,但是当我删除您的 .* 语法以及计数(仅在 printf 中)时,我再次得到旧的输出,这意味着您的代码只是格式化 printf 语句,但缓冲区和消息从不包含相同的字符串。有没有办法确保我只阅读&lt;query&gt;\n 而不是一些额外的奇怪字符?
  • @lufork 你没有收到任何“额外奇怪的字符”。它们已经在那里,您打印它们是因为您的 printf() 调用不正确。我给出的printf() 语句是正确的,因为它将输出的内容限制为实际接收的内容,即count 字节。在复制或以其他方式处理此缓冲区时,您应该使用相同的上限,无论您可能拥有哪些未发布的代码,而不是假设read() 填充了缓冲区,正如我已经说过的。我只能评论你实际发布的代码。
  • 哦,有道理。谢谢。
猜你喜欢
  • 2020-07-10
  • 1970-01-01
  • 1970-01-01
  • 2012-12-14
  • 1970-01-01
  • 1970-01-01
  • 2018-06-30
  • 1970-01-01
  • 2011-10-22
相关资源
最近更新 更多