在套接字中发送多个发送/接收

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 选项。

【讨论】:

以上是关于在套接字中发送多个发送/接收的主要内容,如果未能解决你的问题,请参考以下文章

在同一个套接字上对发送/接收的并行调用是不是有效?

可以在数据报套接字中使用发送和接收吗?

python套接字接收二进制数据

简单的UDP套接字代码,发送和接收消息

Xamarin/WinForms 客户端在双线程架构中发送/接收时无法连接到套接字

如何在java中使用套接字发送/接收对象[重复]