五 Python之socket網絡編程

<1>socket概念

socket通常也稱作"套接字",用于描述IP地址和端口,是一個通信鏈的句柄,應用程序通常通過"套接字"向網絡發出請求或者應答網絡請求。ocket本質上就是在2臺網絡互通的電腦之間,架設一個通道,兩臺電腦通過這個通道來實現數據的互相傳遞。

?

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

?

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

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

client端:

#_*_coding:utf-8_*_
#__author__:"shikai"import socket
client=socket.socket()                     #聲明socket類型,并生成socket連接對象
client.connect(("localhost",1234))      #連接服務器IP和端口
while True:cmd=input("輸入指令:").strip()client.send(cmd.encode())            #發送消息data=client.recv(1024)                #接收數據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()                       #監聽
while True:print("開始等電話了")conn,addr=server.accept()          # 阻塞狀態  等待連接 (accept回返回兩個數據conn和addr)#coon就是客服端連接之后,服務器為其生成的一個連接實例print(conn,addr)while True:print("接電話了")data=conn.recv(1024)             #接收數據print("recv:",data)conn.send(data.upper())         #處理并發送返回  (把小寫變成大寫)server.close()

sk.bind(address)

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

sk.listen(backlog)

  開始監聽傳入連接。backlog指定在拒絕連接之前,可以掛起的最大連接數量。

? ? ? backlog等于5,表示內核已經接到了連接請求,但服務器還沒有調用accept進行處理的連接個數最大為5
? ? ? 這個值不能無限大,因為要在內核中維護連接隊列

sk.setblocking(bool)

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

sk.accept()

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

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

sk.connect(address)

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

sk.connect_ex(address)

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

sk.close()

  關閉套接字

sk.recv(bufsize[,flag])

  接受套接字的數據。數據以字符串形式返回,bufsize指定最多可以接收的數量。flag提供有關消息的其他信息,通常可以忽略。

sk.recvfrom(bufsize[.flag])

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

sk.send(string[,flag])

  將string中的數據發送到連接的套接字。返回值是要發送的字節數量,該數量可能小于string的字節大小。即:可能未將指定內容全部發送。

sk.sendall(string[,flag])

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

? ? ? 內部通過遞歸調用send,將所有內容發送出去。

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

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

sk.settimeout(timeout)

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

sk.getpeername()

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

sk.getsockname()

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

sk.fileno()

  套接字的文件描述符

<3>實現多數據批量傳輸

?按照設定的值每次傳輸數據最多1024大小,如果要傳輸的數據大于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則繼續輸入client.send(cmd.encode("utf-8"))             #發送的數據      --->1cmd_res_size=client.recv(1024)                #接受的數據長度 (要解碼)print("要接收數據大小:",cmd_res_size)client.send("準備接收數據請發送:".encode("utf-8"))received_size=0received_data=b""while received_size < int(cmd_res_size):       #如果接受的長度小于文件本身長度就持續接受data=client.recv(1024)             #接受數據received_size+=len(data)received_data+=dataelse:print("接收最終大小:",received_size)print(received_data.decode())
client.close()

server端:

#_*_coding:utf-8_*_
#__author__:"shikai"#ssh_服務器端
import socket,os
server=socket.socket()
server.bind(("localhost",6969))
server.listen()while True:coon,addr=server.accept()while True:data=coon.recv(1024)         #接收來的數據     ---->1接受命令if not data:       #客戶端沒有數據發送就斷開print("客戶端已斷開")breakcmd_res=os.popen(data.decode()).read()    #解碼發送來的命令,執行結果也是字符串print("傳輸數據大小:",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"))        #發送數據大小給客戶端(編碼成機器語言)client_ack=coon.recv(1024)                        #解決兩次發送之間存在的粘包問題print("準備發送數據:",client_ack.decode())coon.send(cmd_res.encode("utf-8"))           #發送的數據(編碼成機器識別的utf-8格式)print("send over...")server.close()

  

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

hashlib產生md5值,認證傳輸的文件是否唯一,先產生文件md5值作為檢查標準,然后依次發送文件md5,最后做對比驗證。客戶端 實現從服務器現在下載文件,先接收服務器端發送文件md5值,然后依次接收文件md5值在驗證文件下載是否正確。

?

#!_*_coding:utf-8_*_
#__author__:"shikai"
#ftp 客戶端 (實現從服務器現在下載文件)
import socket,hashlib
client=socket.socket()
client.connect(("localhost",6969))
while True:cmd=input("輸入指令:").strip()if len(cmd)==0:continue                    #入如果長度為0則繼續輸入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=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)                    #分次調用接收md5值
            f.write(data)else:md5_nwe=m.hexdigest()server_md5=client.recv(1024)             #接收服務器發送的md5值print("傳輸完成",file_size,file_total_size)print("兩次md5:",md5_nwe,server_md5)f.close()client.close()
