从结构,套接字编程发送数据

时间:2013-11-15 11:39:01

标签: c sockets struct send recv

我有一个学校的任务,一部分是使用套接字编程从客户端向服务器发送一组int,chars 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 个答案:

答案 0 :(得分:5)

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

这是一个陷阱的第一个原因是,在你的情况下,例如,其中一个元素是一个指针。除非在极少数情况下,接收器将获得在该端无用的指针 - 指针指向对发送过程有效的内存。

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

你最好的选择是单独发送每个字段,即使这很痛苦。通过为此结构创建专用的发送器和接收器功能,您可以通过在代码中应用一些面向对象的设计来减轻痛苦。这些函数对内容和顺序有深入的了解,并将其打包成较小的发送(在char *的情况下,可能需要在字符串数据之前包含一个长度)。

如我所描述的打包发送只要结构没有从套接字的一侧改变到另一端,但你可能想要警惕在一端有不同版本的结构。说一个新的(或不存在的)领域。要处理此问题,您可以考虑标记您发送的数据(而不是假设“首先我们发送a,然后b等。”。

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