2009-04-23 5 views
2

У меня есть клиент/серверная программа на C, через которую я передаю файлы клиенту с сервера.socket: клиент ждет даже после получения последнего байта

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

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

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

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

+2

Как вы думаете? – JRL

+0

@JRL давая -1 без какой-либо причины для действительного вопроса очень плохо !!, вопрос правильный. –

+0

@Akash: Я не понимаю, что вы говорите. Если вы говорите, что я дал -1, вы ошибаетесь, я этого не делал. Я просто прокомментировал вопрос, в чем состоял его вопрос. – JRL

ответ

3

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

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

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

EDIT - Я понял это сейчас - это потому, что в этот момент вашего кода родитель также все еще имеет открытый сокет, поэтому он не срывается с ядра. Если после fork() добавить некоторую дополнительную логику:

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

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

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

+0

Спасибо за ваш ответ! are'nt файл, разделяемый как родителем, так и дочерним, после того, как я подключился к ребенку, я думаю, что он должен работать. Кстати, как и сказал, как только клиент получил нулевые байты, он выйдет из его цикла и, наконец, выйдет. Но этого не происходит, ребенок ждет чего-то даже после получения all.i hv также помещает printf в цикл, но он не показывает ничего, пока сервер не будет убит! – mawia

+0

Нет, файл является общим, но дескрипторы файлов являются отдельными. Если вы закрываете его в дочернем, он все равно остается открытым в родительском. Поскольку файл по-прежнему открыт, сервер никогда не отправляет индикатор нулевой длины для конца потока. Я добавил код выше к вашей серверной программе, и тогда все сработало нормально. – Alnitak

0

Вы должны называть что-то вроде: shutdown (s, SD_SEND); закрытие (-а);

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

0

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

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

-1

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

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

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

+0

-1 для полностью фиктивной точки около -1 в середине файла – Alnitak

+0

Один вызов функции за каждый байт действительно сосет! вам нужно сделать лучше. –