client端:
#_*_coding:utf-8_*_
#__author__:"shikai"
#ftp_服務器端   (實現發送文件功能)
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:       #客戶端沒有數據發送就斷開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())        #發送文件大小coon.recv(1024)               #等待客戶端確認for line in f:m.update(line)            #分次調用接收md5值
                coon.send(line)#print("file md5:",m.hexdigest())
            f.close()coon.send(m.hexdigest().encode())       #發送md5值確認print("send done.......")server.close()
服務器端:

?

?<5>socketserver多并發

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

?

ThreadingTCPServer方法實現的Soket服務器內部會為每個client創建一個 “線程”,該線程用來和客戶端進行交互。

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

?

?<6>paramiko模塊

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

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

?

安裝

pip install paramiko

  

SSHClient??連接遠程服務器并執行基本命令

?

基于用戶名密碼連接:

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

  

?

SFTPClient

用于連接遠程服務器并執行上傳下載

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

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

  

?

?

轉載于:https://www.cnblogs.com/shikaishikai/p/9574100.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/397013.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/397013.shtml
英文地址,請注明出處:http://en.pswp.cn/news/397013.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

致敬2016,擁抱2017

2016年5月10號加入現在的團隊&#xff0c;到今天2016年12月31號&#xff0c;已經過去了接近8個月。這整個期間&#xff0c;我們團隊都只有我一個前端工程師&#xff0c;我從剛開始的忐忑不安、壓力極大&#xff0c;到現在基本上手&#xff0c;我們團隊做的項目雖然不大&#xf…

你如何在java中獲取線程堆_如何在Windows上獲取未在控制臺中運行的Java進程的線程和堆轉儲...

問題我有一個Java應用程序&#xff0c;我從控制臺運行&#xff0c;然后控制臺執行另一個Java進程。我想獲得該子進程的線程/堆轉儲。在Unix上&#xff0c;我可以做akill -3 但是在Windows AFAIK上獲取線程轉儲的唯一方法是在控制臺中使用Ctrl-Break。但這只會讓我轉移父進程&am…

html ie亂碼_Java 0基礎入門(初識Html)

在學習Java之前&#xff0c;我們需要了解一定的前端知識。畢竟頁面才是用戶真正看到的&#xff0c;而且也是體現Java后端邏輯結果的地方。學習HTML后&#xff0c;能夠制作界面美觀大方的靜態網站(更復雜的功能需要JavaScript腳本一起來實現)。HTML制作的網頁。所需要的Html開發…

常用自動化框架簡單的分析與介紹

目前常用的可用于APP自動化測試的框架有以下幾個&#xff1a; 1、Monkey是Android SDK自帶的測試工具&#xff0c;在測試過程中會向系統發送偽隨機的用戶事件流&#xff0c;如按鍵輸入、觸摸屏輸入、手勢輸入等)&#xff0c;實現對正在開發的應用程序進行壓力測試&#xff0c;也…

linux一步一腳印---more、less、head、tail

一、more 文件內容或輸出查看命令more 是我們最常用的工具之一&#xff0c;最常用的就是顯示輸出的內容&#xff0c;然后根據窗口的大小進行分頁顯示&#xff0c;然后還能提示文件的百分比&#xff1b; [rootlocalhost ~]# more /etc/profile 1、more 的語法、參數和命令&#…

單片機檢測stc沒反應_我為什么不用STC單片機

寫在2019.10.27這屬于自己打自己臉&#xff0c;不過&#xff0c;我突然想試試 STC15W108.理由可能有點操蛋&#xff0c;因為STM8S沒有 DFN8這樣 3x3的封裝&#xff0c;而PIC的仿真器太貴。我最后感興趣的一個STC型號是 STC15F的8腳系列&#xff0c;那是在2010年&#xff0c;然而…

commons-pool

commons-pool組件是使用對象池時都要用到的。他的作用主要是管理對象池&#xff0c; 當我們要用這個組件時&#xff08;比如redis要用到時&#xff09;&#xff0c;只需要實現它的部分接口&#xff0c;比如PooledObjectFactory接口&#xff0c;實現它的創建對象&#xff0c;銷毀…

JAVA中CyclLink怎么用_Java多線程基本使用一

