TCPServer.py
1 #coding:utf-8 2 3 import socket 4 #s 等待鏈接 5 #c 實時通訊 6 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 7 #socket.AF_INET代表ipv4,socket.SOCK_STREAM代表tcp套接字 8 s.bind(('',23333)) 9 #綁定ip端口 如果為空,那就是所有網絡號都可以 10 s.listen(5) 11 #最大同時5個人鏈接 12 13 14 print('[+]服務端開啟') 15 16 while True: 17 try: 18 c,c_addr = s.accept() 19 #這里只能接受一個人鏈接,如果要鏈接多個客戶端,需要開啟多線程 20 #先接受客戶端的連接 21 #阻塞形式 22 #client 通訊操作的套接字 23 #c_addr 是客戶端的地址 24 25 print('有人來鏈接了:',c_addr) 26 while True: 27 data = c.recv(1024).decode('utf-8') 28 #客戶端斷開鏈接 會發送一個空字符串,長度為0 29 #data存儲的是最大1024字節的數據 30 #要decode解碼,以utf8的形式 31 if not data: 32 #判斷接受到的數據,是不是為空,如果為空的話 就表示客戶端已經斷開鏈接 33 # print(type(data)) 34 # print('----------') 35 # print(len(data)) 36 # print('----------') 37 print('[+] 這個人走了') 38 break 39 #跳出循環,斷開鏈接 40 print('這個人說',data) 41 msg = input('>>>') 42 #回復客戶端 43 if msg == 'quit': 44 #如果 msg為 quit 就與客戶端主動斷開鏈接 45 print('[+] 與這個人主動斷開鏈接.....') 46 break 47 c.send(msg.encode('utf-8')) 48 #發送的時候加碼,以uff8的形式 49 c.close() 50 #斷開與客戶端的連接 51 except KeyboardInterrupt: 52 #ctrl+c終止程序 防止卡主 53 print('檢測到異常 即將推出') 54 break 55 56 print('[+] 服務器關閉') 57 s.close()
TCPclient.py
1 #coding:utf-8 2 3 import socket 4 client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 5 #創建一個客戶端鏈接,socket.AF_INET代表ipv4,socket.SOCK_STREAM代表tcp套接字 6 client.connect(('127.0.0.1',23333)) 7 #客戶端鏈接 8 print('[+] 鏈接成功') 9 #鏈接成功顯示 10 while True: 11 msg = input('>>>') 12 if msg == 'quit': 13 #如果輸入的信息是quit 就退出鏈接 14 break 15 if len(msg) == 0:#如果直接輸入的一個回車的話 16 #就重新輸入,因為不能發送空 ,發送空的花 客戶端會卡住 17 continue 18 client.send(msg.encode('utf-8')) 19 #客戶端發送信息msg 以utf8格式發送數據 20 data = client.recv(1024).decode('utf-8') 21 if not data: 22 #如果數據為空/0 23 #服務器主動斷開s 24 break 25 print('[+] 服務器主動斷開了鏈接......') 26 27 print('服務器發來:',data) 28 29 30 print('[+] 鏈接關閉...') 31 32 client.close()
#注意事項:
- 網絡中傳輸數據的格式是二進制,所以傳輸的數據都要編碼和解碼,默認是UTF-8
- 代碼中發送和接受的數據最大為1024字節,如果大於這個數據,數據會留在緩沖區,等待下一次發送,如果要一次性發送,需要用到循環語句
- 客戶端和服務器如果斷開連接的話,會發送一個空字符串,長度為0,然后對方用一個判斷語句來判斷是否斷開鏈接
- 發送的數據不能為空,假如直接按回車的話 會發送空,是不行的,程序會卡住,input對於用戶輸入的換行是不會讀入的,因為我們都知道input是以換行作為輸入結束的標志的。
- 對於空消息:tcp是基於數據流的,於是收發的消息不能為空,這就需要在客戶端和服務端都添加空消息的處理機制,防止程序卡住,
- QQ也是這樣的,不能發送為空的內容
-
服務器套接字創建模型:
-
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
-
s.bind( ('', 8000) ):綁定該套接字有效地址和端口
-
參數是一個元組
-
-
s.listen(5) 開啟服務器
-
c,c_addr = s.accept() 阻塞等待客戶端連接
-
c:客戶端來訪套接字來與客戶端進行交流
-
c_addr:客戶來訪地址,(ip,port)
-
-
while:具體和這個客戶端進行溝通
-
c.send(msg)
-
發送數據
-
msg == byte
-
-
data = c.recv(1024): -> bytes
-
接收數據
-
接收到的也是個二進制
-
-
取決於客戶端發來的數據如果為空,那么就可以關閉與他的連接了。
-
-
c.close()
-
關閉套接字 釋放資源
-
-
s.close()
-
-
-
-
客戶端套接字模型:
-
c = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
-
c.connect( (ip,port) )
-
47.104.224.67
-
8000
-
-
c.recv() 接收
-
c.send() 發送
-
c.close()
-
關閉套接字 斷開連接 釋放資源
-
-
-
-
單進程模型下,我們寫的代碼,同一時間只能處理一個用戶的來訪信息
-
TCP是要構成連接的
-