Данные сокета повреждены во время передачи по TCP / IP - PullRequest
3 голосов
/ 23 ноября 2010

Когда я отправляю данные через предварительно подключенный сокет TCP-IP, я вижу, что данные повреждены.

Пример:

Station1 отправляет данные на Station2.Я распечатал данные перед отправкой (на S1) и после получения (на S2).Ниже приведено сообщение:

S1: отправленные данные ACK
S2: полученные данные AC�����

Не уверены, в чем проблема.Я даже очистил буфер символов перед отправкой данных (на S1) и перед получением (на S2).

Любая подсказка / информация для вышеупомянутого была бы очень полезной.

Ответы [ 3 ]

4 голосов
/ 23 ноября 2010

Обычно это результат чего-то вроде:

/* BAD CODE */
const char* ack = "ACK";
err = write( sockfd, ack, strlen( ack )); /* sender */
/* ... */
char buf[SOME_SIZE]
readb = read( sockfd, buf, SOME_SIZE ); /* receiver */
printf( "%s", buf );

Проблема с кодом выше заключается в том, что отправитель записывает только три (3) байта в сокет.Это не включает в себя строку нулевого терминатора.Затем получатель получает данные и либо вообще не проверяет возвращаемое значение системного вызова, либо / и слепо печатает полученные данные.printf будет печатать все, пока не найдет нулевой байт в памяти.

Редактировать:

Основываясь на ваших комментариях, я думаю, вы предполагаете, что один send(2) через сокет TCP должен получиться один recv(2) на другом конце с соответствующим количеством байтов (я предполагаю, что это то, что вы подразумеваете под "числом прочитанных байтов, которое является неправильным").Это не в случае с TCP, хотя.Вы должны рассматривать сокет как поток, который может дать вам куски произвольного размера того, что было отправлено вам.Ваша задача собрать их вместе и распознать границы сообщений приложения.Это просто означает, что вы всегда читаете из сокета в цикле (не считая неблокирующих проектов с select(2) и друзьями - это отдельная тема).

Два принятых протокола уровня приложенияВозможны следующие варианты:

  • Связь через предопределенные сообщения фиксированной длины - так вы будете читать, пока не получите столько байтов из сокета.Простой.
  • Включение типа сообщения и / или длины сообщения в само сообщение - обычно это делается с заголовком сообщения фиксированной длины, за которым следует различная полезная нагрузка сообщения.Читайте, пока не получите полный заголовок, затем переключите / отправьте / продолжайте чтение в зависимости от типа / длины.

Не забывайте о endianess - сети, такие как сетевой порядок байтов .

2 голосов
/ 23 ноября 2010

Вы уверены, что получили все сообщение сразу?Поскольку TCP является потоковым протоколом, данные, которые вы читаете на Station2, могут быть небольшими порциями данных.Вы должны посмотреть, сколько данных функция recv () поместила в ваш буфер.

Например, при первом вызове recv () может появиться «AC», а затем следующий вызов может дать вамостальные данные "К"

0 голосов
/ 01 июля 2016

На стороне клиента я посылаю строку в сокет:

char message[200];

/*string to be sent*/
strcpy(message, "Hi PQRS, How are you!?");

/*send string to server's socket*/
if( send(socket_desc , message , strlen(message)+1 , 0) < 0)
    {
        puts("Send failed");
        return 1;
    }
puts("Data Sent\n");

Обратите внимание, как я прохожу

'strlen (сообщение) + 1'

, чтобы учесть разделитель, то есть '\ 0' вместо

STRLEN (сообщение) '

Это обеспечивает конец строки и отсутствие дополнительных данных.

Это будет работать независимо от размера массива символов на стороне сервера, если он равен или больше входящей строки, чтобы вместить его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...