日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

五 Python之socket网络编程

發(fā)布時間:2023/11/29 python 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 五 Python之socket网络编程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

<1>socket概念

socket通常也稱作"套接字",用于描述IP地址和端口,是一個通信鏈的句柄,應(yīng)用程序通常通過"套接字"向網(wǎng)絡(luò)發(fā)出請求或者應(yīng)答網(wǎng)絡(luò)請求。ocket本質(zhì)上就是在2臺網(wǎng)絡(luò)互通的電腦之間,架設(shè)一個通道,兩臺電腦通過這個通道來實現(xiàn)數(shù)據(jù)的互相傳遞。

?

建立一個socket必須至少有2端, 一個服務(wù)端,一個客戶端, 服務(wù)端被動等待并接收請求,客戶端主動發(fā)起請求, 連接建立之后,雙方可以互發(fā)數(shù)據(jù)。

?

注:服務(wù)端與客戶端之間數(shù)據(jù)的傳輸均為字符串,注意編碼 解碼

?<2>簡單客服端與客戶端通信

client端:

#_*_coding:utf-8_*_ #__author__:"shikai"import socket client=socket.socket() #聲明socket類型,并生成socket連接對象 client.connect(("localhost",1234)) #連接服務(wù)器IP和端口 while True:cmd=input("輸入指令:").strip()client.send(cmd.encode()) #發(fā)送消息data=client.recv(1024) #接收數(shù)據(jù)print("recv:",data)client.close()

server端:

#!_*_coding:utf-8_*_ #__author__:"shikai"import socket server=socket.socket() #聲明socket類型,并生成socket連接對象 server.bind(("localhost",1234)) #綁定IP和端口 server.listen() #監(jiān)聽 while True:print("開始等電話了")conn,addr=server.accept() # 阻塞狀態(tài) 等待連接 (accept回返回兩個數(shù)據(jù)conn和addr)#coon就是客服端連接之后,服務(wù)器為其生成的一個連接實例print(conn,addr)while True:print("接電話了")data=conn.recv(1024) #接收數(shù)據(jù)print("recv:",data)conn.send(data.upper()) #處理并發(fā)送返回 (把小寫變成大寫)server.close()

sk.bind(address)

  s.bind(address) 將套接字綁定到地址。address地址的格式取決于地址族。在AF_INET下,以元組(host,port)的形式表示地址。

sk.listen(backlog)

  開始監(jiān)聽傳入連接。backlog指定在拒絕連接之前,可以掛起的最大連接數(shù)量。

? ? ? backlog等于5,表示內(nèi)核已經(jīng)接到了連接請求,但服務(wù)器還沒有調(diào)用accept進行處理的連接個數(shù)最大為5
? ? ? 這個值不能無限大,因為要在內(nèi)核中維護連接隊列

sk.setblocking(bool)

  是否阻塞(默認True),如果設(shè)置False,那么accept和recv時一旦無數(shù)據(jù),則報錯。

sk.accept()

  接受連接并返回(conn,address),其中conn是新的套接字對象,可以用來接收和發(fā)送數(shù)據(jù)。address是連接客戶端的地址。

  接收TCP 客戶的連接(阻塞式)等待連接的到來

sk.connect(address)

  連接到address處的套接字。一般,address的格式為元組(hostname,port),如果連接出錯,返回socket.error錯誤。

sk.connect_ex(address)

  同上,只不過會有返回值,連接成功時返回 0 ,連接失敗時候返回編碼,例如:10061

sk.close()

  關(guān)閉套接字

sk.recv(bufsize[,flag])

  接受套接字的數(shù)據(jù)。數(shù)據(jù)以字符串形式返回,bufsize指定最多可以接收的數(shù)量。flag提供有關(guān)消息的其他信息,通??梢院雎?。

sk.recvfrom(bufsize[.flag])

  與recv()類似,但返回值是(data,address)。其中data是包含接收數(shù)據(jù)的字符串,address是發(fā)送數(shù)據(jù)的套接字地址。

