點對點聊天首先是基于多線程的網絡編程,其次就是將每一個連接都保存為一個具有獨一屬性的對象并添加到連接列表中,對于每一個連接對象發送過來的信息必須要包含主要的三項內容(from,to,messages),這樣當信息發送到服務器之后服務器根據to的連接對象遍歷連接列表找到目標對象將信息發送給目標,目標拿到信息后就知道是誰發過來的,然后根據id號碼進行回復。此實現將會繼續完善,后續新加功能將會在我個人github主頁展現
服務器端實現:
#coding:utf-8'''file:server.pydate:2017/9/10 12:43author:lockeyemail:lockey@123.complatform:win7.x86_64 pycharm python3desc:p2p communication serverside'''import socketserver,jsonimport subprocessconnLst = []## 連接列表,用來保存一個連接的信息(代號 地址和端口 連接對象)class Connector(object):#連接對象類 def __init__(self,account,password,addrPort,conObj): self.account = account self.password = password self.addrPort = addrPort self.conObj = conObjclass MyServer(socketserver.BaseRequestHandler): def handle(self): print("got connection from",self.client_address) register = False while True: conn = self.request data = conn.recv(1024) if not data: continue dataobj = json.loads(data.decode('utf-8')) #如果連接客戶端發送過來的信息格式是一個列表且注冊標識為False時進行用戶注冊 if type(dataobj) == list and not register: account = dataobj[0] password = dataobj[1] conObj = Connector(account,password,self.client_address,self.request) connLst.append(conObj) register = True continue print(connLst) #如果目標客戶端在發送數據給目標客服端 if len(connLst) > 1 and type(dataobj) == dict: sendok = False for obj in connLst: if dataobj['to'] == obj.account: obj.conObj.sendall(data) sendok = True if sendok == False: print('no target valid!') else: conn.sendall('nobody recevied!'.encode('utf-8')) continueif __name__ == '__main__': server = socketserver.ThreadingTCPServer(('192.168.1.4',8022),MyServer) print('waiting for connection...') server.serve_forever()
客戶端實現:
#coding:utf-8'''file:client.py.pydate:2017/9/10 11:01author:lockeyemail:lockey@123.complatform:win7.x86_64 pycharm python3desc:p2p communication clientside'''from socket import *import threading,sys,json,reHOST = '192.168.1.4' ##PORT=8022BUFSIZ = 1024 ##緩沖區大小 1KADDR = (HOST,PORT)tcpCliSock = socket(AF_INET,SOCK_STREAM)tcpCliSock.connect(ADDR)userAccount = Nonedef register(): myre = r"^[_a-zA-Z]/w{0,}" #正則驗證用戶名是否合乎規范 accout = input('Please input your account: ') if not re.findall(myre, accout): print('Account illegal!') return None password1 = input('Please input your password: ') password2 = input('Please confirm your password: ') if not (password1 and password1 == password2): print('Password not illegal!') return None global userAccount userAccount = accout return (accout,password1)class inputdata(threading.Thread): def run(self): while True: sendto = input('to>>:') msg = input('msg>>:') dataObj = {'to':sendto,'msg':msg,'froms':userAccount} datastr = json.dumps(dataObj) tcpCliSock.send(datastr.encode('utf-8'))class getdata(threading.Thread): def run(self): while True: data = tcpCliSock.recv(BUFSIZ) dataObj = json.loads(data.decode('utf-8')) print('{} -> {}'.format(dataObj['froms'],dataObj['msg']))def main(): while True: regInfo = register() if regInfo: datastr = json.dumps(regInfo) tcpCliSock.send(datastr.encode('utf-8')) break myinputd = inputdata() mygetdata = getdata() myinputd.start() mygetdata.start() myinputd.join() mygetdata.join()if __name__ == '__main__': main()運行結果示例:
服務器端結果:

客戶端1:

客戶端2:

客戶端3:

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。
新聞熱點
疑難解答