Похоже, вы используете потоковый сокет (SOCK_STREAM
, т.е. TCP).Потоковый сокет - это в основном (с точки зрения вашей программы) просто двунаправленный канал.
Нет понятия «сообщения», кроме того, что навязывает ваше приложение.Сокет просто отправляет и получает один длинный поток байтов.write(fd, "foo", 3); write(fd, "bar", 3);
имеет тот же эффект, что и write(fd, "foobar", 6);
.Он отправляет одни и те же байты в том же порядке.
Если вы хотите, чтобы ваши потоки передавали несколько отдельных сообщений, вам нужно как-то кодировать эти границы сообщений.
- Например, вы можетерешите, что каждое сообщение имеет длину ровно 100 байт, а затем всегда отправляете / получаете ровно 100 байт.
- Или вы можете пометить конец сообщения явным ограничителем (например,
'\0'
).Получающий код затем должен был бы зацикливаться, пока не увидит '\0'
. - Или вы можете отправить поле длины в качестве первой части каждого сообщения;таким образом, принимающий код заранее знает, сколько байтов ему нужно выделить и прочитать.
Этот комментарий в вашем коде означает, что вы выбрали вариант 1:
/* All messages are 9 bytes. */
Но, очевидно,в отправляющем коде есть ошибка, потому что он пытается передать сообщение длиной более 9 байтов, что, конечно, затем интерпретируется как несколько сообщений.Если клиент отправляет 12 байтов, то это сообщение из 9 байтов, за которым следует другое (неполное) сообщение из 3 байтов." В настоящее время моя клиентская часть работает отлично "?Нет, это не так;по крайней мере, если ваш принимаемый код правильный.
Еще одна проблема:
printf("[DEBUG] Client username is %s.\n", username);
%s
ожидает строку C, то есть последовательность символов с нулевым символом в конце.username
не имеет терминатора NUL (если только клиент не решил явно отправить '\0'
байт как часть сообщения).На самом деле, пользователи recv_msg
не могут сказать, сколько данных было получено.Если это всегда ровно 9 байтов,
printf("%.9s", username);
будет работать, но recv_msg
не гарантирует, что это так:
int n = read(sockfd, msg, 9);
Он просто игнорирует n
,так что все или части msg
могут быть неинициализированы, а вызывающий код не может сказать.