sk.send(string[,flag])

  將string中的數(shù)據(jù)發(fā)送到連接的套接字。返回值是要發(fā)送的字節(jié)數(shù)量,該數(shù)量可能小于string的字節(jié)大小。即:可能未將指定內(nèi)容全部發(fā)送。

sk.sendall(string[,flag])

  將string中的數(shù)據(jù)發(fā)送到連接的套接字,但在返回之前會嘗試發(fā)送所有數(shù)據(jù)。成功返回None,失敗則拋出異常。

? ? ? 內(nèi)部通過遞歸調(diào)用send,將所有內(nèi)容發(fā)送出去。

sk.sendto(string[,flag],address)

  將數(shù)據(jù)發(fā)送到套接字,address是形式為(ipaddr,port)的元組,指定遠程地址。返回值是發(fā)送的字節(jié)數(shù)。該函數(shù)主要用于UDP協(xié)議。

sk.settimeout(timeout)

  設(shè)置套接字操作的超時期,timeout是一個浮點數(shù),單位是秒。值為None表示沒有超時期。一般,超時期應(yīng)該在剛創(chuàng)建套接字時設(shè)置,因為它們可能用于連接的操作(如 client 連接最多等待5s )

sk.getpeername()

  返回連接套接字的遠程地址。返回值通常是元組(ipaddr,port)。

sk.getsockname()

  返回套接字自己的地址。通常是一個元組(ipaddr,port)

sk.fileno()

  套接字的文件描述符

<3>實現(xiàn)多數(shù)據(jù)批量傳輸

?按照設(shè)定的值每次傳輸數(shù)據(jù)最多1024大小,如果要傳輸?shù)臄?shù)據(jù)大于1024則分批依次傳輸完成,為防止粘包問題在兩次傳輸之間添加一次確認消息確認即可

?

client端:

#_*_coding:utf-8_*_ #__author__:"shikai"import socket,osclient=socket.socket() client.connect(("localhost",6969)) while True:cmd=input("輸入指令:").strip()if len(cmd)==0:continue #入如果長度為0則繼續(xù)輸入client.send(cmd.encode("utf-8")) #發(fā)送的數(shù)據(jù) --->1cmd_res_size=client.recv(1024) #接受的數(shù)據(jù)長度 (要解碼)print("要接收數(shù)據(jù)大小:",cmd_res_size)client.send("準備接收數(shù)據(jù)請發(fā)送:".encode("utf-8"))received_size=0received_data=b""while received_size < int(cmd_res_size): #如果接受的長度小于文件本身長度就持續(xù)接受data=client.recv(1024) #接受數(shù)據(jù)received_size+=len(data)received_data+=dataelse:print("接收最終大小:",received_size)print(received_data.decode()) client.close()

server端:

#_*_coding:utf-8_*_ #__author__:"shikai"#ssh_服務(wù)器端 import socket,os server=socket.socket() server.bind(("localhost",6969)) server.listen()while True:coon,addr=server.accept()while True:data=coon.recv(1024) #接收來的數(shù)據(jù) ---->1接受命令if not data: #客戶端沒有數(shù)據(jù)發(fā)送就斷開print("客戶端已斷開")breakcmd_res=os.popen(data.decode()).read() #解碼發(fā)送來的命令,執(zhí)行結(jié)果也是字符串print("傳輸數(shù)據(jù)大小:",len(cmd_res.encode())) #長度編碼if len(cmd_res)==0: #如果client沒有輸入命令cmd_res="cmd has no output"coon.send(str(len(cmd_res.encode())).encode("utf-8")) #發(fā)送數(shù)據(jù)大小給客戶端(編碼成機器語言)client_ack=coon.recv(1024) #解決兩次發(fā)送之間存在的粘包問題print("準備發(fā)送數(shù)據(jù):",client_ack.decode())coon.send(cmd_res.encode("utf-8")) #發(fā)送的數(shù)據(jù)(編碼成機器識別的utf-8格式)print("send over...")server.close()

  

