2010-11-21 38 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