0

我正在进行一项练习,我需要在客户端和服务器之间建立网络并让它们“交谈”。我需要检查来自客户端的特定响应,然后让服务器采取相应措施。为了从客户端读取数据,我使用了一个在循环中调用 recv() 的函数,直到出现 '\n' 字符,或者没有更多字节要读取。当循环结束时,数组中的最后一个字符设置为 '\0'。函数完成后,我希望得到一个以空结尾的字符串,然后我可以在比较中使用它。这是功能 -

int read_in(int socket, char *buf, int len) {
    char *s = buf;
    int slen = len;
    int c = recv(socket, s, slen, 0);
    while((c>0) && (s[c-1]!='\n')) {
        s+=c; slen-=c;
        c = recv(socket, s, slen, 0);
    }
    if (c<0) {
        return c;
    } else if (c==0) {
        buf[0] = '\0';
    } else {
        s[c-1] = '\0';
    }
    return len-slen;
}

现在,我等待连接,声明一个名为“buf”的数组来存储我使用上述函数读取的内容,然后将 2 个字符串与 strcmp() 进行比较

int connect_d = accept(listener_d, (struct sockaddr *)&client_addr, &address_size);
char buf[255];
read_in(connect_d, buf, sizeof(buf));
if (strcmp("Hello\0", buf) == 0) {
    puts("Hello");
} else {
    puts("Not Hello");
}

我相信“buf”字符串包含“Hello\0”,因此比较应该成功。但它不是。我不知道为什么。但是,如果我使用 strncmp() 比较 2 个字符串的前 5 个字节,则比较通过。但是当我比较前 6 个字节时,它失败了。我想知道在失败的第 6 个字节位置存储了什么。

4

2 回答 2

1

有一些可能性:

  1. 如果您读取的最后一个字符是,则read_in()添加 NUL但如果您在最后一次调用中读取了 0 个字节,则执行. 你应该改变它以保留你以前读过的东西(老实说,如果你的情况就是这样,那也行不通,但我还是想指出这个问题)buf'\n'recv()buf[0] = '\0';s[0] = '\0';strncmp("Hello", buf, 5)
  2. 如果客户端发送多于一行,您可能会收到某事。就像"Hello\nWorld\n"在一次调用中一样read_in(),您将设置buf"Hello\nWorld"
  3. 是windows客户端吗?在这种情况下,您可以收到"Hello\r\n",所以您已经设置c[s-2]'\0'(请注意,这两个字符可能会通过不同的调用来接收recv()
  4. 也许客户不发送"Hello\n""Hello \n"矿石类似的东西

只需添加一个printf()(例如printf( "buf[5] = %x\n", buf[5] & 0xff );)即可查看您收到的具体内容

编辑

既然我们知道服务器接收到"Hallo\r\n",我建议您将其添加到read_in()(以防万一c >= 0)的末尾:

 int buflen = strlen( buf );
 if( buflen > 0 && buf[buflen-1] == '\r' )
      buf[buflen-1] = '\0';
于 2014-06-25T16:49:16.973 回答
-2

很可能服务器只向您发送了五个字节“H”、“e”、“l”、“l”、“o”,而不是一个零字节。strcmp 需要以零字节结尾的字符串(并且 C 编译器将零字节添加到字符串文字中,因此您的 "Hello\0" 毫无意义)。

您要检查返回的字节数是否为 5,并且 memcmp ("Hello", buf, 5) 返回 0。您需要单独检查返回的字节数,否则会像“Hello myfriend”这样的回复解释为“你好”。

于 2014-06-25T16:11:23.837 回答