?<4>socket與文件傳輸、添加hashlib認證

hashlib產(chǎn)生md5值,認證傳輸?shù)奈募欠裎ㄒ?#xff0c;先產(chǎn)生文件md5值作為檢查標準,然后依次發(fā)送文件md5,最后做對比驗證??蛻舳?實現(xiàn)從服務(wù)器現(xiàn)在下載文件,先接收服務(wù)器端發(fā)送文件md5值,然后依次接收文件md5值在驗證文件下載是否正確。

?

#!_*_coding:utf-8_*_ #__author__:"shikai" #ftp 客戶端 (實現(xiàn)從服務(wù)器現(xiàn)在下載文件) import socket,hashlib client=socket.socket() client.connect(("localhost",6969)) while True:cmd=input("輸入指令:").strip()if len(cmd)==0:continue #入如果長度為0則繼續(xù)輸入if cmd.startswith("get"): #輸入get文件名(檢查是否以指定字符串開頭) client.send(cmd.encode())file_size=client.recv(1024) #接收文件大小file_total_size=int(file_size.decode())client.send(b"ready to recv file")received_size=0filename=cmd.split()[1] #文件名就是發(fā)來數(shù)據(jù)的第二個f=open(filename+".nwe","wb") #以二進制寫入m=hashlib.md5()while received_size<file_total_size:if file_total_size-received_size>1024: #要接收的不止一次size=1024else:size=file_total_size-received_sizeprint("the last recv:",size)data=client.recv(size) #接收文件received_size+=len(data)m.update(data) #分次調(diào)用接收md5值 f.write(data)else:md5_nwe=m.hexdigest()server_md5=client.recv(1024) #接收服務(wù)器發(fā)送的md5值print("傳輸完成",file_size,file_total_size)print("兩次md5:",md5_nwe,server_md5)f.close()client.close() client端: #_*_coding:utf-8_*_ #__author__:"shikai" #ftp_服務(wù)器端 (實現(xiàn)發(fā)送文件功能) import socket,os,hashlib server=socket.socket() server.bind(("localhost",6969)) server.listen()while True:coon,addr=server.accept()while True:print("等待新指令:")data=coon.recv(1024) #接收來的命令要求if not data: #客戶端沒有數(shù)據(jù)發(fā)送就斷開print("客戶端已斷開")breakcmd,filename=data.decode().split() #獲取文件名if os.path.isfile(filename): #判斷文件是否存在m = hashlib.md5()f=open(filename,"rb")filesize=os.stat(filename).st_size #獲取文件大小coon.send(str(filesize).encode()) #發(fā)送文件大小coon.recv(1024) #等待客戶端確認for line in f:m.update(line) #分次調(diào)用接收md5值 coon.send(line)#print("file md5:",m.hexdigest()) f.close()coon.send(m.hexdigest().encode()) #發(fā)送md5值確認print("send done.......")server.close() 服務(wù)器端:

?

?<5>socketserver多并發(fā)

SocketServer內(nèi)部使用 IO多路復(fù)用 以及 “多線程” 和 “多進程” ,從而實現(xiàn)并發(fā)處理多個客戶端請求的Socket服務(wù)端。即:每個客戶端請求連接到服務(wù)器時,Socket服務(wù)端都會在服務(wù)器是創(chuàng)建一個“線程”或者“進程” 專門負責(zé)處理當前客戶端的所有請求。

?

ThreadingTCPServer方法實現(xiàn)的Soket服務(wù)器內(nèi)部會為每個client創(chuàng)建一個 “線程”,該線程用來和客戶端進行交互。

