標籤:
通過參考其他牛人的文章和代碼, 再根據自己的理解總結得出, 說明已經加在注釋中, FYI
主要參考文章: http://blog.csdn.net/dk_zhe/article/details/37820965
http://www.cnblogs.com/coser/archive/2012/01/06/2315216.html
https://docs.python.org/2.7/library/select.html?highlight=select#module-select
http://www.cnblogs.com/devinzhang/archive/2012/01/13/2321826.html
http://blog.chinaunix.net/uid-23146151-id-3084687.html
server.py 和 client.py
#coding=utf-8# 通過socket建立網路連接的步驟:# 至少需要2個通訊端, server和client# 需要建立socket之間的串連, 通過串連來進行收發data# client 和 server串連的過程:# 1. 建立server的通訊端,綁定主機和連接埠,並監聽client的串連請求# 2. client通訊端根據server的地址發出串連請求, 串連到server的socket上; client socket需要提供自己的 socket fd,以便server socket回應# 3. 當server監聽到client串連請求時, 響應請求, 建立一個新的線程, 把server fd 發送給client# 而後, server繼續監聽其他client請求, 而client和server通過socket串連互發data通訊import socket,select,threadhost = socket.gethostname()port = 5963server_addr = (host,port)# waitable的read list, 表示非同步通訊中可讀socket對象的列表inputs = []# 串連進入server的client的名稱fd_name = {}# 建立並初始化server socketdef serverInit(): ss = socket.socket() # 建立server socket ss.bind(server_addr) # 綁定到server addr ss.listen(10) # 監聽連接埠號碼, 設定最大監聽數10 return ss # 返回初始化後的server socket# 建立一個新的socket串連def newConnection(ss): client_conn,client_addr = ss.accept() # 響應一個client的串連請求, 建立一個串連,可以用來傳輸資料 try: # 向client端發送歡迎資訊 client_conn.send("welcome to chatroom,pls set up your nick name!") client_name = client_conn.recv(1024) #接收client發來的暱稱,最大接收字元為1024 inputs.append(client_conn) fd_name[client_conn] = client_name # 將串連/串連名 加入索引值對 client_conn.send("current members in chatroom are: %s" % fd_name.values()) # 向所有串連發送新成員加入資訊 for other in fd_name.keys(): if other != client_conn and other != ss: other.send(fd_name[client_conn]+" joined the chatroom!") except Exception as e: print edef closeConnection(): passdef run(): ss = serverInit() inputs.append(ss) print "server is running..." while True: # rlist,wlist,elist = select.select(inputs, [], inputs,100) # 如果只是伺服器開啟,100s之內沒有client串連,則也會逾時關閉 rlist,wlist,elist = select.select(inputs, [], []) # 當沒有可讀fd時, 表示server錯誤,退出伺服器 if not rlist: print "timeout..." ss.close() # 關閉 server socket break for r in rlist: if r is ss: # server socket, 表示有新的client串連請求 newConnection(ss) else: # 表示一個client串連上有資料到達伺服器 disconnect = False try: data = r.recv(1024) #接收data data = fd_name[r] + " : "+ data # 確定用戶端暱稱 except socket.error: data = fd_name[r] + " leaved the room" disconnect = True else: pass if disconnect: inputs.remove(r) print data for other in inputs: if other != ss and other != r: #不發生到伺服器和已經斷開的串連 try: other.send(data) except Exception as e: print e else: pass # 除名 del fd_name[r] else: print data # 在伺服器顯示client發送的資料 # 向其他成員(串連)發送相同的資訊 for other in inputs: if other != ss and other != r: try: other.send(data) except Exception as e: print eif __name__ == "__main__": run()
#coding=utf-8# 由於實驗都在本機上運行, 所以server addr == client addrimport socket,select,threading,syshost = socket.gethostname()client_addr = (host,5963) # equals server_addr()# 傾聽其他成員談話def listening(cs): inputs = [cs] while True: rlist,wlist,elist = select.select(inputs, [], []) # client socket就是用來收發資料的, 由於只有這個waitable 對象, 所以不必迭代 if cs in rlist: try: # 列印從伺服器收到的資料 print cs.recv(1024) except socket.error: print "socket is error" exit()# 發言def speak(cs): while True: try: data = raw_input() except Exception as e: print r"can‘t input" exit() # if data == "exit": # cs.close() # break try: cs.send(data) except Exception as e: exit()def main(): # client socket cs = socket.socket() cs.connect(client_addr) # 分別啟動聽和說線程 t = threading.Thread(target=listening,args=(cs,)) # 注意當元組中只有一個元素的時候需要這樣寫, 否則會被認為是其原來的類型 t.start() t1 = threading.Thread(target=speak,args=(cs,)) t1.start()if __name__ == "__main__": main()
Python Socket實現簡單的聊天室