сокет: клиент ждет даже после получения последнего байта - PullRequest
2 голосов
/ 23 апреля 2009

У меня есть клиент-серверная программа на C, с помощью которой я передаю файлы клиенту с сервера.

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

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

Почему клиент не завершает работу при выходе из дочернего сервера?

Здесь вы можете увидеть код сервера здесь и код клиента здесь .

Ответы [ 4 ]

3 голосов
/ 23 апреля 2009

Вы должны убедиться, что вы вызываете shutdown(s, SHUT_WR), а затем close(s) в процессе сервера после отправки всех данных.

Вызов shutdown() сообщает уровню TCP, что больше нет данных для отправки.

ТБХ, я не совсем уверен, почему сам по себе вызов close() также не достигает этого.

РЕДАКТИРОВАТЬ - Я понял это сейчас - это потому, что в этот момент в вашем коде у родителя все еще открыт сокет, поэтому ядро ​​его не разрушает. Если после fork() вы добавите дополнительную логику:

if (p > 0) {
    close(connected);
}

тогда ваш код работает без вызова shutdown().

Если вы используете код, который я отправил в мой ответ на ваш вчерашний вопрос, тогда клиент получит bytes_received отсчет нуля, а затем завершит свой цикл.

0 голосов
/ 23 апреля 2009

Это немного сложно, более подробно было бы неплохо. Вы используете TCP / IP? Поскольку вы говорите о передаче файлов, я предполагаю, что это TCP.

Если вы завершаете процесс на стороне сервера, которому принадлежит сокет, подключенный к клиенту, это должно привести к разрыву соединения. Вызов recv() клиента должен затем завершиться и вернуть -1 (или 0, не уверен на 100%). В противном случае обратите внимание на явное закрытие сокета в процессе основного сервера (не уверен, как вы настроили владение сокетом).

0 голосов
/ 23 апреля 2009

Есть два способа чтения сокетов ...

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

  2. Другим способом является чтение буфера из потока, и этот метод возвращает количество байтов, прочитанных из потока, и если он возвращает 0, это означает его конец потока.

0 голосов
/ 23 апреля 2009

Вы должны звонить что-то вроде: выключение (с, SD_SEND); closesocket (с); * +1001 *

на сервере после отправки файла для закрытия сокета.

...