Python 基于 Socket 實現(xiàn)群聊
↑?關注 + 星標?,每天學Python新技能
后臺回復【大禮包】送你Python自學大禮包
來源:博客園-huny
https://www.cnblogs.com/huny/p/14051152.html
互聯(lián)網時代,怎么能不懂點網絡編程?套接字(Sockets)是雙向通信信道的端點,本文詳細介紹了使用Socket實現(xiàn)類似微信群聊的功能,快進來一起學習下吧!
1.前言
套接字(Sockets)是雙向通信信道的端點。套接字可以在一個進程內,在同一機器上的進程之間,或者在不同主機的進程之間進行通信,主機可以是任何一臺有連接互聯(lián)網的機器。
套接字可以通過多種不同的通道類型實現(xiàn):Unix域套接字,TCP,UDP等。套接字庫提供了處理公共傳輸?shù)奶囟?,以及一個用于處理其余部分的通用接口。
1.1 socket模塊:
要創(chuàng)建套接字,必須使用套接字模塊中的socket.socket()函數(shù),該函數(shù)具有一般語法
s = socket.socket (socket_family, socket_type, protocol = 0)
1.2 常用方法

2. 示例1
2.1?服務器端
#sever.pyimport sockets = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)host = socket.gethostname()port = 8088s.bind((host,port))try:while True:receive_data,addr = s.recvfrom(1024)print("來自服務器" + str(addr) + "的消息:")print(receive_data.decode('utf-8'))msg = input('please input send to msg:')s.sendto(msg.encode('utf-8'),addr)except:s.close()
2.2 客戶端
#client.pyimport sockets = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)try:while True:host = socket.gethostname()port = 8088send_data = input('please input msg:')s.sendto(send_data.encode('utf-8'),(host,port))msg,addr = s.recvfrom(1024)print("來自服務器" + str(addr) + "的消息:")print(msg.decode('utf-8'))except:s.close()
服務器示例

客戶端示例

簡易的UDP聊天實現(xiàn)了,下面我們來優(yōu)化一下示例。
3.示例優(yōu)化
服務端
#server.pyimport socketimport loggingdef main():s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 創(chuàng)建socket對象addr = ('127.0.0.1', 9999)s.bind(addr) # 綁定地址和端口logging.info('UDP Server on %s:%s...', addr[0], addr[1])user = {} # 存放字典{addr:name}while True:try:data, addr = s.recvfrom(1024) # 等待接收客戶端消息存放在2個變量data和addr里if not addr in user: # 如果addr不在user字典里則執(zhí)行以下代碼for address in user: # 從user遍歷數(shù)據出來addresss.sendto(data + ' 進入聊天室...'.encode('utf-8'), address) # 發(fā)送user字典的data和address到客戶端user[addr] = data.decode('utf-8') # 接收的消息解碼成utf-8并存在字典user里,鍵名定義為addrcontinue # 如果addr在user字典里,跳過本次循環(huán)if 'EXIT'.lower() in data.decode('utf-8'):#如果EXIT在發(fā)送的data里name = user[addr] #user字典addr鍵對應的值賦值給變量nameuser.pop(addr) #刪除user里的addrfor address in user: #從user取出addresss.sendto((name + ' 離開了聊天室...').encode(), address) #發(fā)送name和address到客戶端else:print('"%s" from %s:%s' %(data.decode('utf-8'), addr[0], addr[1]))for address in user: #從user遍歷出addressif address != addr: #address不等于addr時間執(zhí)行下面的代碼s.sendto(data, address) #發(fā)送data和address到客戶端except ConnectionResetError:logging.warning('Someone left unexcept.')if __name__ == '__main__':main()
客戶端
#clinet.pyimport socketimport threadingdef recv(sock, addr):'''一個UDP連接在接收消息前必須要讓系統(tǒng)知道所占端口也就是需要send一次,否則win下會報錯'''sock.sendto(name.encode('utf-8'), addr)while True:data = sock.recv(1024)print(data.decode('utf-8'))def send(sock, addr):'''發(fā)送數(shù)據的方法參數(shù):sock:定義一個實例化socket對象server:傳遞的服務器IP和端口'''while True:string = input('')message = name + ' : ' + stringdata = message.encode('utf-8')sock.sendto(data, addr)if string.lower() == 'EXIT'.lower():breakdef main():'''主函數(shù)執(zhí)行方法,通過多線程來實現(xiàn)多個客戶端之間的通信'''s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)server = ('127.0.0.1', 9999)tr = threading.Thread(target=recv, args=(s, server), daemon=True)ts = threading.Thread(target=send, args=(s, server))tr.start()ts.start()ts.join()s.close()if __name__ == '__main__':print("-----歡迎來到聊天室,退出聊天室請輸入'EXIT(不分大小寫)'-----")name = input('請輸入你的名稱:')print('-----------------%s------------------' % name)main()
支持多人的簡易聊天室示例,多個客戶端通過一個服務器進行之間通信。




(完)
推薦閱讀
掃碼回復「大禮包」后獲取大禮
掃碼加我微信備注「三劍客」送你上圖三本電子書
評論
圖片
表情

