Модификация клиент-сервер Python чата идет ужасно неправильно - PullRequest
1 голос
/ 22 ноября 2010

В качестве упражнения я искал простую клиент-серверную систему Python для чата, которую можно было бы модифицировать и поиграть.Первой серьезной ошибкой, которую я обнаружил в системе, было то, что она использовала одно соединение TCP для связи сервера и клиента.Во-вторых, вы могли общаться только с двумя людьми (один использовал клиент, а другой - сервер).В-третьих, последовательные посты были невозможны.Один человек отправил сообщение, затем ему пришлось ждать, пока другой отправит одно сообщение, прежде чем снова говорить.Очень, очень ограниченно.

Итак, я начал проделывать это и экспериментировать с сокетами.Клиенты подключаются к серверу один раз, дают свои IP-адреса, создают поток прослушивания, а затем повторно подключаются к получателю сообщений сервера.Все сообщения отправляются этому получателю, который просматривает список подключенных клиентов, подключается к каждому из них и отправляет сообщение (с именем отправителя в начале; функция misc).(Я знаю, что так часто открывать новое соединение неэффективно, но я хотел сохранить с tcp-соединениями, пока оно не заработало, и ТОГДА не перейти на UDP)

Однако странная чушь начала происходить.Достаточно сказать, что у меня кошмары из-за ошибки 91.

Может ли кто-нибудь определить, как сделать этот код работоспособным в рамках этой структуры и набора функций?(Python версии 2.6 год назад; игнорируйте бесконечный цикл, который является просто заполнителем)

КОД СЕРВЕРА:

from socket import *
from time import time, ctime
import Queue, threading

IP = ''  
PORT = 5000  
PORTPlus = 2  
PORTRec = 1000  
ADS = (IP, PORT)  
namelist = []  
clientlist = []  



class clientRec(threading.Thread):  
    def __init__(self):  
        threading.Thread.__init__(self)  
        print "I'm this far:", (IP, (PORT + PORTRec))  
        self.receiver = socket(AF_INET, SOCK_STREAM)  
        self.receiver.bind((IP, PORT + PORTRec))  
        self.sender = socket(AF_INET, SOCK_STREAM)  
    def run(self):  
        global clientlist, namelist  
        self.receiver.listen(10)  
        connected = True  
        while connected:  
            tcpcli, addr = receiver.accept()  
            message = tcpcli.recv(1024)                 # Accept clien't IP for   home-dialing  
            for i in range(clientlist.__len__()):               # For each connected client  
                try:  
                    sender.connect(clientlist(i))                 # connect  
                    sender.send(namelist[i] + message)         # and deliver message with sender's name  
                    sender.close()  
                except:  
                    del clientlist[i], namelist[i]  

print "ADS:", (IP, 5000)  
handle = clientRec()  
tcpsoc = socket(AF_INET, SOCK_STREAM)   # Paperwork  
tcpsoc.bind(ADS)                        # Bind self to port  
tcpsoc.listen(5)                        # Listen on that port0  
handle.start()                          # Start thread  

# Main  
while 1:  
    print "Waiting for connection"  
    tcpcli, addr = tcpsoc.accept()      # Accept unknown client  
    print "Connection received; handling..."  
    namelist.append(tcpcli.recv(1024))  # Accept client's name  
    client_IP = tcpcli.recv(1024)       # Accept clien't IP for home-dialing  
    client_port = int(tcpcli.recv(1024))# Accept clien't listening port  
    port_assign = PORT + PORTRec  
    tcpcli.send(str(port_assign))       # Tell the client that port  
    tcpcli.close()                      # Close client connection  

    clientlist.append((client_IP, client_port))# Add client to send-list  
    print "Handled."  

tcpsoc.close()  

КОД КЛИЕНТА:

#!/usr/bin/env python

from socket import *  
import threading, cgi, os  

IP = ''  
PORT = 5000  
PORTmy = 100  
ADS = (IP, PORT)  

class iListen(threading.Thread):  
    def __init__(self):  
        threading.Thread.__init__(self)  
        self.receiver = socket(AF_INET, SOCK_STREAM)# Paperwork  
        self.receiver.bind(('', PORT + PORTmy))     # Listen on that port  
        self.receiver.listen(5)                     # Listen for posts  
    def run(self):  
        while listening:  
            tcpcli, addr = receiver.accept()        # Accept unknown client  
            message = tcpcli.recv(1024)  
            if message == "/q":  
                listening = False  
            tcpcli.close()  

# Initial CONNECT  
myname = raw_input("Tell me yer name partnah: ")  
tcpsoc = socket(AF_INET, SOCK_STREAM)  
tcpsoc.connect(ADS)                     # First Connect  
tcpsoc.send(myname)                     # Declare name  
tcpsoc.send(gethostbyname(gethostname()))# Give IP address  
tcpsoc.send(str(PORT + PORTmy))         # Give listening port  
ADS = (IP, int(tcpsoc.recv(1024)))      # Get new connect details  
tcpsoc.close()                          # Close old connection  
listen = iListen()                      # Create listener thread  
listen.start()                          # Start listening  

# RECONNECT  
print ADS  
tcpsoc = socket(AF_INET, SOCK_STREAM)  
tcpsoc.connect(ADS)                     # reconnect to new port  
connected = True  

# Main Chat-loop  
while connected:  
    mes = raw_input(">>>")  
    tcpsoc.send(mes)  
    if mes == "/q":  
        tcpsoc.close()  
        connected = False  
        time.sleep(4)  

sys.exit()  

1 Ответ

0 голосов
/ 13 декабря 2010

Я работаю над чем-то вроде этого, но вместо этого я собираюсь реализовать шифрование текста. Я вижу, вы подаете в суд на списки клиентов ... но я бы сказал, что есть лучший способ сделать это. Я использую словарь.

если вы знакомы со словарями, пропустите следующий абзац.

Словари могут обрабатывать в основном 2 переменные и определяются с помощью {}.

>>> stuff = {'a':'hello','b':'world'}
>>> print stuff['a']
hello
>>> print stuff['a'],stuff['b']
hello world

поэтому, используя это, вы можете создать словарь, подобный {'username': 'ipaddr'}, таким образом вы можете сделать так, чтобы и имена пользователей, и ips были в одной переменной. Если вы хотите получить конечный продукт, такой как я, вы сделаете так, чтобы все, что делал сервер, повторяло сообщение и отправляло всем, кто подключен. тогда сервер может просто переключаться между именами пользователей.

В качестве другого примечания, я думаю, что tcpsoc.listen (5) - это то, сколько людей может быть соединено одновременно ... Я думаю, это то, что я где-то читал.

Я понятия не имею, почему у вас возникла такая ошибка, но если вы хотите взглянуть на мой наполовину составленный код, вам также будет очень приятно. (игнорировать случайный импорт, он еще не используется, но будет частью системы шифрования)

http://piratepad.net/PwQzdU0bkk

...