| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Сети > Лимиты Сокета |
| Автор: nerdy_weirdie 10.11.2008, 20:24 |
| Добрый вечер. У меня возникла проблема с серверным приложением. Может, кто сталкивался. Программа принимает подключения от клиентов (accept();) и в потоке работает с ними, завершая работу shutdown()+closesocket(). Основную часть времени соединения находятся в режиме ожидания - нагрузка на канал небольшая. Соединений обычно около 2к. Проблема в следующем: примерно раз в сутки мне приходится рестартовать программу, потому что она перестает принимать подключения, причем на любой открытый сокет, а не только на тот, что принимает основную часть подключений. Клиент получает ошибку "удаленный хост принудительно разорвал соединение". Другие программы при этом сохраняют способность принимать подключения. Такое ощущение, что есть какие-то лимиты у winsocket. Проверил ветку реестра HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters - там нет параметра TcpNumConnections, видимо, не ограничен. В чем может быть дело? |
| Автор: SVN74 10.11.2008, 21:07 |
| А в потоке по работе с клиентом при ошибке соединения сокет закрывается (closesocket) ? |
| Автор: J0ker 10.11.2008, 22:31 |
| http://forum.vingrad.ru/index.php?showtopic=233713&view=findpost&p=1680133 сокеты надо правильно закрывать потомучто Добавлено через 2 минуты и 25 секунд в winsock есть лимиты на полуоткрытые сокеты, но это относится к исходящим соединениям |
| Автор: nerdy_weirdie 12.11.2008, 21:50 | ||
При завершении сеанса работы с клиентом, сервер всегда заканчивает связь вызовами shutdown()+closesocket(). Этого не достаточно? |
| Автор: J0ker 13.11.2008, 21:22 | ||
| проверьте netstat'ом на наличие большого числа сокетов в состояние FIN_WAIT так-же я не уверен, как у вас обстоит дело со слушающим сокетом - вы его живым держите или после каждого accept'а ребайндаете? Добавлено через 14 минут и 41 секунду да, и на будущее правильная последовательность закрытия TCP соединения: инициатор - инициатор завершения соединения
(*) - должны применяться таймауты - в случае истечения таймаута выполняется переход к shutdown(SD_RECV) |
| Автор: nerdy_weirdie 13.11.2008, 23:24 |
| в цикле только accept() + ::CloseHandle(::CreateThread()). Вот, наблюдаю за нетстатом - пока что только исключительно "ESTABLISHED". |
| Автор: J0ker 14.11.2008, 00:49 |
| вы не должны вызывать CreateThread если вы работаете с MFC - используйте AfxBeginThread для остального - _beginthread CreateThread можно использовать только в raw windows API в этом возможно как раз и проблема |
| Автор: nerdy_weirdie 30.11.2008, 07:40 | ||||||
Не, MFC не использую. Спасибо за ответ, но мне кажется что в этом врядли может скрываться причина. Будь то AfxBeginThread или _beginthread, все они вызывают ::CreateThread. Добавлено через 11 минут и 15 секунд
Дело в том что, как показывает статистика, основная причина завершения соединения - разрыв подключения к интернету у клиента. Чем это чревато? Незакрытые сокеты видимо не висят, т.к. потоков в момент коллапса наблюдается не больше обычного. Такие ситуации требуют особой обработки сервером? Возможно, в этом и кроется моя проблема. |
| Автор: Олег2005 30.11.2008, 14:30 | ||||
Какая ОС?
Проблема описана некорректно. Что значит - принимать подключения? Подключения принимаются только на слушающий сокет - параметр длины очереди устанавливается в listen() А поэтому фраза:"перестает принимать подключения, причем на любой открытый сокет, а не только на тот, что принимает основную часть подключений." - абсолютно непонятна. На любой сокет принимать подключения - нельзя - прием идет только по одному - слушающему. А запросы обслуживаются на акцептированных (присоединенных) сокетах. Так что сформулируйте проблему покорректнее |
| Автор: nerdy_weirdie 30.11.2008, 15:12 |
| Олег2005, да, я имел ввиду слушающие сокеты, listen()+<accept() в цикле>. ОС Windows Server 2003, но всё равно об этом патче TCPIP.SYS почитаю, спасибо. Добавлено через 9 минут и 47 секунд Длина очереди в listen() установлена в SOMAXCONN. |
| Автор: nerdy_weirdie 30.11.2008, 15:40 | ||
При нештатном уходе клиента из онлайна сервер замечает это по send() == -1, ::GetLastError() == 10054 An existing connection was forcibly closed by the remote host. Обрабатывает он эту ситуацию: shutdown(s,SD_BOTH); closesocket(s); Собственно, сокеты незакрытые, видимо, не висят. |
| Автор: Олег2005 30.11.2008, 15:47 | ||
И сколько же стоит? Добавлено @ 15:49
Как видно все нормально на присоединенных сокетах закрывается. Тогда где же всетаки нештатная ситуация? |
| Автор: J0ker 30.11.2008, 19:27 | ||
только они еще и инициализируют библиотеки в потоках - _beginthread - CRT, а AfxBeginThread - CRT и afx я вам совершенно серьезно советую исправить - вероятность что именно здесь собака и порылась очень высока есть после отсылки пакета с выставленым FIN сокет переходит в состояние FIN_WAIT_1, а после приема ACK без FINа переходит в состояние FIN_WAIT_2 правда я не уверен, что netstat эти состояния отображает - не задавался таким вопросом nerdy_weirdie, совершенно серьезно - обрати внимание на ::CreateThread - при отсутствии инициализации библиотек в потоке могут быть точно такие явления как ты описал |
| Автор: Олег2005 30.11.2008, 21:31 |
| Есть еще вариант - на каждый поток выделяется память - 1 мег в раме. Как с этим делом? |
| Автор: MAKCim 30.11.2008, 22:27 | ||
верно и где здесь FIN_WAIT? |
| Автор: nerdy_weirdie 30.11.2008, 23:50 |
| Видимо, таки где-то есть утечка хендлов. Вот, таскменеджером наблюдаю. Сразу после запуска их было примерно по 5 на поток. Через несколько часов около 10 на поток. И сейчас, часов через 8 стало около 12 на поток. Только ума пока что не приложу, откуда они утекают. Может, кто знает какой попроще способ узнать, откуда лишние хендлы при 2000 работающих потоках )) |
| Автор: J0ker 1.12.2008, 01:17 | ||||
имелось ввиду в каком-либо FIN_WAIT - _1 или _2 ну впрочем тебя я не осуждаю - сие очевидно только ОО программистам Добавлено через 5 минут и 4 секунды вы игнорируете мое предупреждение насчет CreateThread CRT и MFC имеют глобальные объекты, которые должны быть инициализированны на каждый поток отдельно - при отсутствии инициализации последствия непредсказуемы и трудно обнаруживаемы в том числе это может быть и утечка ресурсов |
| Автор: MAKCim 1.12.2008, 02:21 | ||
ага, и потом вот из-за таких ОО программистов и ракеты взрываются, и еще куча всего нехорошего происходит очевидно != формально |
| Автор: J0ker 1.12.2008, 03:38 | ||||
из-за формалистов происходит столько всяких неприятностей, что одной ракетой больше, одной меньше - никакого рояля не играет |
| Автор: MiklVolkov 4.7.2009, 07:40 |
| Уважаемые, если проблему решили, то подскажите как? Я наступил н теже грабли. Есть набор клиент-серверных приложений собственной разработки. Для связи используются сокеты в виде классов в которых реализовна и клиентская и серверная части. Вся часть ПО ответственная за связь вынесена в отдельную DLL. Сервер запускается, клиенты к нему подключаются, отключаются и т.д. и т.п. Все нормально работало неделями - дольше не получалось тестировать непрерывно - приходилось перезапускать. Клиентов было штук 20. Сейчас клиентов увеличил до 150. Теперь все работает но 2,5 дня. Может и дольше - до недели, но не меньше точно. Потом происходит следующая ситуация. Сервер видит подключения клиентов, новые подключаются, старые отключаются, но данные не пересылаются ни в одну сторону. Была идея - сделать перезапуск класса сервера, отвечающего за связь. Обнаружил интересную штуку - если сделать этот перезапуск искусственно - скажем через 1 сутки - все нормально работает. Но если дождаться когда связь "отвалится" сама - увы, клиенты подключаются, а данные не ходят ни в одну сторону. Перезапускаешь приложение - все опять работает. Понятно, что где-то что-то переполняется, но вот что и где? Да, еще забыл добавить интересное наблюдение - перезапуск класса связи искусственно срабатывает 101 раз. А потом надо один фиг перезагружать всю программу целиком. Памяти сколько выделено и нитей - столько же, сколько и при старте программы. А вот насчет netstat - сказать ничего не могу - я только что про нее узнал Средствами VS никаких утечек чего либо не обнаруживается. |