c套接字发送和接收一个int而不是一个char缓冲区

Posted

技术标签:

【中文标题】c套接字发送和接收一个int而不是一个char缓冲区【英文标题】:c socket send and receive an int instead of a char buffer 【发布时间】:2012-08-29 10:28:21 【问题描述】:

1:服务器将文件大小复制到缓冲区并发送:

  snprintf(t_buf, 255, "%" PRIu32, fsize);
  if(send(f_sockd, t_buf, sizeof(t_buf), 0) < 0)
    perror("error on sending file size\n");
    onexit(f_sockd, m_sockd, 0, 2);
  

2:客户端收到文件大小,放入fsize:

  if(recv(f_sockd, t_buf, sizeof(t_buf), 0) < 0)
    perror("error on receiving file size");
    onexit(f_sockd, 0 ,0 ,1);
  
  fsize = atoi(t_buf);

----------------- 上面的代码让我的程序完美运行! 如果我编写这段代码而不是之前的代码,就会出现问题: 1:服务器发送fsize:

  if(send(f_sockd, &fsize, sizeof(fsize), 0) < 0)
    perror("error on sending file size\n");
    onexit(f_sockd, m_sockd, 0, 2);
  

2:客户端收到fsize:

  if(recv(f_sockd, &fsize, sizeof(fsize), 0) < 0)
    perror("error on receiving file size");
    onexit(f_sockd, 0, 0, 1);
  

uint32_t fsize;char t_buf[256];. 问题是第一种方法都可以工作,但第二种方法客户端不会收到所有文件,而只会收到其中的一部分。这段代码有什么问题?谢谢!

【问题讨论】:

Handling Partial return from recv() TCP in C的可能重复 看起来不像,上面的代码就是错的;-)。 客户端和服务器是否在同一台机器上? 只有一部分是什么意思? @hmjd 是的!巴特:你能解释一下为什么吗?:) 我看错了。我认为 fsize 是指向缓冲区的指针。 【参考方案1】:

recv(2) 不一定会填满整个输出缓冲区 - 根据可用数据的多少,它可能会返回更少的字节:

接收调用通常会返回任何可用数据,直至请求的数量,而不是等待接收请求的全部数量。

返回值(当 > 0 时)将是接收到的字节数,因此如果您想确保接收到所有内容,可以在循环中调用它。

或者,您可以传递MSG_WAITALL 标志:

此标志请求操作阻塞,直到满足完整请求。但是,如果捕获到信号、发生错误或断开连接,或者要接收的下一个数据与返回的数据类型不同,则调用返回的数据仍可能少于请求的数据。

所以在你的情况下,你可以这样做:

ssize_t bytes = recv(f_sockd, &fsize, sizeof(fsize), MSG_WAITALL);

if(bytes == sizeof(fsize))

    /* received everything */

else

    /* something went wrong */

【讨论】:

服务器发送20字节,客户端收到1801745249 O.o 为什么?? :(【参考方案2】:

没有更多数据很难判断。

可能是endianness。您应该打印出fsize 的值。

也可能是来自recv() 的部分返回,正如评论中提到的那样。

【讨论】:

小端,我在同一台机器上运行服务器和客户端!

以上是关于c套接字发送和接收一个int而不是一个char缓冲区的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Linux 中创建原始套接字而不缓冲接收数据包?是不是可以?

快速读取 char(不是 char *)作为 C 字符串指针

Python网络编程——修改套接字发送和接收的缓冲区大小

C 是不是发送方法空闲缓冲区?

c++ vector<char> 和套接字

c 接收/发送同一个套接字