#_*_coding:utf-8_*_ #__author__:"shikai"import socket client=socket.socket() #聲明socket類型,并生成socket連接對象 client.connect(("localhost",6969)) #連接服務(wù)器IP和端口 while True:cmd=input("輸入指令:").strip()client.send(cmd.encode()) #發(fā)送消息 data=client.recv(1024) #接收數(shù)據(jù)print("recv:",data)client.close() client端: #!_*_coding:utf-8_*_ #__author__:"shikai"import socketserver class MyTCPHandler(socketserver.BaseRequestHandler):def handle(self):while True:try:self.data=self.request.recv(1024).strip() #接收數(shù)據(jù)print("{} wrote:".format(self.client_address[0]))print(self.data)self.request.send(self.data.upper()) #將數(shù)據(jù)轉(zhuǎn)化為大寫發(fā)送except ConnectionResetError as e: #抓取連接異常print("err:",e)break if __name__=="__main__": #手動執(zhí)行程序HOST,PORT="localhost",6969#為每個client端創(chuàng)建一個進程或線程server=socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler) #ThreadingTCPServer 多并發(fā)擦操作server.serve_forever() socketserver

?

?<6>paramiko模塊

paramiko是用python語言寫的一個模塊,遵循SSH2協(xié)議,支持以加密和認證的方式,該模塊基于SSH用于連接遠程服務(wù)器并執(zhí)行相關(guān)操作

1:獲得密鑰對命令行輸入:ssh-keygen

?

安裝

pip install paramiko

  

SSHClient??連接遠程服務(wù)器并執(zhí)行基本命令

?

基于用戶名密碼連接:

#_*_coding:utf-8_*_ #__author__:"shikai"import paramiko ssh=paramiko.SSHClient() #實例化ssh 客戶端 #允許連接不再host 文件中的主機 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())#連接服務(wù)器 ssh.connect(hostname="localhost",port=22,username="shikai",password="123") #執(zhí)行命令 stdin,stdout,stderr=ssh.exec_command("df") #返回:標準輸入 輸出 錯誤命令三種結(jié)果 #獲取命令結(jié)果 res=stdout.read() ssh.close()

?

基于公鑰密鑰連接:

#無需密碼遠程連接主機(把公鑰給主機,自己保存私鑰)

#_*_coding:utf-8_*_ #__author__:"shikai" #無需密碼遠程連接主機(把公鑰給主機,自己保存私鑰) import paramiko private_key=paramiko.RSAKey.from_private_key_file("id_rsa") #私鑰儲存目錄ssh=paramiko.SSHClient() #允許連接不再know_host文件中的主機 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy) #連接主機 ssh.connect(hostname="localhost",port=22,username="shikai",pkey=private_key) #執(zhí)行命令 stdin,stdout,sterr=ssh.exec_command("df") #返回:標準輸入 輸出 錯誤命令三種結(jié)果 #獲取結(jié)果 res=stdout.read() #關(guān)閉連接 ssh.close()

  

?

SFTPClient

用于連接遠程服務(wù)器并執(zhí)行上傳下載

基于用戶名密碼上傳下載:

import paramikotransport = paramiko.Transport(('hostname',22)) transport.connect(username='shikai',password='123')sftp = paramiko.SFTPClient.from_transport(transport)# 將location.py 上傳至服務(wù)器 /tmp/test.py sftp.put('/tmp/location.py', '/tmp/test.py')# 將remove_path 下載到本地 local_path sftp.get('remove_path', 'local_path')transport.close()

基于公鑰密鑰上傳下載:

?

import paramikoprivate_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') #私鑰文件路徑transport = paramiko.Transport(('hostname', 22)) transport.connect(username='shikai', pkey=private_key )sftp = paramiko.SFTPClient.from_transport(transport)# 將location.py 上傳至服務(wù)器 /tmp/test.py sftp.put('/tmp/location.py', '/tmp/test.py')# 將remove_path 下載到本地 local_path sftp.get('remove_path', 'local_path')transport.close()

  

?

?

轉(zhuǎn)載于:https://www.cnblogs.com/shikaishikai/p/9574100.html

總結(jié)

以上是生活随笔為你收集整理的五 Python之socket网络编程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。