簡單的套接字通訊\加通訊迴圈\修復bug\連結迴圈
阿新 • • 發佈:2018-12-01
客戶端
import socket # 1、買手機 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 2、打電話 phone.connect(("127.0.0.1", 8080)) # phone相當於服務端的conn # 3、發、收訊息 phone.send('hello'.encode("utf-8")) data = phone.recv(1024) print(data) # 4、關閉 phone.close()
服務端
import socket # 1、買手機 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 2、繫結手機卡 phone.bind(("127.0.0.1", 8080)) # 127.0.0.1本地地址,埠範圍0-65535:其中0-1024給作業系統使用 # 3、開機 phone.listen(5) # 5代表最大掛起連線數 # 4、等電話連線 print("starting...") conn, client = phone.accept() # 5、收、發訊息 data = conn.recv(1024) # 收1024個位元組,接受資料的最大數。單位是bytes print("客戶端的資料", data) conn.send(data.upper()) # 6、掛電話 conn.close() # 7、關機 phone.close()
加迴圈(通訊迴圈)
客戶端
import socket # 1、買手機 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 2、打電話 phone.connect(("127.0.0.1", 8080)) # phone相當於服務端的conn # 3、發、收訊息 while True: msg = input(">> ").strip() phone.send(msg.encode("utf-8")) data = phone.recv(1024) print(data) # 4、關閉 phone.close()
服務端
import socket # 1、買手機 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 2、繫結手機卡 phone.bind(("127.0.0.1", 8080)) # 127.0.0.1本地地址,埠範圍0-65535:其中0-1024給作業系統使用 # 3、開機 phone.listen(5) # 5代表最大掛起連線數 # 4、等電話連線 print("starting...") conn, client = phone.accept() # 5、收、發訊息 while True: data = conn.recv(1024) # 收1024個位元組,接受資料的最大數。單位是bytes print("客戶端的資料", data) conn.send(data.upper()) # 6、掛電話 conn.close() # 7、關機 phone.close()
加連線迴圈
客戶端
import socket # 1、買手機 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 2、打電話 phone.connect(("127.0.0.1", 8080)) # phone相當於服務端的conn # 3、發、收訊息 while True: msg = input(">> ").strip() if not msg: continue phone.send(msg.encode("utf-8")) data = phone.recv(1024) print(data.decode("utf-8")) # 4、關閉 phone.close()
服務端
import socket # 1、買手機 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # (如果機器中存在,重新用埠)應對端口占用報錯情況 # 2、繫結手機卡 phone.bind(("127.0.0.1", 8080)) # 127.0.0.1本地地址,埠範圍0-65535:其中0-1024給作業系統使用 # 3、開機 phone.listen(5) # 5代表最大掛起連線數 # 4、等電話連線 print("starting...") while True: # 迴圈連結 conn, client = phone.accept() # conn套接字物件 # 5、收、發訊息 while True: # 通訊迴圈 try: data = conn.recv(1024) # 收1024個位元組,接受資料的最大數。單位是bytes # if not data: break # 僅適用於Linux作業系統(客戶端斷開),win 用try...except print("客戶端的資料", data) conn.send(data.upper()) except ConnectionRefusedError: break # 6、掛電話 conn.close() # 7、關機 phone.close()
修復bug
1、客戶端單方面斷開,服務端: linux 解決辦法:if not data:break
windows 解決辦法:try...except
send 可以發 空 # 發給了os的記憶體 在呼叫網絡卡 傳送資料
recv 不可以 收空 # 到了os的記憶體 在傳給了應用程式記憶體
所以 客戶端 就卡住了 if not msg:continue 卡住原因 os 不會發''(空)資料
2、埠已存在,重用
問題:
這個是由於你的服務端仍然存在四次揮手的time_wait狀態在佔用地址
解決辦法1:
#加入一條socket配置,重用ip和埠
phone=socket(AF_INET,SOCK_STREAM)
phone.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
phone.bind(('127.0.0.1',8080))
解決辦法2:
發現系統存在大量TIME_WAIT狀態的連線,通過調整linux核心引數解決,
vi /etc/sysctl.conf
編輯檔案,加入以下內容:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
然後執行 /sbin/sysctl -p 讓引數生效。
net.ipv4.tcp_syncookies = 1 表示開啟SYN Cookies。當出現SYN等待佇列溢位時,啟用cookies來處理,可防範少量SYN攻擊,預設為0,表示關閉;
net.ipv4.tcp_tw_reuse = 1 表示開啟重用。允許將TIME-WAIT sockets重新用於新的TCP連線,預設為0,表示關閉;
net.ipv4.tcp_tw_recycle = 1 表示開啟TCP連線中TIME-WAIT sockets的快速回收,預設為0,表示關閉。
net.ipv4.tcp_fin_timeout 修改系統預設的 TIMEOUT 時間
客戶端
import socket # 1、買手機 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 2、打電話 phone.connect(("127.0.0.1", 8080)) # phone相當於服務端的conn # 3、發、收訊息 while True: msg = input(">> ").strip() if not msg: continue phone.send(msg.encode("utf-8")) data = phone.recv(1024) print(data.decode("utf-8")) # 4、關閉 phone.close()
服務端
import socket # 1、買手機 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # (如果機器中存在,重新用埠)應對端口占用報錯情況 # 2、繫結手機卡 phone.bind(("127.0.0.1", 8080)) # 127.0.0.1本地地址,埠範圍0-65535:其中0-1024給作業系統使用 # 3、開機 phone.listen(5) # 5代表最大掛起連線數 # 4、等電話連線 print("starting...") conn, client = phone.accept() # conn套接字物件 # 5、收、發訊息 while True: try: data = conn.recv(1024) # 收1024個位元組,接受資料的最大數。單位是bytes # if not data: break # 僅適用於Linux作業系統(客戶端單方面斷開),win 用try...except print("客戶端的資料", data) conn.send(data.upper()) except ConnectionRefusedError: break # 6、掛電話 conn.close() # 7、關機 phone.close()