Модераторы: feodorv

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Лимиты Сокета, Сокет перестает принимать подключения 
:(
    Опции темы
nerdy_weirdie
Дата 10.11.2008, 20:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 179
Регистрация: 16.1.2007

Репутация: нет
Всего: нет



Добрый вечер. У меня возникла проблема с серверным приложением. Может, кто сталкивался.
Программа принимает подключения от клиентов (accept();) и в потоке работает с ними, завершая работу shutdown()+closesocket(). Основную часть времени соединения находятся в режиме ожидания - нагрузка на канал небольшая. Соединений обычно около 2к.
Проблема в следующем: примерно раз в сутки мне приходится рестартовать программу, потому что она перестает принимать подключения, причем на любой открытый сокет, а не только на тот, что принимает основную часть подключений. Клиент получает ошибку "удаленный хост принудительно разорвал соединение". Другие программы при этом сохраняют способность принимать подключения.
Такое ощущение, что есть какие-то лимиты у winsocket.
Проверил ветку реестра HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters - там нет параметра TcpNumConnections, видимо, не ограничен.
В чем может быть дело?
PM MAIL   Вверх
SVN74
Дата 10.11.2008, 21:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 740
Регистрация: 5.5.2008
Где: Комсомольск на Дн епре

Репутация: 1
Всего: 18



А в потоке по работе с клиентом при ошибке соединения сокет закрывается (closesocket) ?
PM MAIL WWW   Вверх
J0ker
Дата 10.11.2008, 22:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 1
Всего: 14



http://forum.vingrad.ru/index.php?showtopi...t&p=1680133
сокеты надо правильно закрывать потомучто

Добавлено через 2 минуты и 25 секунд
в winsock есть лимиты на полуоткрытые сокеты, но это относится к исходящим соединениям

Это сообщение отредактировал(а) J0ker - 10.11.2008, 22:32


--------------------
user posted image
PM MAIL   Вверх
nerdy_weirdie
Дата 12.11.2008, 21:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 179
Регистрация: 16.1.2007

Репутация: нет
Всего: нет



Цитата(J0ker @ 10.11.2008,  22:31)
http://forum.vingrad.ru/index.php?showtopi...t&p=1680133
сокеты надо правильно закрывать потомучто

Добавлено @ 22:33
в winsock есть лимиты на полуоткрытые сокеты, но это относится к исходящим соединениям

При завершении сеанса работы с клиентом, сервер всегда заканчивает связь вызовами  shutdown()+closesocket(). Этого не достаточно?
PM MAIL   Вверх
J0ker
Дата 13.11.2008, 21:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 1
Всего: 14



проверьте netstat'ом на наличие большого числа сокетов в состояние FIN_WAIT
так-же я не уверен, как у вас обстоит дело со слушающим сокетом - вы его живым держите или после каждого accept'а ребайндаете?

Добавлено через 14 минут и 41 секунду
да, и на будущее
правильная последовательность закрытия TCP соединения:
инициатор - инициатор завершения соединения
Код

инициатор                          peer
-----------------------------------------------------------------------
shutdown(SD_SEND)          --->    recv пакет длиной 0
recv оставшихся данных*    <---    send оставшихся данных (опционально)
recv пакета длиной 0*      <---    shutdown(SD_BOTH)
shutdown(SD_RECV)                  closesocket()
closesecket()

(*) - должны применяться таймауты - в случае истечения таймаута выполняется переход к shutdown(SD_RECV) 


--------------------
user posted image
PM MAIL   Вверх
nerdy_weirdie
Дата 13.11.2008, 23:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 179
Регистрация: 16.1.2007

Репутация: нет
Всего: нет



в цикле только accept() + ::CloseHandle(::CreateThread()).
Вот, наблюдаю за нетстатом - пока что только исключительно "ESTABLISHED".
PM MAIL   Вверх
J0ker
Дата 14.11.2008, 00:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 1
Всего: 14



вы не должны вызывать CreateThread
если вы работаете с MFC - используйте AfxBeginThread
для остального - _beginthread
CreateThread можно использовать только в raw windows API
в этом возможно как раз и проблема


--------------------
user posted image
PM MAIL   Вверх
nerdy_weirdie
Дата 30.11.2008, 07:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 179
Регистрация: 16.1.2007

Репутация: нет
Всего: нет



Цитата(J0ker @ 14.11.2008,  00:49)
вы не должны вызывать CreateThread
если вы работаете с MFC - используйте AfxBeginThread
для остального - _beginthread
CreateThread можно использовать только в raw windows API
в этом возможно как раз и проблема

Не, MFC не использую.
Спасибо за ответ, но мне кажется что в этом врядли может скрываться причина. Будь то AfxBeginThread или _beginthread, все они вызывают ::CreateThread.

Добавлено через 11 минут и 15 секунд
Цитата(J0ker @ 13.11.2008,  21:22)
проверьте netstat'ом на наличие большого числа сокетов в состояние FIN_WAIT
так-же я не уверен, как у вас обстоит дело со слушающим сокетом - вы его живым держите или после каждого accept'а ребайндаете?

Добавлено @ 21:37
да, и на будущее
правильная последовательность закрытия TCP соединения:
инициатор - инициатор завершения соединения
Код

инициатор                          peer
-----------------------------------------------------------------------
shutdown(SD_SEND)          --->    recv пакет длиной 0
recv оставшихся данных*    <---    send оставшихся данных (опционально)
recv пакета длиной 0*      <---    shutdown(SD_BOTH)
shutdown(SD_RECV)                  closesocket()
closesecket()

(*) - должны применяться таймауты - в случае истечения таймаута выполняется переход к shutdown(SD_RECV)

Дело в том что, как показывает статистика, основная причина завершения соединения - разрыв подключения к интернету у клиента. Чем это чревато? Незакрытые сокеты видимо не висят, т.к. потоков в момент коллапса наблюдается не больше обычного. Такие ситуации требуют особой обработки сервером? Возможно, в этом и кроется моя проблема. 
PM MAIL   Вверх
MAKCim
Дата 30.11.2008, 11:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 6
Всего: 207



Цитата(J0ker @  13.11.2008,  21:22 Найти цитируемый пост)
проверьте netstat'ом на наличие большого числа сокетов в состояние FIN_WAIT

нет такого состояния  smile

Добавлено через 5 минут и 2 секунды
Цитата(nerdy_weirdie @  30.11.2008,  07:40 Найти цитируемый пост)
разрыв подключения к интернету у клиента.

как именно разрыв происходит?

посмотри, в каком состоянии находятся сокеты на стороне сервера
сразу станет понятно


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Олег2005
Дата 30.11.2008, 14:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 421
Регистрация: 26.5.2005
Где: Рига Латвия

Репутация: 6
Всего: 11



Цитата(nerdy_weirdie @  10.11.2008,  19:24 Найти цитируемый пост)
TcpNumConnections, видимо, не ограничен.

Какая ОС?
Цитата
Windows XP для повышения безопасности введен новый механизм, ограничивающий число одновременных попыток подключений каждого процесса десятью в секунду (но не ограничивающий вообще число установленных одновременных подключений!), что призвано снизить вредоносный эффект от некоторых типов вирусов. Если же опасность новых вирусных эпидемий вас волнует мало, а главное для вас - скорость, то придется пропатчить системный файл TCPIP.SYS (параметр TcpNumConnections реестра не сработает!).


Цитата(nerdy_weirdie @  10.11.2008,  19:24 Найти цитируемый пост)
Проблема в следующем: примерно раз в сутки мне приходится рестартовать программу, потому что она перестает принимать подключения, причем на любой открытый сокет, а не только на тот, что принимает основную часть подключений. Клиент получает ошибку "удаленный хост принудительно разорвал соединение". Другие программы при этом сохраняют способность принимать подключения.

Проблема описана некорректно.
Что значит - принимать подключения?
Подключения принимаются только на слушающий сокет - параметр длины очереди устанавливается в listen()
А поэтому фраза:"перестает принимать подключения, причем на любой открытый сокет, а не только на тот, что принимает основную часть подключений." - абсолютно непонятна.
На любой сокет принимать подключения - нельзя - прием идет только по одному - слушающему.
А запросы обслуживаются на акцептированных (присоединенных) сокетах.
Так что сформулируйте проблему покорректнее


PM MAIL WWW MSN   Вверх
nerdy_weirdie
Дата 30.11.2008, 15:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 179
Регистрация: 16.1.2007

Репутация: нет
Всего: нет



Олег2005, да, я имел ввиду слушающие сокеты, listen()+<accept() в цикле>.
ОС Windows Server 2003, но всё равно об этом патче TCPIP.SYS почитаю, спасибо.

Добавлено через 9 минут и 47 секунд
Длина очереди в listen() установлена в SOMAXCONN.
PM MAIL   Вверх
nerdy_weirdie
Дата 30.11.2008, 15:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 179
Регистрация: 16.1.2007

Репутация: нет
Всего: нет



Цитата(MAKCim @ 30.11.2008,  11:29)
Цитата(nerdy_weirdie @  30.11.2008,  07:40 Найти цитируемый пост)
разрыв подключения к интернету у клиента.

как именно разрыв происходит?

посмотри, в каком состоянии находятся сокеты на стороне сервера
сразу станет понятно

При нештатном уходе клиента из онлайна сервер замечает это по send() == -1,
::GetLastError() == 10054 An existing connection was forcibly closed by the remote host. 

Обрабатывает он эту ситуацию:
shutdown(s,SD_BOTH);
closesocket(s);
Собственно, сокеты незакрытые, видимо, не висят.

Это сообщение отредактировал(а) nerdy_weirdie - 30.11.2008, 15:41
PM MAIL   Вверх
Олег2005
Дата 30.11.2008, 15:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 421
Регистрация: 26.5.2005
Где: Рига Латвия

Репутация: 6
Всего: 11



Цитата(nerdy_weirdie @  30.11.2008,  14:12 Найти цитируемый пост)
SOMAXCONN. 

И сколько же стоит?

Добавлено @ 15:49
Цитата(nerdy_weirdie @  30.11.2008,  14:40 Найти цитируемый пост)
При нештатном уходе клиента из онлайна сервер замечает это по send() == -1,
::GetLastError() == 10054 An existing connection was forcibly closed by the remote host. 

Как видно все нормально на присоединенных сокетах закрывается.
Тогда где же всетаки нештатная ситуация?

Это сообщение отредактировал(а) Олег2005 - 30.11.2008, 15:49
PM MAIL WWW MSN   Вверх
J0ker
Дата 30.11.2008, 19:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 1
Всего: 14



Цитата(nerdy_weirdie @  30.11.2008,  07:40 Найти цитируемый пост)
Спасибо за ответ, но мне кажется что в этом врядли может скрываться причина. Будь то AfxBeginThread или _beginthread, все они вызывают ::CreateThread.

только они еще и инициализируют библиотеки в потоках - _beginthread - CRT, а AfxBeginThread - CRT и afx
я вам совершенно серьезно советую исправить - вероятность что именно здесь собака и порылась очень высока


Цитата(MAKCim @  30.11.2008,  11:29 Найти цитируемый пост)
нет такого состояния

есть
после отсылки пакета с выставленым FIN сокет переходит в состояние FIN_WAIT_1, а после приема ACK без FINа переходит в состояние FIN_WAIT_2
правда я не уверен, что netstat эти состояния отображает - не задавался таким вопросом

nerdy_weirdie, совершенно серьезно - обрати внимание на ::CreateThread - при отсутствии инициализации библиотек в потоке могут быть точно такие явления как ты описал

Это сообщение отредактировал(а) J0ker - 30.11.2008, 19:28


--------------------
user posted image
PM MAIL   Вверх
Олег2005
Дата 30.11.2008, 21:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 421
Регистрация: 26.5.2005
Где: Рига Латвия

Репутация: 6
Всего: 11



Есть еще вариант - на каждый поток выделяется память - 1 мег в раме.
Как с этим делом?
PM MAIL WWW MSN   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0581 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.