2014-10-26 5 views
-1

Я пытаюсь передать структурную переменную через TCP-соединение, но я не могу понять, в чем проблема. Я получаю команду переменных и id, но когда я читаю переменные имени пользователя (и те, что после), printf не дает никаких результатов.C - Связь сокета (TCP)

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; 
} 
+0

Возможно, вам следует показать определение вашей структуры? – Alnitak

+1

Вы должны ** действительно ** заботиться о том, что 'read()' и 'write()' return! Прочитайте документацию по этому вопросу! – alk

+0

TCP - это поток, он ничего не знает о сообщениях. Не ожидайте, что число чтений, необходимое для получения, будет соответствовать количеству записей, отправленных для отправки. – alk

ответ

1

Ваш struct кажется, содержит строки фиксированной длины поля, но в вашей send_msg функции вы просто проездом указатели.

Поэтому при использовании sizeof вы будете просто быть прохождение размер указателя (обычно 4 на 32-битной системе, или 8 на 64-битной системы) вместо длины строки ,

Я бы настоятельно рекомендовал изменить функцию 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; 
} 

т.е. (в лучшем случае) один read или write на вызов, с полями int, переданными в двоичной форме. Функция get_msg показывает, как продолжать чтение, пока вы не получите всю структуру - функция send_msg в идеале будет выглядеть одинаково.

Там есть несколько предостережений здесь, что вы должны знать, хотя:

Во-первых, данные, передаваемые всегда будет полный размер struct msg, даже если строки в нем не заполняют их буферы. Более оптимальный протокол будет передавать длины строк, а затем строковые данные.

Во-вторых, формат двоичных данных будет зависящим от архитектуры, поэтому код не будет работать, если один конец был малознаковым, а другой - большим. Однако последнее может быть тривиально зафиксировано с помощью htonl() и связанных функций для преобразования двоичных полей в канонический «порядок сети» перед передачей и ntohl() для преобразования обратно при получении.

+0

Я разместил структуру! – Gopre

+0

и я работаю над обновлением моего ответа ... – Alnitak

+0

@alk Я уже упоминал об этом в тексте, но теперь я обновил код. – Alnitak

Смежные вопросы