## socket ```python socket 就是套接字: CP用主機的IP地址加上主機上的端口號做爲TCP鏈接的端點,這種端點就叫作套接字 它是網絡通訊過程當中端點的抽象表示,包含進行網絡通訊必需的五種信息:鏈接使用的協議,本地主機的IP地址,本地進程的協議端口,遠地主機的IP地址,遠地進程的協議端口。 #網絡通訊和鏈接,主要有3個參數:通訊的目的IP地址、使用的傳輸層協議(TCP或UDP)和使用的端口號。Socket原意是 「插座」。經過將這3個參數結合起來,與一個「插座」Socket綁定,應用層就能夠和傳輸層經過套接字接口,區分來自不一樣應用程序進程或網絡鏈接的通訊,實現數據傳輸的併發服務 就是一個封裝好的模塊,要學習的就是模塊的使用方法 socket分爲兩種類型 AF_UNIX : 進程間通信 AF_INET : 網絡通信 需明確:關於網絡協議 和socket相關概念,對於全部編程語言都是一致的,區別僅僅是各編程語言的函數名稱不一樣 要明確一點:不管是客戶端服務器端都使用的都是socket對象 ``` ## socket內經常使用函數 ```python 服務端套接字函數 s.bind() 綁定(主機,端口號)到套接字 s.listen() 開始TCP監聽 s.accept() 被動接受TCP客戶的鏈接,(阻塞式)等待鏈接的到來 客戶端套接字函數 s.connect() 主動初始化TCP服務器鏈接 s.connect_ex() connect()函數的擴展版本,出錯時返回出錯碼,而不是拋出異常 公共用途的套接字函數 s.recv() 接收TCP數據 s.send() 發送TCP數據(send在待發送數據量大於己端緩存區剩餘空間時,數據丟失,不會發完) s.sendall() 發送完整的TCP數據(本質就是循環調用send,sendall在待發送數據量大於己端緩存區剩餘空間時,數據不丟失,循環調用send直到發完) s.recvfrom() 接收UDP數據 s.sendto() 發送UDP數據 s.getpeername() 鏈接到當前套接字的遠端的地址 s.getsockname() 當前套接字的地址 s.getsockopt() 返回指定套接字的參數 s.setsockopt() 設置指定套接字的參數 s.close() 關閉套接字 面向鎖的套接字方法 s.setblocking() 設置套接字的阻塞與非阻塞模式 s.settimeout() 設置阻塞套接字操做的超時時間 s.gettimeout() 獲得阻塞套接字操做的超時時間 ``` <p style="color:red">注意TCP中必須先啓動服務器再啓動客戶端,不然客戶端因爲沒法連接服務器,直接報錯!</p> ## TCP服務端 ```python import socket ip_port=('127.0.0.1',8081)#電話卡 BUFSIZE=1024 s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #買手機 s.bind(ip_port) #手機插卡 s.listen(5) #手機待機 while True: #新增接收連接循環,能夠不停的接電話 conn,addr=s.accept() #手機接電話 # print(conn) # print(addr) print('接到來自%s的電話' %addr[0]) while True: #新增通訊循環,能夠不斷的通訊,收發消息 msg=conn.recv(BUFSIZE) #聽消息,聽話 print(msg,type(msg)) conn.send(msg.upper()) #發消息,說話 conn.close() #掛電話 s.close() #手機關機 ``` ## TCP客戶端 ```python import socket ip_port=('127.0.0.1',8081) BUFSIZE=1024 s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect_ex(ip_port) #撥電話 while True: #新增通訊循環,客戶端能夠不斷髮收消息 msg=input('>>: ').strip() if len(msg) == 0:continue s.send(msg.encode('utf-8')) #發消息,說話(只能發送字節類型) feedback=s.recv(BUFSIZE) #收消息,聽話 print(feedback.decode('utf-8')) s.close() #掛電話 ``` 當客服端與服務器連接成功後,若是一方沒有執行close,而是直接強行終止程序(或是遇到異常被迫終止),都會致使另外一方發送問題 linux下,不會拋出異常會致使接收數據的一方,recv方法不斷的收到空消息,形成死循環 要使應用程序可以在不一樣平臺正常工做,那須要分別處理這兩個問題 解決方案以下: ```python import socket ip_port=('127.0.0.1',8081) BUFSIZE=1024 s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.bind(ip_port) s.listen(5) while True: conn,addr=s.accept() while True: try: msg=conn.recv(BUFSIZE) #linux不會拋出異常,會接收到空消息,這裏加以判斷 if not msg: conn.close() break print(msg,type(msg)) conn.send(msg.upper()) except ConnectionResetError: #只要異常發生則意味着對方以及關閉了,服務器也相應的關閉該連接 conn.close() break conn.close() s.close() ``` 至此TCP通信模板程序就完成了,能夠不斷的接收新的連接,不斷的收發消息,而且不會由於客戶端強制關閉而異常退出!