如何通过网络套接字可移植地发送C结构?

use*_*758 6 c portability

假设我有一个C结构定义如下:

typedef struct servData {
    char max_word[MAX_WORD];
    char min_word[MAX_WORD];
    int word_count ;
} servSendData ;
Run Code Online (Sandbox Code Playgroud)

其中'MAX_WORD'可以是任何值.现在,如果我有这个结构的实例:

servSendData  myData ;
Run Code Online (Sandbox Code Playgroud)

如果我填充此实例然后通过网络发送它,考虑到我希望我的服务器以及客户端在64位系统或32位系统上运行,是否会出现任何可移植性问题.

我将发送和接收数据如下:

//server side
strcpy(myData.max_word, "some large word") ;
strcpy(myData.min_word, "small") ;
myData.word_count=100 ;
send(sockFd, (char*)&myData, sizeof(myData);

//client side
recv(sockFd, (char*)&myData, sizeof(myData);
printf("large word is %s\n", myData.max_word) ;
printf("small word is %s\n", myData.min_word) ;
printf("total words is %d\n", myData.word_count) ;
Run Code Online (Sandbox Code Playgroud)

Tim*_*Čas 5

是的,肯定是便携性的问题.

即使在同一平台上的不同编译器之间,结构成员的对齐也可能不同,更不用说不同的平台了.而这一切都假设所有这些sizeof(int)都是相同的(虽然被授予,但通常是---但你真的想依靠"通常"并希望最好吗?).

即使MAX_WORD在两台计算机上都是相同的(即我假设它们是从这里开始;如果它们不是,那么你在这里遇到麻烦).

您需要做的是分别发送(和接收)每个字段.还有sizeof(int)endianness 的问题,所以我添加了一个htonl()从系统转换为网络字节顺序的调用(反函数是ntohl()).它们都返回uint32_t具有固定的,已知的尺寸.

send(sockFd, myData.max_word, sizeof(myData.max_word)); // or just MAX_WORD
send(sockFd, myData.min_word, sizeof(myData.min_word));
uint32_t count = htonl(myData.word_count); // convert to network byte order
send(sockFd, &count, sizeof(count));

// error handling!
if((ret = recv(sockFd, myData.max_word, sizeof(myData.max_word))) != sizeof(myData.max_word))
{
    // handle error or read more data
}
... // and so on
// remember to convert back from network byte order on recv!
// also keep in mind the third field is now `uint32_t`, and not `int` in the stream
Run Code Online (Sandbox Code Playgroud)

  • 注意:你的`if`条件是错误的.即使这是真的,也不会是错误的.错误将以"-1"表示. (2认同)

Jac*_*son 1

正如其他依赖者所说,在具有不同编译器/字大小/和字节序结构的不同机器之间复制 C 结构存在真正的问题。解决此问题的一种常见方法是将数据转换为与机器无关的格式,通过网络传输,然后将其转换回接收器上的结构。这是一个非常常见的要求,以至于已经存在多种技术来做到这一点 - 我最初想到的两种技术是gsoaprpcgen,尽管可能还有许多其他选择。

我主要使用 gsoap,在完成最初的学习曲线后,您可以开发出强大的解决方案,该解决方案可以很好地扩展(具有多个线程),并且可以为您处理网络和数据转换。

如果您不想走这条路,那么最安全的方法是编写将数据转换为标准字符串格式或从标准字符串格式转换为数据的例程(如果您遇到 Unicode 问题,您还需要考虑到这一点)并且然后通过网络发送。