Уведомления

Группа в Telegram: @pythonsu

#1 Авг. 3, 2011 18:39:47

haize
От:
Зарегистрирован: 2011-01-13
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

socket.close() и количество соединений

Здравствуйте! Столкнулся с проблемой.

def connect(self):
self.disconnect()
self.link = socket.socket(type = socket.SOCK_DGRAM)
self.link.settimeout(self.timeout)

def disconnect(self):
if self.link:
self.link.close()
self.link = None
Подключаюсь к серверу с помощью connect(). Отправляю n байт. Всё проходит нормально, получаю обратно то, что мне было нужно. Вызываю disconnect().

Всё проходит в цикле, обращаюсь к различным серверам. После вызова disconnect() не происходит разрыва соединения. Если посмотреть количество соединений с помощью файрвола или какого-нибудь network monitor'a обнаруживается, что соединения постоянно растут. После того, как программа завершает работу, количество соединений падает до нуля. Пробовал socket.socket().shutdown() – не помогло.

Помогите, пожалуйста, разобраться в чём проблема. Как мне обрывать соединения после disconnect()?



Офлайн

#2 Авг. 3, 2011 19:28:09

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

socket.close() и количество соединений

Это фича. Сокет висит открытым некоторое время после close(). Ручки подкрутить это время — нет. Придется с этим жить.



Офлайн

#3 Авг. 3, 2011 21:16:13

haize
От:
Зарегистрирован: 2011-01-13
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

socket.close() и количество соединений

Андрей Светлов
А как же быть, если у меня это реализовано в виде сервера и запросы идут постоянно? Количество соединений вырастает до тысячи очень быстро, что недопустимо для моего приложения.

Сборщик мусора ведь сбрасывает все соединения при завершении программы, или же это ОС закрывает все соединения после завершения скрипта? Есть какой-нибудь выход из этой ситуации?



Офлайн

#4 Авг. 3, 2011 23:21:47

Enchantner
От:
Зарегистрирован: 2009-02-11
Сообщения: 442
Репутация: +  0  -
Профиль   Отправить e-mail  

socket.close() и количество соединений

Андрей Светлов
а разве REUSEADDR не для этого? Или он только для TCP?

haize
Попробуйте сделать через какой-нибудь pycurl. Возможно, что даже многопоточно получится. И да, еще есть вариант - использовать gevent, там своя обертка на сокет и легкие юзерспейс-треды.



Отредактировано (Авг. 3, 2011 23:25:22)

Офлайн

#5 Авг. 3, 2011 23:23:01

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

socket.close() и количество соединений

Извините, просмотрел. У вас же UDP сокеты. Так зачем вы их каждый раз заново создаете?



Офлайн

#6 Авг. 3, 2011 23:24:41

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

socket.close() и количество соединений

Enchantner, REUSEADDR именно для TCP, причем серверного. Т.е. при .connect он не поможет.



Офлайн

#7 Авг. 3, 2011 23:37:06

haize
От:
Зарегистрирован: 2011-01-13
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

socket.close() и количество соединений

Андрей Светлов
Каждый раз я подключаюсь к серверам с разными IP адресами и портами. Можно как-то переподключиться к другому серверу не вызывая создавая нового экземпляра сокета и не вызывая функцию socket.socket().connect()?
Подскажите, пожалуйста, как будет правильно поступить в этом случае?



Офлайн

#8 Авг. 3, 2011 23:55:28

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

socket.close() и количество соединений

У вас UDP? Так используйте sendto/recvfrom.



Офлайн

#9 Авг. 4, 2011 23:12:45

haize
От:
Зарегистрирован: 2011-01-13
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

socket.close() и количество соединений

Андрей Светлов
У вас UDP? Так используйте sendto/recvfrom.
Да. Пробовал сегодня вместо socket.connect((self.host, self.port)) сразу отправлять данные с помощью socket.sendto.

В цикле обхожу кортеж со значениями ip-адреса и порта и выполняю socket.sendto.

Что-то, типа:
soc = socket.socket(type = socket.SOCK_DGRAM)
for ip, port in server_list:
soc.sendto(data, (ip, port))
res = soc.recv(packet_size)
# -- код выполняющий обработку ответа --
Количество соединений постоянно растёт и почти не падает. Точно так же, как и с socket.connect и socket.send. Как сделать правильно?



Отредактировано (Авг. 4, 2011 23:14:21)

Офлайн

#10 Авг. 4, 2011 23:26:47

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

socket.close() и количество соединений

Без полного работающего кода гадаю по пятнам света от проезжающих мимо окна машин.
Зачем вам soc.recv — нужно делать soc.recvfrom.
И вы всё ещё создаёте сокет на каждый запрос?



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version