Python網路程式設計----實現簡單的多人聊天室
阿新 • • 發佈:2018-12-19
還是用UDP,socket作為主體來實現,之前我們已經實現過單對單socket通訊,這次想實現群發功能
原理其實就是一臺伺服器在負責分配轉發資料,來達成廣播的效果,這些思路其實也差不多
但是多人聊天沒有這麼強的規整性,你可能沒等到A的訊息,就要去和B說話了,多執行緒就可以實現這一點
主要就是依靠threading模組
你可以理解為,我們建立了一個類似於陣列的空間,來存放我們所有要執行的工作,然後同時開始,然後通過阻塞父程序來等待子程序結束,這就是多執行緒工作
直接上程式碼段好了,用txt和字典可以偽造一個非常非常破的聊天室,自己其實感覺做的挺垃圾的,畢竟最後的成品,本地就算是儲存了個人資訊,要群發訊息的話,還需要伺服器存放的字典的values來追蹤各個地址,完全是脫節的,唉,菜到落淚,不會資料庫,也沒有介面,不過總算是熟悉了一波字典的操作,爭取早日用上json
SERVER:
import json import socket name_dict={} #空字典 def register(data,client_addr): f=open("members.txt",'a+') data=data[9::] key=data.decode('utf-8') line=f.readline().strip() print(line) result=line.find(key) if result >=0: s="your information has been used, please register again" server.sendto(s.encode('utf-8'),client_addr) f.close() return 1 while line: line = f.readline().strip() result=line.find(key) if result>=0: s="your information has been used, please register again" server.sendto(s.encode('utf-8'),client_addr) f.close() return 1 #print(key[:8:]) #print(key[9::]) f.write('name/password:%s\n' %key) s='welcome,now you can login' server.sendto(s.encode('utf-8'),client_addr) f.close() return 0 def login(data,client_addr): f=open("members.txt",'r+') data=data[9::] #print(data) key=data.decode('utf-8') print(key) #data,client_addr = server.recvfrom(BUFSIZE) #從緩衝區讀取1024個位元組,The return value is a pair (bytes, client_address) #try: line=f.readline().strip() result=line.find(key) print(result) if result >=0: name_dict[key]=client_addr s='wait for you for a long time, what do you want to tell to others' server.sendto(s.encode('utf-8'),client_addr) f.close() return 1 while line: line=f.readline().strip() result=line.find(key) if result >=0: name_dict[key]=client_addr s='wait for you for a long time, what do you want to tell to others' server.sendto(s.encode('utf-8'),client_addr) f.close() return 1 s='wrong password or name, goodbye' #make client closed server.sendto(s.encode('utf-8'),client_addr) f.close() return 0 def qunfa111(data,client_addr): #data=data.decode('utf-8') data=data[9::] flag=0 for value in name_dict.values(): if value==client_addr: flag=1 for value in name_dict.values(): if value==client_addr: continue server.sendto(data,value) if flag==0: server.sendto(b'please login first',client_addr) return def sifa1111(data,client_addr,toname): toname=data[9:28:] print(toname) data2=data[28::] print(data2) flag=0 print(name_dict) for value in name_dict.values(): if value==client_addr: flag=1 for key in name_dict.keys(): if key==toname: server.sendto(data2,name_dict[toname]) server.sendto(b'OK',client_addr) return flag=2 if flag==2: server.sendto(b'who is he?',client_addr) return if flag==0: server.sendto(b'please login first',client_addr) return #----------------------------------------------------------------------------------------------------------------------------------------------------- BUFSIZE = 1024 #規定緩衝區的大小 ip_port = ('127.0.0.1', 9999) server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # udp協議 server.bind(ip_port) print('Listening at {}'.format(server.getsockname)) #getsockname()可以獲取套接字目前繫結的IP地址即埠,返回的是一個二元組 #s='welcome, what do you want to do: QUIT,register,login' #server.sendto(s.encode('utf-8'),client_addr) while True: data,client_addr = server.recvfrom(BUFSIZE) #從緩衝區讀取1024個位元組,The return value is a pair (bytes, client_address) print(data[:8:]) if data[:8:]==b'Leaving~': server.sendto(b'see you later',client_addr) for key in name_dict.keys(): if name_dict[key]==client_addr: del name_dict[key] continue elif data[:8:]==b'register': #print(data) n=1 while(n): n=register(data,client_addr) elif data[:8:]==b'logining': #data=data[9::] login(data,client_addr) elif data[:8:]==b'sifa1111': sifa1111(data,client_addr,data[9:12:]) #名字暫時只能3個字元 elif data[:8:]==b'qunfa111': qunfa111(data,client_addr) server.close()
CLIENT
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import socket import threading BUFSIZE = 1024 client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # udp協議 print('welcome, what do you want to do: Leaving~,register,logining') ip_port = ('127.0.0.1', 9999) def recv(): while(True): client.connect(ip_port) data,server_addr= client.recvfrom(BUFSIZE) if data==b'see you later': #輸入QUIT即可斷開連線 print('Data recived from sever:',data,server_addr) client.close() print('Data recived from sever:',data.decode('gb2312','ignore'),server_addr) def send(): while(True): msg = input(">> ").strip() #strip() 方法用於移除字串頭尾指定的字元(預設為空格或換行符)或字元序列 client.sendto(msg.encode('utf-8'),ip_port) # 以utf-8編碼對u進行編碼,獲得bytes型別物件 threads=[] t1 = threading.Thread(target=send) threads.append(t1) t2 = threading.Thread(target=recv) threads.append(t2) for i in range(len(threads)): #啟動執行緒 threads[i].start() threads[0].join() #send未結束不可以停止
群發問題不大,但是私聊還有問題,調對齊很麻煩,先不弄了