【问题标题】:How to add null termination in socket stream buffer. C如何在套接字流缓冲区中添加空终止。 C
【发布时间】:2017-09-19 09:59:10
【问题描述】:

我已经成功地用 C 创建了一个 TCP 客户端/服务器模型。 一切正常,所以我不希望这个问题被误认为是关于如何用 C 编写 TCP 客户端/服务器。

我想要的只是通过流发送一个 NullTerminator(大小为一个字节)。

假设客户端仅发送而服务器正在接收。 我开始使用以下代码,但它有一些问题(我正在寻找一些帮助)

/* client code*/
        strcpy(stringToSend,argv[i]);
        strcat(stringToSend,argv[i+1]);
        strcat(stringToSend,"\\0");  //note that double '\\' refers on escaping the '\'
        strcat(stringToSend,argv[i+2]);
        send(mySocket, stringToSend, strlen(stringToSend), 0);
/* client code*/

但是快速浏览一下下面的代码(及其结果),它对我正在处理的问题是不言自明的:

#include <stdio.h>

int main(){
    printf("Null in ASCII is <%d>\n", ((char) 0));
    printf("Size of null is <%ld>\n", sizeof((char)0));

    printf("Size of this \\0 is <%ld>\n", sizeof("\0"));
    return 0;
}

终端输出:

bash$>./test
Null in ASCII is <0>
Size of null is <1>
Size of this \0 is <2>
bash$>

简而言之,strcat(stringToSend,"\\0"); 我只是将字符 '\''0' 添加到字符串中,仅此而已。

我尝试在客户端使用strcat(stringToSend,(char) 0) 在字符串中附加空字符(1 个字节)以发送到流,但我遇到了strcatstrcpy 需要指针才能工作而不是INT((char) 0 是,我不认为这也是解决问题的方法。

我知道每个字符串本身都是空终止的,我不是在寻找这些信息。我所尝试的只是将我自己的意愿附加到流中,这个空终止符在特定点处有一个字节。还有其他我不知道的功能可以帮助我做到这一点吗?

感谢您的宝贵时间!

【问题讨论】:

  • 我认为你误解了str* 函数......这些库函数不知道字符串有多长......每次调用这些函数时,它们(重新)计算字符串长度根据字节流中的第一个 NUL 字符...考虑使用memcpy,否则当您组合字符串时,您的 NUL 字符将被覆盖。

标签: c sockets tcp null stream


【解决方案1】:
send(mySocket, stringToSend, strlen(stringToSend), 0);

问题就在这里。缓冲区中已经有一个尾随 null 可以正常工作,但您没有发送它。试试这个:

send(mySocket, stringToSend, strlen(stringToSend)+1, 0);

你也在误导自己:

printf("Size of this \\0 is <%ld>\n", sizeof("\0"));

打印sizeof "\0",而不是sizeof "\\0",这是你想要的,应该是3。这都无关紧要。

【讨论】:

    【解决方案2】:

    不要逃避 \0

    char *s = "\0";
    send(mySocket,s,1,0);
    

    【讨论】:

    • 如果您尝试sizeof("\0");,您将看到这是 2 个字节。另一方面,空终止符是 1 个字节。 (它是我在我的原始帖子中发布的终端输出)
    • 但是由于send中的'1'参数,只发送了一个字节。
    • a.k.a '\' 因为 s 指向一个由 '\' 和 '0' 字符组成的字符串,而不是一个空终止符。
    • C 中的字符串会自动以 NULL 结尾,因此大小不是 2,因为文字 "\0" - 你可以使 s = "" 大小为 1 而不是 2 NULL字符
    • 或者干脆char c = '\0'; send( s, &amp;c, 1, 0 );
    【解决方案3】:

    使用

    memcpy(your_buffer,your_string,strlen(your_string)+1);/*this copies a 
    string with its null terminator,
    for the next string if your_buffer has allocated enough
    memory space (more than strlen(your_string)+strlen(your_other_string)+2*(NULL terminators) 
    then:*/
    memcpy(your_buffer+strlen(your_string)+1,your_other_string,strlen(your_other_string)+1);
    // now your_buffer contains your 2 strings with their null terminators
    send(your_socket, your_buffer, (strlen(your_string)+strlen(your_other_string)+2)*sizeof(char), 0);//You've now sent your two strings with their null terminators to your client
    

    现在这样:'\0' == 1 字节 零位(仅当您的机器实现了很可能发生的 C 数据类型标准但不要不要指望这个)。

    如果遵循标准,则:“/0”是指向某些字符所在的内存区域的指针,更具体地说,如果我没记错的话,后面是一个零字节,后面是一个零字节, 一个“nulled null”。

    PS1:如果您以您的方式发送服务器“//0”,它不会看到 1 个字节的“/0”,其 ASCII 十六进制等于 00,而是 1 个字节的“//”,即 2F ,以及 '0' 之一,即 30,因此请谨慎操作。

    PS2:这是我第一次回答,所以如果我需要任何更正,请随时指出。

    PS3:如果我回答了你的问题,别忘了接受。

    【讨论】:

    • 仅当您的 C 编译器 实现了 C 数据类型标准,这是必需的
    • 我的意思是机器编译器实现的数据类型可能比标准要求的要大,这可能会不时发生,不是 char 而是一般来说,对吧?
    • 另外,你不应该对我的第一篇文章投反对票 :'(他 100% 来自我的大学,而且他已经在课堂上以 50-70% 的概率问过这个问题。另外,我想我已经让他明白了。
    • Stack Exchange 社区,不允许声望低于 125 的成员影响帖子的得分。我有 58 个。感谢您的努力并感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-09
    相关资源
    最近更新 更多