在套接字中发送多个发送/接收
Posted
技术标签:
【中文标题】在套接字中发送多个发送/接收【英文标题】:sending multiple send/recv in socket 【发布时间】:2021-04-08 11:28:20 【问题描述】:我需要澄清一下在套接字程序中使用多个发送/接收。 我的客户端程序如下所示(使用 TCP SOCK_STREAM)。
send(sockfd,"Messgfromlient",15,0);
send(sockfd,"cli1",5,0);
send(sockfd,"cli2",5,0);
send(sockfd,"cli3",5,0);
send(sockfd,"cli4",5,0);
send(sockfd,"cli5",5,0);
服务器程序如下所示。
recv(newsockfd,buf,20,0);
printf("Buffer is %s\n",buf);
当我执行上述程序时,输出如下:
客户端消息:Messgfromlient
我相信缓冲区大小是 20,所以只有一个缓冲区被接收。 在服务器端再添加一个 recv。
char buf[20],buf[20];
------skipped------
recv(newsockfd,buf,20,0);
recv(newsockfd,buf1,20,0);
printf("Client Msg :%s\n",buf);
printf("Client Msg :%s \n",buf1);
输出: 第一次审判:
Client Msg :Messgfromlient
Client Msg :cli2
第二步:
Client Msg :Messgfromlient
Client Msg :cli1
我们可以看到输出中存在一些矛盾, 从客户端看起来所有的消息都被发送了,但是在服务器中,消息将根据 buf 大小接收,这里即使 buf1 的大小为 20,为什么在 buf1 上没有收到'cli3''cli4''cli4'消息?.有没有具体的限制?请澄清这一点。
提前致谢, 拉贾
【问题讨论】:
send()
和recv()
的返回值是多少?你不能忽视这一点。
您正在发送 5 和 15 字节的缓冲区,但在接收时,您正在打印以第一个 NUL
字节 (0x00) 结尾的字符串。如果您保存 recv()
调用的返回值并将它们打印出来,这可能会有所帮助。
传递的len
是允许的最大长度。 recv
也可以返回单个字符或(在非阻塞系统中)-1
。您的“问题”属于进程调度:它取决于在上下文切换之前执行的代码点以及内核已经调度的内容。
'使用 TCP SOCK_STREAM' - 想想这意味着什么!
【参考方案1】:
TCP 是一个基于字节流的协议,它对消息一无所知。您总共发送25
字节,另一端的每个recv
将读取这些字节中的一些。你可以得到 20,你可能会得到1
,然后是19
,你可能会得到5
,然后是4
,然后是11
,然后是5。recv
的大小参数是阅读。
您需要循环,直到您自己阅读整条消息,并且了解您可能会在收到的同一条消息中收到多个“发送”。
【讨论】:
如果两个进程同时通过同一个套接字发送?数据会损坏吗?一个send
是否被阻止直到另一个send
完成?【参考方案2】:
服务器程序如下所示。
recv(newsockfd,buf,20,0);
printf("Buffer is %s\n",buf);
这已经是错误的了。应该是:
int count = recv(newsockfd,buf,20,0);
if (count == -1)
perror("recv"); // please improve this message
close(newsocketfd);
else if (count == 0)
// peer has closed the connection
close(newsockfd);
else
printf("Buffer is %.*s\n",count,buf);
这应该给你足够的提示......
【讨论】:
【参考方案3】:您有 2 个问题:
当您显示结果时,您将在第一个空字节处停止,该字节始终位于“Messgfromlient”之后。可能已经收到更多文本,但您没有显示它。
第二个问题是 TCP 连接是一个流。您可能一次收到所有数据,您可能只收到第一个字节。你不知道它是哪一个,也无法预测它。您需要在应用程序中处理不完整的读取,并且必须处理重试。
但是,您可以让所有数据更有可能在一个数据包中发送,而不是 6 个。查看 TCP_CORK 选项。
【讨论】:
以上是关于在套接字中发送多个发送/接收的主要内容,如果未能解决你的问题,请参考以下文章