Уведомления

Группа в Telegram: @pythonsu

#1 Июнь 10, 2010 21:44:05

Alex2ndr
От:
Зарегистрирован: 2009-12-26
Сообщения: 204
Репутация: +  0  -
Профиль   Отправить e-mail  

Конфликт socket в threading

Хмм….
Изучил вышеприведенную статью. Если вы обратите внимание, то они там сделали так, же как и я - создали socket внутри метода run:

class ConnectionThread(threading.Thread):
def run(self):
# Connect to the server:
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect (('localhost', 2727))

# Retrieve and unpickle the list object:
print pickle.loads(client.recv(1024))

# Send some messages:
for x in xrange(10):
client.send('Hey. ' + str(x) + '\n')

# Close the connection
client.close()
“Это жжж… не спроста!” (с)



Офлайн

#2 Июнь 11, 2010 03:41:04

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

Конфликт socket в threading

Alex2ndr
“Это жжж… не спроста!” (с)
Да вы правы, именно этим и занимался, переделывал код что бы вынести создание в функцию. Сейчас почти работает, и это очень интересно, потому что код который внутри класса но не в функций выполняется один раз и становиться общим между трэдами, например:
import socket
import threading
import time
import random

class client(threading.Thread):
print "Run"
temp = 0 + random.randint(1,100)
def connect(self):
HOST = "127.0.0.1"
PORT = 411
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
print "connect true"
print "temp = ",self.temp
return

def run(self):
self.connect()
return

print "thread 1"
client().start()
time.sleep(2)
print "thread 2"
client().start()
По логике должно вывести слово “run” два раза, и вывести два случайных числа, но в итоге мы имеем вот такое:
Run
thread 1
connect true
temp = 43
thread 2
connect true
temp = 43
Видимо код в классе становится общим, но такого описания еще не в какой книжке не видел… Меня тоже насторожило в примере код создания сокета выведено в функцию, и это было единственное различие.



Офлайн

#3 Июнь 11, 2010 05:35:46

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

Конфликт socket в threading

Хм, очень интересно, если объявлять переменные в классе то они становятся общими в трэдах, но если менять значение переменных в функций класса то для каждого трэда будет доступна своя переменная…



Офлайн

#4 Июнь 11, 2010 09:09:16

Alex2ndr
От:
Зарегистрирован: 2009-12-26
Сообщения: 204
Репутация: +  0  -
Профиль   Отправить e-mail  

Конфликт socket в threading

Покопался в исходниках threading, но с налету ничего, объясняющего такое поведение не нашел. Он уходит корнями к встроенному модулю thread, а как там копаться я пока не знаю.

Может быть не стоит наследоваться от threading.Thread? Вот у меня тут есть старая прога, в которой делается по другому:

#!/usr/bin/env python
# -*-coding: utf-8 -*-
# vim: sw=4 ts=4 expandtab ai

import subprocess
import threading
import Queue

def ipgen(oct1,oct2,oct3,oct4):
for o1 in xrange(oct1[0],oct1[1]+1):
for o2 in xrange(oct2[0],oct2[1]+1):
for o3 in xrange(oct3[0],oct3[1]+1):
for o4 in xrange(oct4[0],oct4[1]+1):
yield '%s.%s.%s.%s' % (o1,o2,o3,o4)

def ping2mac(ip):
subprocess.call(("/bin/ping -c1 -s1 %s &>/dev/null" % ip), \
shell=True)
macstr = subprocess.Popen(('arp -an | grep "(%s)"' % ip), \
shell=True, stdout=subprocess.PIPE)
mac = macstr.communicate()[0]
if mac:
mac = mac.split()[3]
if mac != '<incomplete>':
return mac
return ''

def pinger(que):
while True:
ip = que.get()
mac = ping2mac(ip)
if mac: print ip,mac
que.task_done()

if __name__ == '__main__':
queue = Queue.Queue()
for i in xrange(20):
worker = threading.Thread(target=pinger,args=(queue,))
worker.setDaemon(True)
worker.start()

for ip in ipgen((192,192),(168,168),(0,0),(0,255)):
queue.put(ip)
queue.join()
Может быть чем поможет…



Офлайн

#5 Июнь 11, 2010 09:14:57

Alex2ndr
От:
Зарегистрирован: 2009-12-26
Сообщения: 204
Репутация: +  0  -
Профиль   Отправить e-mail  

Конфликт socket в threading

О!
получил рабочий вариант:

#!/usr/bin/env python
# -*-coding: utf-8 -*-
# vim: sw=4 ts=4 expandtab ai
# pylint: disable-msg=C0301

import socket
import threading
import time

class client(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
print "RUN!"
self.HOST = "192.168.0.1"
self.PORT = 80
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

def connect(self):
self.s.connect((self.HOST, self.PORT))
print "connect true"
return

def run(self):
self.connect()
return
print "thread 1"
c1 = client()
c1.start()
time.sleep(3)
print "thread 2"
c2 = client()
c2.start()
Все оказалось просто…
alex@debian-gate:~$ python ./test/thread.py
thread 1
RUN!
connect true
thread 2
RUN!
connect true



Отредактировано (Июнь 11, 2010 09:15:54)

Офлайн

#6 Июнь 11, 2010 09:19:35

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

Конфликт socket в threading

Alex2ndr
Может быть чем поможет…
Спасибо. Переписал класс что бы необходимые данные создавались в __init__ и проблема решилась. Конечно интересный факт что объявленные внутри класса данные общие для трэдов. Спасибо за помощь. У вас опыта больше чем у меня, не подскажете можно ли зная имя необходимого трэда вызвать в нем функцию с параметрами которая есть в классе?



Офлайн

#7 Июнь 11, 2010 09:22:30

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

Конфликт socket в threading

Alex2ndr
Все оказалось просто…
Пока писал ответ вы моё решение написали, я тоже пришел к этому выводу :)



Офлайн

#8 Июнь 11, 2010 09:34:40

Alex2ndr
От:
Зарегистрирован: 2009-12-26
Сообщения: 204
Репутация: +  0  -
Профиль   Отправить e-mail  

Конфликт socket в threading

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

Вообще можно сделать что угодно ;) Главное правильно сформулировать задачу.



Офлайн

#9 Июнь 11, 2010 09:45:26

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

Конфликт socket в threading

Alex2ndr, необходимо после создания трэдов с клиентами, отправлять через сокет данные, в классе трэда есть функция sendmessage:

class client(threading.Thread):
def __init__(self,name):
threading.Thread.__init__(self, name=name)
self.HOST = "127.0.0.1"
self.PORT = 411
self.s = socket.socket(socket.AF_INET,
def connect(self):
self.s.connect((self.HOST, self.PORT))
return
def sendmessage(self, text):
self.s.send(text)
return
Вот и встал вопрос можно ли по имени трэда вызвать в нём функицю sendmessage(text) …



Отредактировано (Июнь 11, 2010 09:49:38)

Офлайн

#10 Июнь 11, 2010 10:02:53

Alex2ndr
От:
Зарегистрирован: 2009-12-26
Сообщения: 204
Репутация: +  0  -
Профиль   Отправить e-mail  

Конфликт socket в threading

Эээээ…. Я бы сделал по другому.
Вот у нас есть некий класс, который занимается созданием сокета и передачей по нему данных. Так пусть этот класс сам рулит тем, когда нужно вызывать какие-то sendmessage. А вы хотите наоборот, создавая себе лишние проблемы. Т е нужна иная архитектура программы.

Честно скажу, что не знаю как сделать так, как вы хотите. Может можно, а может и нет.



Отредактировано (Июнь 11, 2010 10:03:21)

Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version