1 多線程--初步【1進程比如&#xff1a;QQ、迅雷、360、飛秋...2線程的概念3線程的意義&#xff1a;4.Java程序的運行原理代碼是運行在線程中的&#xff0c;如果一個進程沒有線程&#xff0c;那么進程就結束了&#xff0c;也就是說一個進程至少要有一個線程當開啟一個Java…

指針分析

int *a; int b 4; a &b; //a:b的地址 //*a 取b地址的值&#xff0c;為4 //&a為指針變量的地址 //*(&a)為指針變量儲存的地址 即為a int **b &a; //b為指針變量a的地址 //*b為指針變量a所儲存的地址 //改變*b(指針變量所儲存的地址)即改變了*b的值轉載于:http…

live server插件怎么用_分享幾個我日常使用的VS Code插件

在這篇文章中&#xff0c;我想介紹一下自己日常使用中最喜歡的Visual Studio Code擴展。大多數時候&#xff0c;我用VS Code編寫的是JavaScript應用程序(標準JavaScript、React、Angular、NodeJS……各式各樣)。Bracket Pair Colorizer 2這個擴展很不錯&#xff0c;可以幫助我搞…

Xtrabackup數據全備份與快速搭建從服務器

Percona Xtrabackup可以說是一個完美的數據備份工具。特別是當數據庫的容量達到了一定數量級的時候且存在單表達到幾十G的數據量&#xff0c; 很難容忍一些邏輯備份的漫長時間。如單個數據庫約200G&#xff0c;單表最大為120G&#xff0c;mysqldump邏輯備份的時間長達20多小時。…

簡單的java方法_Java簡單實用方法一

整理以前的筆記&#xff0c;在學習Java時候,經常會用到一些方法。雖然簡單但是經常使用。因此做成筆記&#xff0c;方便以后查閱這篇博文先說明構造和使用這些方法。1&#xff0c;判斷String類型數據是否為空String類型的數據為空&#xff0c;主要為等于null或”“那么只要判斷…

Android應用程序開發

第一章 Android應用初體驗 1.1應用基礎 activity是Android SDK中Activity類的一個具體實例&#xff0c;負責管理用戶與信息屏的交互。 應用的功能是通過編寫一個個Activity子類來實現的。 布局定義了一系列用戶界面對象以及它們顯示在屏幕上的位置。組成布局的定義保存在XML文件…

phonegap

phonegap 框架詳解 轉自&#xff1a;http://www.cnblogs.com/hubcarl/p/4216844.html首先, 來看一下phonegap 初始化流程以及Native 與 JS 交互流程圖。 說明&#xff1a;socket server模式下, phonegap.js 源碼實現的采用1 毫秒執行一次XHR請求, 當Native JS 隊列里面有JS語…

j2ee核心模式_Operator和Sidecar正在成為軟件交付新模式

現如今的開發人員希望可以開發出具備彈性和可擴展的分布式系統。該系統受益于軟件復用和開源模型創新&#xff0c;針對安全性問題能夠輕易完成補丁更新并進行低風險的升級。該系統不可能通過帶有各種嵌入式語言庫的應用程序框架來實現。最近&#xff0c;一篇關于“多運行時微服…

微信JS-SDK選擇相冊或拍照并上傳PHP實現

理解&#xff1a;微信上傳接口是拍照&#xff0c;或者選擇本地照片&#xff0c;上傳到微信的服務器&#xff0c;獲取到一個id&#xff0c;通過token與這個id獲取到圖片&#xff0c;保存到服務器即可。 效果 通過微信js接口&#xff0c;調用底層程序。 需要引入js文件&#xff0…

JMS-ActiveMQ學習-3 ActiveMQ與Spring集成

Spring下開發消息的發送和接收程序 點對點模式 一、創建生產者項目 1.創建maven項目 2.添加spring-jms、jms規范、activemq依賴 <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms&…

看libevent所遇到的英語生詞

libevent – an event notification library The libevent API &#xff08;libevent應用程序&#xff09;provides a mechanism&#xff08;機制&#xff09; to execute&#xff08;執行&#xff09; a callback function&#xff08;回調函數&#xff09; when a specific&a…

java中迭代器要導包嗎_java 中迭代器的使用方法詳解

java 中迭代器的使用方法詳解前言&#xff1a;迭代器模式將一個集合給封裝起來&#xff0c;主要是為用戶提供了一種遍歷其內部元素的方式。迭代器模式有兩個優點&#xff1a;①提供給用戶一個遍歷的方式&#xff0c;而沒有暴露其內部實現細節&#xff1b;②把元素之間游走的責任…