| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Сети > Ошибка accept() |
| Автор: VitaminCPP 16.1.2008, 23:16 | ||||
| Есть сервер, есть клиент. Дескриптор сокета хранится в глобальной переменной sock. Вообще, куча глобальных данных, так надо. Если видите переменную и она не обьявлена в коде, значит глобальная. Сервер и клиент запускаются в новом потоке. Сервер:
Клиент:
Вобщем, проблема в следующем: Я запускаю сервер, подключаюсь к нему клиентом через localhost. В глобальной сети программа не тестировалась. Потом, если я закрываю сокеты у клиента и сервера и пытаюсь подключить сокет сервера снова к тому же порту (тоесть запускаю сервер заново), получаю в статус баре строку Failed accept connection(см. вызов accept() у сервера). Код ошибки WSAEINVAL (10022). Другие порты работают. Если я не подключаю клиент, а просто создаю подключение сервера к порту, удаляю его и снова создаю, всё работает. Windows XP, SP2 Visual Studio 2008 Как мне освобождать порт? |
| Автор: onsql 16.1.2008, 23:38 |
| Ну, вообще говоря, в функции void SetUpListener() никак не сигнализируется результат выполнения bind и listen. Могу предположить что во второй запуск bind возвращает что то типа address already in use. |
| Автор: VitaminCPP 17.1.2008, 00:20 |
| Почему не сигнализируется? Есть ведь проверка на SOCKET_ERROR в самой функции и на INVALID_SOCKET после вызова. Я файрволом проверил... Он показывает, что программа закрывает сокет на самом деле. Когда запускаю сервер показывает что порт открыт, когда вызываю функцию - что закрыт... Блин, где же проблема... |
| Автор: onsql 17.1.2008, 00:52 | ||
В упор не вижу где тут печать об ошибке если bind вернет SOCKET_ERROR
Добавлено через 1 минуту и 8 секунд Файрвол - это хорошо. А он показывает TCP соединения в состоянии FIN_WAIT, CLOSE_WAIT? |
| Автор: Олег2005 17.1.2008, 11:39 |
| 3 замечания: listen(sock, 1); - может вызывать проблемы backlog не ставят 1 - может неверно формироваться очередь принятых соединений listen(sock, 5); - это минимально для всех видов стека второе: ShutDownConnection() Зря там такой код - нужно просто делать closesocket() Третье: Для того чтобы выключать и быстро включать сервер без проблем надо на сервере для прослушивающего сокета ставить опцию SO_REUSEADDR |
| Автор: onsql 17.1.2008, 12:05 |
| Если посмотреть на код в самом первом посте, то, думаю, тут происходит следующее: 1. Вызов DoServer. Из него первым делом вызывается SetUpListener() 2. В SetUpListener создается сокет, допустим успешно, переменная sock проинициализирована, не равна INVALID_SOCKET 3. В SetUpListener Вызывается bind, который, допустим, возвращает ошибку address already in use. В этом случае, listen не будет вызван. Никакой печати об этом нет, никаких действий не предпринимается. 4. Далее выход из SetUpListener, возврат в DoServer где проверяется sock на значение INVALID_SOCKET. Но оно в порядке, сокет создан, однако bind на требуемый порт не сделан, listen не вызван. 5. Далее по коду DoServer, поскольку дескриптор сокета валидный, на него делается accept который возвращает ошибку из за условий описанных в п.4. Вот такой сценарий и приводит видимо к описанной автором темы ситуации. |
| Автор: VitaminCPP 17.1.2008, 20:34 |
| onsql, ты прав. проблема в bind, ошибка Address already in use. Попробовал поставить в опциях SO_REUSEADDR , сервер запускается сразу, клиент подключается, но данные не посылаются. Но я уже на верном пути, знаю точно что за ошибка. Тему пока не помечаю как решенную, может еще кто-то чего посоветует... |
| Автор: GrayCardinal 18.1.2008, 20:52 | ||
"Омская 1" рулит |
| Автор: VitaminCPP 21.1.2008, 00:07 |
| ладно, всё. |
| Автор: GremlinProg 23.1.2008, 17:08 |
| Насоветовали много, в деталях, по ошибкам, а главное - упустили. Вообще, странно было увидеть индивидуальное выделение сервера для каждого клиента, обычно это делается немного иначе. Сервер всегда один, клиенты, конечно можно обрабатывать в потоках, но по потоку на каждый клиент - слижком уж расточительно и небезопасно (обычный результат - перегрузка машины, на которой висит сервер). Можно, конечно, использовать несколько серверов, но тогда уж и делить их нужно по портам (даже биндить можно на один адрес, но порты должны отличаться), в общем, это не так удобно и просто, как кажется. В развитии темы: даже в таком случае, при разделенных портами серверов, должен быть один - связующий, который раскидывает клиентов по свободным серверам, такая система даже не оправдывает свою себестоимость По поводу портов: они будут свободны, пока не заняты ) Второй экземпляр сервера на том же адресе и том же порту в принципе не возможен до тех пор, пока первый экземпляр не закроется, отсюда, кстати, и происходят конфликты различных сетевых приложений, к примеру: проксирование на "общеизвестных" портах приводит к невозможности запуска различных "общеизвестных" служб, типа ftp, http, ssh, telnet и т.п. |
| Автор: VitaminCPP 25.1.2008, 00:30 |
| GremlinProg, у моего приложения на один сервер может быть только один клиент. Игра 1 на 1. Всё продумано |