C - 套接字通信(TCP)

时间:2014-10-26 09:46:33

标签: c sockets tcp

我试图通过TCP连接传递结构变量,但我无法理解哪个是问题。我得到变量命令和id,但是当我读取用户名变量(以及之后的那些)时,printf没有给出结果。

typedef struct _msg{ // 4+4+20+20+44+200+8=300
    int command;
    int id;
    char username[20];
    char password[20];
    char subject[44];
    char text[200];
    time_t timestamp;
} msg;




msg* get_msg(int client_socket){
     char *auxString= (char*) calloc (1, sizeof(time_t));
      msg *auxMsg= (msg*) calloc(1,sizeof(msg));

     read(client_socket, auxString , sizeof(auxMsg->command));
     auxMsg->command=strtol(auxString,NULL,10);
     printf("%d\n", auxMsg->command);
     read(client_socket, auxString, sizeof(auxMsg->id));
     auxMsg->id=strtol(auxString,NULL,10);
     printf("%d\n", auxMsg->id);

     read(client_socket, auxMsg->username, sizeof(auxMsg->username));
     printf("%s\n", auxMsg->username);
     read(client_socket, auxMsg->password, sizeof(auxMsg->password));
     printf("%s\n", auxMsg->password);
     read(client_socket, auxMsg->subject, sizeof(auxMsg->subject));
     printf("%s\n", auxMsg->subject);
     read(client_socket, auxMsg->text, sizeof(auxMsg->text));
     printf("%s\n", auxMsg->text);

     read(client_socket, auxString , sizeof(auxMsg->timestamp));
     auxMsg->timestamp=strtol(auxString,NULL,10);
     printMsg(auxMsg);
     return auxMsg;
 }

 int send_msg(int client_socket, int command, int id, char* username, char* password, char*subject, char*text, time_t timestamp){
     char* auxString=(char*) calloc (1,sizeof(time_t));

     sprintf(auxString,"%d",command);
     write(client_socket,auxString,sizeof(int));
     sprintf(auxString,"%d",id);
     write(client_socket,auxString,sizeof(int));

     write(client_socket,username,sizeof(username));
     write(client_socket,password,sizeof(password));
     write(client_socket,subject,sizeof(subject));
     write(client_socket,text,sizeof(text));

     sprintf(auxString,"%d",command);
     write(client_socket, auxString, sizeof(time_t));

     return SUCCESS;
 }

1 个答案:

答案 0 :(得分:1)

您的struct似乎包含固定长度的字符串字段,但在send_msg函数中,您只是传递指针。

因此,当您使用sizeof时,您只需传递指针的大小(通常在32位系统上为4,在64位系统上为8) 字符串的长度

我强烈建议您更改send_msg函数,以便它还需要msg*指针而不是单个字段,然后使用单独的函数从这些字段构建此类结构。

完成此操作后,您的send_msg函数将简化为:

ssize_t send_msg(int client_socket, msg *m) {
    return write(client_socket, m, sizeof(msg));
}

同样get_msg()会缩减为:

msg *get_msg(int client_socket) {
    msg *m = malloc(sizeof(msg));
    if (m) {
        char *p = (char *)m;
        ssize_t r = 0;
        size_t n = sizeof(msg);
        while ((r = read(client_socket, p, n)) > 0) {
            n -= r;
            p += r;
        }
        if (r == -1) { /* an error occurred */
            free(m);
            m = NULL;
        }
    }
    return m;
}

即。 (最多)每次调用readwrite,其中int字段以二进制形式传输。 get_msg函数显示了在获得整个结构之前如何继续阅读 - send_msg函数理想情况下看起来也一样。

但是你应该注意这里有一些注意事项:

首先,传输的数据将始终是struct msg的完整大小,即使其中的字符串未填充其缓冲区。更优化的协议将传输字符串长度,然后传输字符串数据。

其次,二进制数据的格式将取决于体系结构,因此如果一端是little-endian而另一端是big-endian,则代码将无法工作。然而,后者可以通过使用htonl()和相关函数来简单地修复,以便在传输之前将二进制字段转换为规范的“网络顺序”,并在收到时转换回ntohl()