分别通过 TCP 套接字发送和接收字符串 [英] Sending and receiving strings over TCP socket separately

查看:95
本文介绍了分别通过 TCP 套接字发送和接收字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 TCP 服务器和客户端,有一个已建立的套接字.假设我有以下情况:

I have a TCP server and client, with an established socket. Let's say I have the following case:

服务器:

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()... 因为我已经完成了发送.

Expected result: I want to receive each string separately (as I am saving them in different variables), instead the first recv() gets both the fn "John" and ln "Doe" concatenated "JohnDoe", and the program gets stuck on the second recv()... since I've already done the sending.

我尝试了以下方法:- 将 \0 添加到 fn 和 ln 字符串中,如下所示:

I tried the following: - Adding \0 to the fn and ln strings like so:

char *fn = "John\0";
char *ln = "Doe\0";

但问题依然存在.

是否可以强加某种条件,以便分别接收每个字符串?

Is there some sort of condition I can impose so each string is received separately?

编辑以添加更多问题:

1) 为什么它在某些情况下实际上是分开发送的,而其他情况下是联合发送的?

1) Why does it in certain instances actually send them separately, and others sends them jointly?

2) 我应该使用 send() 和 recv() 替代吗?在我代码的其他一些部分,它似乎是自我调节的,并且只在正确的时间接收正确的字符串而无需我检查.这行得通吗?

2) Should I send() and recv() alternatively maybe? In some other parts of my code, it seems it is self regulating and only receiving the right strings at the right time without me having to check. Does this do the trick?

3) 关于发送带有我将要发送的字符串长度的标头,我如何解析传入的字符串以知道在哪里拆分?任何例子都会很棒.

3) About sending a header with the length of the string I am about to send, how do I parse the incoming string to know where to split? Any examples would be great.

4) 我一定会检查我得到的东西是否比我的缓冲区大,感谢您指出.

4) I will definitely check if I'm getting something bigger than my buffer, thanks for pointing to it.

编辑 2:

5) 因为我总是把东西放在一个大小为 512 的缓冲区字符数组中.即使我发送一个 1 个字母的字符串,难道每个发送操作都不应该占用缓冲区的完整大小吗?这就是令人困惑的地方.我有John",但我将它放在一个大小为 512 的数组中并发送它,这不应该填满发送缓冲区,因此 recv() 函数还通过拉动整个大小数组来清空网络缓冲区512?

5) Since I'm always putting things in a buffer char array of size 512. Shouldn't every send operation take the full size of the buffer even if I am sending a 1 letter string? That's what confusing. I have "John" but I'm putting it in an array of size 512 and sending it, shouldn't that fill up the send buffer, and so the recv() function empties the network buffer by also pulling the whole array of size 512?

推荐答案

首先,当客户端调用recv(*socket, buffer, sizeof(buffer), 0);时,会收到最多 sizeof(buffer) 个字符(此处为 512)来自网络.这是来自网络缓冲区,与服务器上调用了多少次 send 无关.recv 不会查找 \0 或任何其他字符 - 它是从网络缓冲区中提取的二进制文件.它将读取整个网络缓冲区或 sizeof(buffer) 个字符.

First, when the client calls recv(*socket, buffer, sizeof(buffer), 0);, it will receive up to sizeof(buffer) characters (here, 512) from the network. This is from the network buffer, and has nothing to do with how many times send has been called on the server. recv does not look for \0 or any other character - it's a binary pull from the network buffer. It will read either the entire network buffer, or sizeof(buffer) characters.

您需要检查第一个 recv 以查看它是否同时具有名字和姓氏并进行适当处理.

You need to check in the first recv to see if it has both the first and last name and handle it appropriately.

您可以通过让服务器将字符串的长度作为流的前几个字节(头")发送,或者通过扫描接收到的数据查看是否有两个字符串来实现.

You can do so either by having the server send the length of the strings as the first few bytes of a stream (a "header"), or by scanning the received data to see if there are two strings.

您真的需要在调用 recv 时执行检查 - 如果字符串长度超过 512 字节怎么办?然后你需要多次调用 recv 来获取字符串.如果你得到第一个字符串,而只有第二个字符串的一半怎么办?通常这两种情况只在处理大量数据时发生,但我以前在我自己的代码中看到过这种情况,所以最好在 recv 上结合良好的检查,即使在处理像这样的小字符串时这个.如果您尽早练习良好的编码策略,以后就不会遇到那么多麻烦.

You really need to perform checks whenever you call recv - what if the string is longer than 512 bytes? Then you need to call recv multiple time sto get the string. And what if you get the first string, and only half of the second string? Usually these two cases only happen when dealing with larger amounts of data, but I've seen it happen in my own code before, so it's best to incorporate good checks on recv even when dealing with small strings like this. If you practice good coding tactics early on you won't have as many headaches down the road.

这篇关于分别通过 TCP 套接字发送和接收字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