2010-11-21 114 views
1

作为一个练习,我寻找一个简单的Python聊天客户端 - 服务器系统来修改和玩弄。我在系统中发现的第一个主要失败是它使用单个tcp连接让服务器和客户端进行通信。第二个是你只能有两个人(一个使用客户端,另一个使用服务器)进行通信。第三,连续的职位是不可能的。一个人发了一条消息,然后不得不等待另一个人在再次交谈之前发送一条消息。非常,非常有限。Python聊天客户端 - 服务器修改出错可怕

所以我开始穿线它并试验插座。客户端连接到服务器一次,给他们的IP地址,创建一个监听线程,然后重新连接到服务器的消息接收器。 所有帖子都发送到该接收者,它遍历连接的客户端列表,并连接到他们每个人并发送消息(发件人的名字在开头;杂项功能)。 (我知道这样经常打开一个新的连接效率很低,但我想保持TCP连接,直到我有它的工作,然后去UDP)

然而,奇怪的废话开始发生。只要说我有错误91的恶梦。

任何人都可以识别如何呈现此代码可在此结构和功能集内操作吗? (Python版本2.6 yey;忽略了无限循环,这只是一个占位符)

服务器代码:

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() 
+3

你可能会得到幸运,并有专人编写代码为你在这里,但我怀疑这一点,partnah。 StackOverflow问题需要更专注一些,看起来不像功课练习。 – msw 2010-11-21 23:11:51

+0

UDP聊天?哈哈很好! PS:修正了缩进... – 2010-11-21 23:14:24

+1

,而不是说“怪异的废话开始发生”,你可能想解释你所看到的详细错误。另外,请尝试将其分解为更简单的示例,以更加明确地分析问题。这将是为了你自己的利益,也可能使问题变得可以回答。 – 2010-11-21 23:14:48

回答

0

我工作的事情很多这样的,但我将实施文本加密。我看到你正在为客户名单起诉名单......但我会说有一个更好的方式来做到这一点。我正在使用字典。

如果您熟悉字典,请跳过下一段。

Dicionaries可以基本处理2个变量,并使用{}定义。

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

,因此使用此,您可以可以像{“用户名”:“IPADDR”}字典这种方式可以让这个两个用户名和IPS都是一个变量。如果你想要像我这样的最终产品,你会做到这一点,所以服务器所做的就是重复这条消息,并将它发送给所有连接的人。那么服务器可以循环访问用户名。

作为另一个说明,我认为tcpsoc.listen(5)是一次可以连接多少人......我认为这就是我在某处阅读的内容。

我不知道为什么你会有这样的错误,但如果你想看看我的中途建立的代码,你是多么欢迎。 (忽略进口随机的,这还没有使用,但将加密系统的一部分)

http://piratepad.net/PwQzdU0bkk