c - 截断缓冲区

标签 c sockets

我正在尝试解决一个奇怪的 C 编程问题。

我在客户端程序上输入一个 URL,然后将该 URL 传输到服务器程序。唯一的问题是,当服务器程序收到 URL 时,它丢失了前两个字符。所以,如果 url 是 http://www.google.com服务器报告收到的是“tp://www.google.com”。

奇怪的是,这不是部分发送问题。我正在检查发送的字节数,它声称已发送整条消息。问题是在接收端它只是声称它正在获取一小部分数据。接收方报告它收到了长度为 -2 的消息。这是接收端的代码:

  printf("%s \n", "Connected. Receive length of URL to wget.");
  if ((messageSize = recv(acceptDescriptor, &urlLength, sizeof (int), 0)) == -1) {
    perror("recv URL length");
    exit(1);
  }
  urlSizeInt = atoi(urlLength);
  char url[urlSizeInt];
  printf("%s %d \n", "urlSizeInt: ", urlSizeInt);
  printf("%s \n", "Receive URL to wget.");

  if((messageSize = recv(acceptDescriptor, &url, 13, 0)) == -1) {
    perror("recv URL");
    exit(1);
  }

发送代码:

  printf("%s \n", "Connected");
  //connected to first stepping stone in the chain.
  //transfer the length of the URL
  if (send(socketDescriptor, urlLengthStr, strlen(urlLengthStr), 0) == -1){
    perror("send URL Length");
    exit(0);
  }

  //transfer the URL
  printf("%s %d \n", "strenlen(url): ",strlen(url));
  printf("%s %s \n", "url: ",url);
  int sent;
  int totalSent=0;
  if((sent=send(socketDescriptor, url, strlen(url), 0))==-1){
      perror("send URL");
      exit(0);
    }

  printf("%s %d \n", "sent: ",sent);


Send Output:
Connected
strenlen(url):  13
url:  http://www.cs
sent:  13

Receive Output:
Connected. Receive length of URL to wget.
urlSizeInt:  13
Receive URL to wget.
messageSize:  11
URL Received:  tp://www.cs

将长度编码为字符发送的代码:

char* url = "http://www.cs";
int urlLength  = strlen(url);
char* urlLengthStr;
sprintf(urlLengthStr, "%d", urlLength);

最佳答案

感谢您发布完整代码。问题在于您发送 UrlLength 的方式。因为您总是 recv sizeof(int) 字节,所以您的第一次读取会消耗已发送 URL 的第一个字节。

从头开始 - 假设您不发送 URL 长度。

问题:URL 的长度可变。接收者怎么知道它什么时候读完了? 解决方案:发送之前的长度

这很好,除非您将长度编码为字符串,因为这会引入另一个问题

问题:URL 长度可能是可变长度(“1”、“12”、“1234”)。接收者怎么知道它什么时候读完了? 解决方案:我们以前不是来过这里吗...

有几种方法可以解决这个递归问题:

解决方案 a:将 URL 长度编码为固定大小的字段。 (您可以只发送 int 的二进制表示,但要注意字节顺序问题 - 或者您可以将其编码为固定宽度的 ascii 字段,例如“00000124”

TX(忽略 JimR 提到的字节顺序问题)

  int urlLength = strlen(url);
  send(socketDescriptor, &urlLength, sizeof(int), 0)

接收:

  int urlLength;
  recv(socketDescriptor, &urlLength, sizeof(int), 0)

解决方案 b:使用终止符(通常为 null 或换行符)来指示 URL 的结尾。只需循环读取字节,直到到达终止符。这也解决了您可能会遇到的“部分接收”问题。

关于c - 截断缓冲区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19233017/

相关文章:

c - 在 C 中读写 .txt 文件

c - 外部数组的地址在编译单元之间不同

c++ - 使用查找表进行坐标转换

c - 区分同一 NAT 后面的多个客户端

Python 仅为主机创建 VPN 连接

c++ - 使用 C++ 套接字编程的最大 TCP 数据包大小

c - 共享内存访问 CUDA 中的垃圾值

c - 为什么 C 预处理器将单词 "linux"解释为常量 "1"?

c++ - 为什么 getservbyname 不返回正确的端口号?

c - 使用套接字的 IPC 中的意外输出