Уведомления

Группа в Telegram: @pythonsu
  • Начало
  • » Network
  • » Клиент-серверный чат (сервер многопоточный) [RSS Feed]

#1 Май 6, 2011 09:14:21

ibn_maksimys
От:
Зарегистрирован: 2011-03-27
Сообщения: 9
Репутация: +  0  -
Профиль   Отправить e-mail  

Клиент-серверный чат (сервер многопоточный)

Всем доброго времени суток!

Решил написать клиент-серверный чат, почитал про сокеты и потоки. Нашел готовый код, который почти удовлетворяет моим требованиям по логике работы.

Сервер:

import socket, threading, string

debug = True

_connector = None
_running = True

_host = '127.0.0.1'
_port = 12345
_maxClient = 999
_recvBuffer = 2000

def printd (aString):
if debug:
print (aString)

class talkToClient (threading.Thread):
def __init__(self, clientSock, addr):
self.clientSock = clientSock
self.addr = addr
threading.Thread.__init__(self)
def run (self):
while True:
recvData = self.clientSock.recv (_recvBuffer)
if not recvData:
self.clientSock.send ('bye')
break
printd('Client ' + str (self.addr) + ' say "' + str (recvData) + '"')
for p in range(len(list)):
self.clientSock.sendto(recvData, list[p])
if recvData == "exit":
break
self.clientSock.close ()

_connector = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
_connector.bind ((str(_host), int(_port)))
_connector.listen (int(_maxClient))
list = []
while _running:
printd ('Running on ' + _host + ':' + str (_port) + '.')
channel, details = _connector.accept ()
list.append(details)
printd ('Conect on : ' + str (details))
talkToClient (channel, details).start ()

_connector.close ()
Клиент:
import socket, string

debug = True

_connector = None
_running = True

_host = '127.0.0.1'
_port = 12345
_recvBuffer = 2000

_connector = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
_connector.connect ((str(_host), int(_port)))

while _running:
sendData = input ("> ")
_connector.send (bytes(sendData,'utf-8'))
recvData = _connector.recv (_recvBuffer)
print (recvData)
if recvData == "bye":
break
if recvData == "exit":
break

_connector.close ()
Идея такая, клиент конектится к серверу, сервер заносит его данные (IP и порт) в список:
list.append(details)
После этого для каждого клиента запускается свой поток и слушает порт клиента. Если с него что-то приходит, то это сообщение отправляется всем клиентам информация о которых присутствует в списке.
for p in range(len(list)):
self.clientSock.sendto(recvData, list[p])
И вот в чем загвоздка: сообщения очень странно пересылаются клиентам из списка. Они приходят только отправителю и порой они дублируются. Подскажите пожалуйста, что не так в коде?



Офлайн

#2 Май 6, 2011 09:47:41

rip86oz
От:
Зарегистрирован: 2011-03-14
Сообщения: 24
Репутация: +  0  -
Профиль   Отправить e-mail  

Клиент-серверный чат (сервер многопоточный)

Не знаю как питон отнёсся к переменной с именем “list”, но я-бы ругнулся ))
Одной из причин является возможно блокирующий ввод. Пока пользователь не нажмёт Ентер, то он не увидит входящих сообщений.
Серверная сторона.. бррррр… Я от потоков в питоне отказался, по крайней мере когда в них используются блокирующие функции.
Думаю стоит продумать алгоритм программы заново - и с нуля всё написать. ))



Офлайн

#3 Май 6, 2011 10:25:43

pill
От:
Зарегистрирован: 2010-08-27
Сообщения: 223
Репутация: +  0  -
Профиль   Отправить e-mail  

Клиент-серверный чат (сервер многопоточный)

socket.sendto “The socket should not be connected to a remote socket,”
В данном случае сокет в потоке, похоже, подключен, и шлет данные только своему клиенту забив на адрес (если подключить 3 клиента - данные будут отсылаться обратно три раза и так далее)

вот так должно работать:

# -*- coding: utf-8 -*-
import socket, threading, string

debug = True

_connector = None
_running = True

_host = '127.0.0.1'
_port = 12345
_maxClient = 999
_recvBuffer = 2000

def printd (aString):
if debug:
print (aString)

class talkToClient (threading.Thread):
def __init__(self, clientSock, addr):
self.clientSock = clientSock
self.addr = addr
threading.Thread.__init__(self)
def run (self):
while True:
recvData = self.clientSock.recv (_recvBuffer)
if not recvData:
self.clientSock.send ('bye')
break
printd('Client ' + str (self.addr) + ' say "' + str (recvData) + '"')
if recvData == "exit":
break
#-------здесь----------------------->>
for conn in CONNS:
conn.sendData(recvData)
self.clientSock.close ()
def sendData(self, data):
print 'sending to ', self.addr
self.clientSock.send(data)
#----------------------------------

_connector = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
_connector.bind ((str(_host), int(_port)))
_connector.listen (int(_maxClient))


#----и здесь---------------------------
CONNS = []

while _running:
printd ('Running on ' + _host + ':' + str (_port) + '.')
channel, details = _connector.accept ()
printd ('Conect on : ' + str (details))
CONNS.append(talkToClient (channel, details))
print CONNS
CONNS[-1].start ()

_connector.close ()
Но вцелом эть конечно не гут.
Возьмите что-то готовое и не мучайтесь… тот же Твистед например.
Ссылочка вдогонку: туц



Отредактировано (Май 6, 2011 13:29:26)

Офлайн

  • Начало
  • » Network
  • » Клиент-серверный чат (сервер многопоточный)[RSS Feed]

Board footer

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

Powered by DjangoBB

Lo-Fi Version