我有一个TCP服务器和一个带有已建立套接字的客户端。假设我有以下情况:
服务器:
char *fn = "John";
char *ln = "Doe";
char buffer[512];
strcpy(buffer, fn);
send(*socket, buffer, strlen(buffer), 0);
strcpy(buffer, ln);
send(*socket, buffer, strlen(buffer), 0);
客户:
char *fn;
char *ln;
char buffer[512];
bytes = recv(*socket, buffer, sizeof(buffer), 0);
buffer[bytes] = '\0';
strcpy(fn, buffer);
bytes = recv(*socket, buffer, sizeof(buffer), 0);
buffer[bytes] = '\0';
strcpy(ln, buffer);
printf("%s", fn);
printf("%s", ln);
预期结果:
我想分别接收每个字符串(因为我将它们保存在不同的变量中),而是第一个recv()同时获取了fn“John”和ln“Doe”并置为“JohnDoe”,并且该程序卡在了第二个recv上()...,因为我已经完成了发送。
我尝试了以下方法:
-在fn和ln字符串中添加\0,如下所示:
char *fn = "John\0";
char *ln = "Doe\0";
但是问题仍然存在。
我可以施加某种条件,以便分别接收每个字符串吗?
编辑以添加更多问题:
1)为什么在某些情况下实际上将它们单独发送,而其他情况则将它们共同发送?
2)我应该send()和recv()交替吗?在我的代码的其他部分,这似乎是自我调节的,并且仅在正确的时间接收正确的字符串,而无需我检查。这能达到目的吗?
3)关于发送带有我要发送的字符串长度的 header ,如何解析传入的字符串以知道在哪里拆分?任何例子都很好。
4)我肯定会检查我是否得到比缓冲区更大的东西,感谢您指出它。
编辑2:
5)因为我总是把东西放在大小为512的缓冲区char数组中。即使我发送的是1个字母的字符串,每个发送操作也不应该占用缓冲区的全部大小吗?那真是令人困惑。我有“John”,但我将其放入大小为512的数组中进行发送,不应该填满发送缓冲区,因此recv()函数也通过拉取整个大小的数组来清空网络缓冲区512?
最佳答案
首先,当客户端调用recv(*socket, buffer, sizeof(buffer), 0);
时,它将从网络接收多达sizeof(buffer)个字符(此处为512)。这来自网络缓冲区,与在服务器上调用send
的次数无关。 recv
不会查找\0
或任何其他字符-它是从网络缓冲区中提取的二进制文件。它将读取整个网络缓冲区或sizeof(buffer)
字符。
您需要 checkin 第一个recv
来查看它是否同时具有名字和姓氏,并进行适当的处理。
您可以通过使服务器将字符串的长度作为流的前几个字节(“ header ”)发送,或者通过扫描接收到的数据以查看是否有两个字符串来做到这一点。
每当调用recv
时,您实际上都需要执行检查-如果字符串长于512个字节,该怎么办?然后,您需要多次调用recv
来获取字符串。如果得到第一个字符串,而只有第二个字符串的一半,该怎么办?通常,这两种情况仅在处理大量数据时才会发生,但是我之前已经在我自己的代码中看到过,因此即使在处理像这样的小字符串时,最好也对recv
进行良好的检查。如果您尽早练习良好的编码策略,那么您将不会有太多麻烦。