作者:huny
https://www.cnblogs.com/huny/p/14051152.html
套接字(Sockets)是雙向通信信道的端點。套接字可以在一個進程內,在同一機器上的進程之間,或者在不同主機的進程之間進行通信,主機可以是任何一臺有連接網際網路的機器。
套接字可以通過多種不同的通道類型實現:Unix域套接字,TCP,UDP等。套接字庫提供了處理公共傳輸的特定類,以及一個用於處理其餘部分的通用接口。
1.1 socket模塊:
要創建套接字,必須使用套接字模塊中的socket.socket()函數,該函數具有一般語法
s = socket.socket (socket_family, socket_type, protocol = 0)1.2 常用方法
2. 示例
2.1 伺服器端
import socket
s = 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 客戶端
import sockets = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)try: while True: host = socket.gethostname() port = 8088 send_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聊天實現了,下面我們來優化一下示例。
3.示例優化
服務端
import socketimport logging
def main(): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
addr = ('127.0.0.1', 9999) s.bind(addr)
logging.info('UDP Server on %s:%s...', addr[0], addr[1])
user = {} while True: try: data, addr = s.recvfrom(1024) if not addr in user: for address in user: s.sendto(data + ' 進入聊天室...'.encode('utf-8'), address) user[addr] = data.decode('utf-8') continue
if 'EXIT'.lower() in data.decode('utf-8'): name = user[addr] user.pop(addr) for address in user: s.sendto((name + ' 離開了聊天室...').encode(), address) else: print('"%s" from %s:%s' %(data.decode('utf-8'), addr[0], addr[1])) for address in user: if address != addr: s.sendto(data, address)
except ConnectionResetError: logging.warning('Someone left unexcept.')
if __name__ == '__main__': main()客戶端
import socketimport threading
def recv(sock, addr): ''' 一個UDP連接在接收消息前必須要讓系統知道所佔埠 也就是需要send一次,否則win下會報錯 ''' sock.sendto(name.encode('utf-8'), addr) while True: data = sock.recv(1024) print(data.decode('utf-8'))
def send(sock, addr): ''' 發送數據的方法 參數: sock:定義一個實例化socket對象 server:傳遞的伺服器IP和埠 ''' while True: string = input('') message = name + ' : ' + string data = message.encode('utf-8') sock.sendto(data, addr) if string.lower() == 'EXIT'.lower(): break
def main(): ''' 主函數執行方法,通過多線程來實現多個客戶端之間的通信 ''' 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()支持多人的簡易聊天室示例,多個客戶端通過一個伺服器進行之間通信。