Проверка состояния CR / LF в C - PullRequest
1 голос
/ 10 мая 2011

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

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

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

TCP-СЕРВЕР

while(1)
{
    socket = accept(server_socket, (struct sockaddr *)&client_address, (socklen_t)&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 () ждать, пока она не получит все символы от клиента, а затем отправить ответ клиенту.

Буду признателен за любые предложения

Привет

Ответы [ 3 ]

1 голос
/ 10 мая 2011

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

1 голос
/ 10 мая 2011

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

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 ждать, пока буфер заполнится, прежде чем вернуться. Он будет ждать до тех пор, пока не станет доступно несколько байтов, а затем вернется. То же самое относится и к отправке, кстати. Вы не можете предположить одним вызовом, что все ваши байты действительно были отправлены. Вы также должны поместить send в цикл:

ssize_t totalBytesWritten = 0;
ssize_t bytesWritten = 0;
while (bytesWritten >= 0 && totalBytesWritten < bytesToWrite)
{
    bytesWritten = send(socket, sendBuffer + totalBytesWritten, bytesToWrite - totalBytesWritten, 0);
    if (bytesWritten > 0)
    {
        totalBytesWritten += bytesWritten;
    }
}
if (bytesWritten == -1)
{
    // error
}
1 голос
/ 10 мая 2011

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

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

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

Вместо этого сделайте что-то вроде этого:

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