服務端套接字函數shell
s.bind() 綁定(主機,端口號)到套接字
s.listen() 開始TCP監聽
s.accept() 被動接受TCP客戶的鏈接,(阻塞式)等待鏈接的到來
客戶端套接字函數編程
s.connect() 主動初始化TCP服務器鏈接
s.connect_ex() connect()函數的擴展版本,出錯時返回出錯碼,而不是拋出異常
公共用途的套接字函數windows
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() 獲得阻塞套接字操做的超時時間
面向文件的套接字的函數服務器
s.fileno() 套接字的文件描述符
s.makefile() 建立一個與該套接字相關的文件
tcp是基於連接的,必須先啓動服務端,而後再啓動客戶端去連接服務端網絡
socket是位於應用層與傳輸層之間的一個抽象層,專門把傳輸層如下的協議封裝成接口提供給應用層使用,應用只須要調用socket的接口或者說按照socket的標準編寫程序,寫出的程序天然是遵循TCP/IP協議socket
tcp的協議數據不會丟,沒有收完包,下次接收,會繼續上次繼續接收,己端老是在收到ack時纔會清除緩衝區內容。數據是可靠的,可是會粘包tcp
客戶端:函數
import socket #地址家族,基於網絡 TCP協議 phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 建立客戶套接字 phone.connect(('127.0.0.1',8080))#服務端ip和端口 # 嘗試鏈接服務器 phone.send('你好'.encode('utf-8')) # 發消息b'hello' data=phone.recv(1024) #收消息 print(data.decode('utf-8')) phone.close() # 關閉客戶套接字
服務端:編碼
import socket phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 建立服務器套接字 phone.bind(('127.0.0.1',8080) #地址綁定到套接字(0-65535) 0-1024給系統用的 phone.listen(5) # 監聽連接 print('start...') conn,client_addr=phone.accept() # 接受客戶端連接 print('鏈接來了:',conn,client_addr) #conn: 鏈接對象 client_addr: 客戶端的ip和端口 # 收發消息 msg=conn.recv(1024) #收消息,1024是一個最大的限制 print('客戶端的消息: ',msg) conn.send(msg+b'SB') # 掛電話 conn.close() #關閉客戶端套接字 # 關機 phone.close() #關閉服務器套接字(可選)
服務端:
import socket phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.bind(('127.0.0.1',8081)) phone.listen(5) print('start...') while True: # 鏈接循環 conn,client_addr=phone.accept() print('客戶端 ',client_addr) while True: # 通訊循環 try: msg=conn.recv(1024) print('客戶端的消息: ',msg) conn.send(msg+b'SB') except ConnectionResetError: #只有在當前客戶端中止向服務端發送信息時,下一個客戶端才能發送 break conn.close() phone.close()
客戶端:
import socket phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 買電話 phone.connect(('127.0.0.1',8081)) # 嘗試鏈接服務器 地址爲服務端的ip和端口 while True: msg=input('>>>: ').strip() phone.send(msg.encode('utf-8')) # 發消息b'hello' data=phone.recv(1024) #收消息 print(data.decode('utf-8')) phone.close()
注意:
res=subprocess.Popen(cmd.decode('utf-8'), shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
的結果的編碼是以當前所在的系統爲準的,若是是windows,那麼res.stdout.read()讀出的就是GBK編碼的,在接收端須要用GBK解碼,且只能從管道里讀一次結果
客戶端:
from socket import * client=socket(AF_INET,SOCK_STREAM) client.connect(('127.0.0.1',8080)) while True: cmd=input('>>>: ').strip() if not cmd: continue client.send(cmd.encode('utf-8')) res=client.recv(14744) print(res.decode('gbk'))#subprocess返回byte類型,須要gbk解碼 client.close()
服務端:
from socket import * import subprocess server=socket(AF_INET,SOCK_STREAM) server.bind(('127.0.0.1',8080)) server.listen(5) while True: conn,client_addr=server.accept() #(鏈接對象,客戶端的ip和端口) print(client_addr) while True: try: cmd=conn.recv(1024) obj=subprocess.Popen(cmd.decode('utf-8'),#subprocess返回byte類型,可直接傳輸但須要gbk解碼 shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) stdout=obj.stdout.read() stderr=obj.stderr.read() total=stdout + stderr# 發送真實的數據 conn.send(total) except ConnectionResetError: break conn.close() server.close()