2013-11-15 35 views
1

我有一个学校的任务,一部分是发送一套整数,字符char *从客户端到服务器使用套接字编程。发送整数或字符工作得很好,但有什么办法可以将整个结构作为一个包发送吗?阅读关于序列化,但我似乎无法使其工作。这里有一个代码片段:发送数据从一个结构,套接字编程

The struct looks like this: 
struct Msg 
{ 
     int a; 
     char b; 
     char *user; 
}; 

Client: 
init variables and such... 
int netcom(char* ip, int port) { 
    sd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 
    // clear the structure 
    bzero(&serveraddr, sizeof(struct sockaddr_in)); 
    serveraddr.sin_family = AF_INET; 
    // add the server adress 
    inet_pton(AF_INET, ip, &serveraddr.sin_addr); 
    // add the port number 
    serveraddr.sin_port = htons(port); 
    // connect 
    connect (sd,(struct sockaddr*)&serveraddr, sizeof(struct sockaddr_in)); 
} 

int sendPkg(struct Msg msg) { 
    send(sd, &msg, sizeof(msg), 0); 
} 

和接收这样长相的服务器的一部分:

char buf[100]; 
recv(sd[i], buf, sizeof(buf)-1, 0); 

客户发送完美的罚款,并接收服务器的罚款。但我不知道我要发送什么,以及如何正确阅读。所以这是我的问题。如何使用套接字正确发送来自struct的数据。

+1

您需要阅读http://en.wikipedia.org/wiki/Serialization。无法发送指针。即char * –

+1

另外,TCP是一个STREAM服务,而recv()返回一个你需要使用的值。 –

回答

5

直接发送一个结构看起来很吸引人,因为你可以在一次调用中完成它......而且更糟糕的是:有时候它实际上会工作得很好!尽管这是一个陷阱。

这是一个陷阱的第一个原因是,例如,在你的情况下,其中一个元素是一个指针。除非常罕见的情况,接收者将得到那个在这方面无用的指针 - 指针指向对发送进程有效的内存。

第二个也是不太明显的原因是这个陷阱是一个套接字一侧的结构布局(在内存中)在另一侧可能不完全相同。这是机器体系结构和编译器设置的一个功能,因此相信它会“一切正常”并不安全。这个陷阱很容易脱离一段时间,特别是在开发过程中,您可能在测试的每一侧都有兼容的体系结构。

最好的办法是单独发送每个字段,即使这很痛苦。通过为代码创建一个专用的发送者和接收者函数,您可以通过在代码中应用一些面向对象的设计来减少它的痛苦。这些功能对内容和订单有深入的了解,并将其打包成更小的发送(如果您的文件为char *,可能需要在字符串数据之前包含一个长度)。

只要结构没有从套接字的一端改变到另一端,我描述的打包发送就没有问题,但是您可能希望在一端具有不同版本的结构时保持警惕。 ..说一个新的(或不存在的)领域。为了解决这个问题,你可以考虑标记你发送的数据(而不是假设“首先我们发送a,然后b等)”。

查看许多JSON库来管理序列化将是有益的。这为您提供了一种易于阅读的格式,可解决我在此处介绍的所有问题,并且几乎可为所有常见编程语言提供JSON库。