Проверка состояния CR / LF в C

#c #tcp

#c #tcp

Вопрос:

Я тестирую свой эхо-сервер TCP с помощью Telnet, я вижу, что клиент подключается к серверу и отправляет символ, а взамен сервер возвращает клиенту строку.

Теперь моя проблема в том, что с помощью этого recv () в бесконечном цикле я могу получить только один символ (даже если клиент обычно отправляет строку).

Вот как я делаю, чтобы получить дейтаграмму от клиента

TCP-СЕРВЕР

 while(1)
{
    socket = accept(server_socket, (struct sockaddr *)amp;client_address, (socklen_t)amp;client_length);

    recv(socket, recv_buffer, sizeof(recv_buffer), 0);
    printf("Received string from client is %s", recv_buffer);

    /*then I send my string to the client*/
    send(socket, send_buffer, sizeof(send_buffer), 0);
}
  

Моя проблема в том, что моя процедура recv () считывает только один символ, даже если клиент хочет отправить целую строку. Есть ли способ, как я могу заставить эту процедуру recv () подождать, пока она получит все символы от клиента, а затем отправить ответ клиенту.

Любые предложения будут оценены

С уважением

Комментарии:

1. В качестве побочной проблемы … стоит отметить, что Telnet является клиентом терминала, поэтому он собирается передавать на ваш сервер нечто большее, чем просто строку, которую вы вводите в него, поэтому не удивляйтесь, если вы получите некоторые управляющие коды, которые на первый взгляд могут показаться мусором…

2. моя проблема в том, что я получаю только один символ, хотя клиент отправляет мне полную строку, которую я набираю на клиенте telnet вручную. Как только я набираю письмо, оно принимается сервером ma, и мой сервер отправляет текст, который можно увидеть на выводе терминала telnet.

Ответ №1:

Ну, вы делаете что-то неправильно. Посмотрите на определение recv :

 int recv(int s, void *buf, size_t len, int flags); 
  

Таким образом, он получает len количество байтов. Вы передали sizeof(recv_buffer) в качестве параметра len. Теперь я предполагаю, что recv_buffer определяется как char* . Получение sizeof указателя означает, что вы получаете количество байтов, необходимое для хранения этого указателя, вместо памяти, на которую он указывает.

Вместо этого сделайте что-то подобное:

 const int buf_len = 100;
char recv_buffer[buf_len];

recv(socket, recv_buffer, buf_len, 0);
printf("Received string from client is %s", recv_buffer);   
  

Комментарии:

1. Вообще не будет работать — нет гарантии, что строка может быть получена с помощью одного вызова recv().

2. @unapersson: Верно, но усложняет историю. Проблема заключалась в получении sizeof указателя.

3. Я устал от предложенного вами способа, но результат все тот же

Ответ №2:

Вам нужно создать строку, которую вы получаете самостоятельно, в цикле, используя возвращаемое значение recv() , чтобы определить, сколько байт вы на самом деле получили. TCP / IP не гарантирует, что все данные, отправленные при одном вызове на send() , могут быть получены при одном вызове на recv() . И вы должны проверять возвращаемое значение каждой вызываемой вами функции сокетов, чтобы проверить фактическую отправленную / полученную длину и наличие ошибок.

Комментарии:

1. Я проверил возвращаемое значение recv (), и оно показывает мне ‘1’, это означает, что как только я получаю символ, моя функция send () вызывает и отправляет строку.

2. @Devb Вы должны продолжать вызывать recv, пока не получите все ожидаемые символы.

Ответ №3:

Ваш код — это катастрофа (извините за прямоту, но лучше всего говорить прямо).

recv() возвращает количество фактически прочитанных байтов. Не только это, но и то, что это не очистит предыдущее содержимое буфера, и оно будет заполнено до конца буфера, если есть доступные данные. Все это означает, что вы не можете обрабатывать содержимое буфера как строку, завершающуюся нулем.

Вам нужно сделать что-то вроде:

 ssize_t bytesRead = 1;
char recv_buffer[SOME_SIZE];

while (bytesRead > 0)
{
    int bytesRead = recv(socket, recv_buffer, SOME_SIZE, 0);
    if (bytesRead > 0)
    {
        // do something with the bytes.  Note you cannot guarantee that the buffer contains a valid C string.
    }    
}
if (bytesRead == -1)
{
    // report error from errno
}
else
{
    // bytesRead == 0 have reached end of file (i.e. socket closed at other end)
}
  

Нет способа заставить recv дождаться заполнения буфера перед возвратом. Он будет ждать, пока не освободится несколько байтов, а затем вернется. Кстати, то же самое относится и к отправке. Вы не можете предположить с помощью одного вызова для отправки, что все ваши байты действительно были отправлены. Вам также нужно поместить отправку в цикл:

 ssize_t totalBytesWritten = 0;
ssize_t bytesWritten = 0;
while (bytesWritten >= 0 amp;amp; totalBytesWritten < bytesToWrite)
{
    bytesWritten = send(socket, sendBuffer   totalBytesWritten, bytesToWrite - totalBytesWritten, 0);
    if (bytesWritten > 0)
    {
        totalBytesWritten  = bytesWritten;
    }
}
if (bytesWritten == -1)
{
    // error
}
  

Комментарии:

1. Я должен сказать, что после того, как я последовал вашему совету, я все еще не могу получить желаемый результат, для отправки он отлично работает с моим старым кодом. Я все еще понятия не имею