Python Basic - 遠端執行命令優化示例(迴圈接收直至接收完成)

Fei-Huang發表於2020-10-01

前言

遠端執行命令部落格示例中,示例並不完美,但是就程式碼而言,沒有最好的程式碼,只有更好的程式碼。但是在該示例中,有一個BUG可想而知,就是在客戶端的sk.revc()函式中,只指定了接收1024個位元組,那如果服務端傳送的資料超過了1024個位元組呢?此時資料會接收不完整,為了解決此問題,我們需要引入一些新的東西。

基本思路

  1. 先讓服務端計算一下要傳送資料的大小
  2. 將此大小的這個數值(int)傳送給客戶端,讓客戶端知道你需要接收多大的資料
  3. 客戶端根據這個大小來判斷需要迴圈幾次來接收服務端一次性傳送的資料。

示例程式碼

伺服器端程式碼

import socket
import subprocess
sk = socket.socket()
address = ("127.0.0.1",9200)
sk.bind(address)
sk.listen(3)
print("waiting.....")
connection,clientinfo = sk.accept()
print(connection)
print(clientinfo)


while True:
    try:
        print("waiting for message input.....")
        user_recv = connection.recv(1024)
    except ConnectionResetError as e:
        connection.close()
        print(e)
        print(clientinfo,"已經主動關閉了會話")
        connection, clientinfo = sk.accept()#因為上面對connection關閉了,所以這裡需要重新來一個connection等待連線
        continue
    if not user_recv:# 當使用者輸入exit的時候,服務端會接收到一個“空”的內容,所以判斷使用者終止了會話,所以我們接收一個新的連線。
        print("當前使用者已經退出會話。")
        connection.close()
        connection, clientinfo = sk.accept()
        print("新使用者建立了一個連線,客戶端資訊:",clientinfo)
        continue
    command = str(user_recv,"utf8")
    command_result = subprocess.Popen(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
    command_result_str = command_result.stdout.read()
    #計算出資料有多大
    result_length = len(command_result_str)
    print("傳送資料大小為:",result_length)



    try:
        connection.sendall(bytes(str(result_length),"gbk"))
        connection.sendall(command_result_str)
        print("執行結果已經傳送")
    except ConnectionResetError as e:
        connection.close()
        print(e)
        print(clientinfo,"已經主動關閉了會話")
        connection, clientinfo = sk.accept()#因為上面對connection關閉了,所以這裡需要重新來一個connection等待連線
        continue

connection.close()

客戶端程式碼

import socket

sk = socket.socket()
address = ("127.0.0.1",9200)
sk.connect(address)


while True:
    user_input = input(">>>")
    if user_input == "exit":
        print("exiting....")
        break
    if not user_input:
        print("輸入資料不允許為空,請重新輸入.")
        continue


    sk.send(bytes(user_input,"utf8"))

    #先接收服務端傳送過來的資料長度數值
    result_recv = int(str(sk.recv(1024),"utf8"))
    print(str(result_recv))

    # 新建一個bytes型別的空資料,用於儲存即將接收到的bytes的資料。而且每迴圈一次都要往後面累加資料
    data = bytes()
    while len(data) != result_recv:
        user_recv = sk.recv(1024)
        print("接收到%s資料。"%(len(user_recv)))
        data += user_recv
    else:
        print("總共接收到%s資料。"%(len(data)))
    print("接收資料完成")
    print(str(data,"gbk"))
sk.close()

執行結果展示

>>>ipconfig
1615
接收到1024資料。
接收到591資料。
總共接收到1615資料。
接收資料完成

Windows IP Configuration


Ethernet adapter Ethernet:

   Connection-specific DNS Suffix  . : cjfco.com.cn
   Link-local IPv6 Address . . . . . : fe80::2c4b:39e4:88c1:49dd%13
   Link-local IPv6 Address . . . . . : fe80::51b0:72cf:65:ad49%13
   IPv4 Address. . . . . . . . . . . : 192.168.255.52
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : ::

Ethernet adapter 乙太網:

   Connection-specific DNS Suffix  . : 
   Link-local IPv6 Address . . . . . : fe80::e5db:5993:684:a0c4%10
   IPv4 Address. . . . . . . . . . . : 192.168.1.3
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 192.168.1.1

Ethernet adapter loopback0:

   Connection-specific DNS Suffix  . : 
   Link-local IPv6 Address . . . . . : fe80::d9ba:7cc6:cae6:c7aa%14
   IPv4 Address. . . . . . . . . . . : 192.168.100.254
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 

Ethernet adapter VMware Network Adapter VMnet1:

   Connection-specific DNS Suffix  . : 
   Link-local IPv6 Address . . . . . : fe80::991:4897:10f8:18f3%8
   IPv4 Address. . . . . . . . . . . : 192.168.169.1
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 

Ethernet adapter VMware Network Adapter VMnet8:

   Connection-specific DNS Suffix  . : 
   Link-local IPv6 Address . . . . . : fe80::e9db:995e:e588:67ca%6
   IPv4 Address. . . . . . . . . . . : 192.168.128.1
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 

>>>ipconfig /all
5478
接收到1024資料。
接收到1024資料。
接收到1024資料。
接收到1024資料。
接收到1024資料。
接收到358資料。
總共接收到5478資料。
接收資料完成

Windows IP Configuration

   Host Name . . . . . . . . . . . . : DESKTOP-JT18FSK
   Primary Dns Suffix  . . . . . . . : 
   Node Type . . . . . . . . . . . . : Hybrid
   IP Routing Enabled. . . . . . . . : No
   WINS Proxy Enabled. . . . . . . . : No
   DNS Suffix Search List. . . . . . : cjfco.com.cn

Ethernet adapter Ethernet:

   Connection-specific DNS Suffix  . : cjfco.com.cn
   Description . . . . . . . . . . . : Cisco AnyConnect Secure Mobility Client Virtual Miniport Adapter for Windows x64
   Physical Address. . . . . . . . . : 00-05-9A-3C-7A-00
   DHCP Enabled. . . . . . . . . . . : No
   Autoconfiguration Enabled . . . . : Yes
   Link-local IPv6 Address . . . . . : fe80::2c4b:39e4:88c1:49dd%13(Preferred) 
   Link-local IPv6 Address . . . . . : fe80::51b0:72cf:65:ad49%13(Preferred) 
   IPv4 Address. . . . . . . . . . . : 192.168.255.52(Preferred) 
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : ::
   DHCPv6 IAID . . . . . . . . . . . : 218105242
   DHCPv6 Client DUID. . . . . . . . : 00-01-00-01-24-E9-11-5A-00-E0-1B-68-01-75
   DNS Servers . . . . . . . . . . . : 10.243.1.1
                                       10.243.1.2
   NetBIOS over Tcpip. . . . . . . . : Enabled

Ethernet adapter 乙太網:

   Connection-specific DNS Suffix  . : 
   Description . . . . . . . . . . . : Realtek PCIe GbE Family Controller
   Physical Address. . . . . . . . . : 00-E0-1B-68-01-75
   DHCP Enabled. . . . . . . . . . . : Yes
   Autoconfiguration Enabled . . . . : Yes
   Link-local IPv6 Address . . . . . : fe80::e5db:5993:684:a0c4%10(Preferred) 
   IPv4 Address. . . . . . . . . . . : 192.168.1.3(Preferred) 
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Lease Obtained. . . . . . . . . . : 202010117:17:17
   Lease Expires . . . . . . . . . . : 202010217:17:06
   Default Gateway . . . . . . . . . : 192.168.1.1
   DHCP Server . . . . . . . . . . . : 192.168.1.1
   DHCPv6 IAID . . . . . . . . . . . : 100720667
   DHCPv6 Client DUID. . . . . . . . : 00-01-00-01-24-E9-11-5A-00-E0-1B-68-01-75
   DNS Servers . . . . . . . . . . . : fe80::1%10
                                       192.168.1.1
                                       fe80::1%10
   NetBIOS over Tcpip. . . . . . . . : Enabled

Ethernet adapter loopback0:

   Connection-specific DNS Suffix  . : 
   Description . . . . . . . . . . . : Microsoft KM-TEST Loopback Adapter
   Physical Address. . . . . . . . . : 02-00-4C-4F-4F-50
   DHCP Enabled. . . . . . . . . . . : No
   Autoconfiguration Enabled . . . . : Yes
   Link-local IPv6 Address . . . . . : fe80::d9ba:7cc6:cae6:c7aa%14(Preferred) 
   IPv4 Address. . . . . . . . . . . : 192.168.100.254(Preferred) 
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 
   DHCPv6 IAID . . . . . . . . . . . : 503447628
   DHCPv6 Client DUID. . . . . . . . : 00-01-00-01-24-E9-11-5A-00-E0-1B-68-01-75
   DNS Servers . . . . . . . . . . . : fec0:0:0:ffff::1%1
                                       fec0:0:0:ffff::2%1
                                       fec0:0:0:ffff::3%1
   NetBIOS over Tcpip. . . . . . . . : Enabled

Ethernet adapter VMware Network Adapter VMnet1:

   Connection-specific DNS Suffix  . : 
   Description . . . . . . . . . . . : VMware Virtual Ethernet Adapter for VMnet1
   Physical Address. . . . . . . . . : 00-50-56-C0-00-01
   DHCP Enabled. . . . . . . . . . . : Yes
   Autoconfiguration Enabled . . . . : Yes
   Link-local IPv6 Address . . . . . : fe80::991:4897:10f8:18f3%8(Preferred) 
   IPv4 Address. . . . . . . . . . . : 192.168.169.1(Preferred) 
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Lease Obtained. . . . . . . . . . : 202010117:17:09
   Lease Expires . . . . . . . . . . : 202010119:32:02
   Default Gateway . . . . . . . . . : 
   DHCP Server . . . . . . . . . . . : 192.168.169.254
   DHCPv6 IAID . . . . . . . . . . . : 234901590
   DHCPv6 Client DUID. . . . . . . . : 00-01-00-01-24-E9-11-5A-00-E0-1B-68-01-75
   DNS Servers . . . . . . . . . . . : fec0:0:0:ffff::1%1
                                       fec0:0:0:ffff::2%1
                                       fec0:0:0:ffff::3%1
   NetBIOS over Tcpip. . . . . . . . : Enabled

Ethernet adapter VMware Network Adapter VMnet8:

   Connection-specific DNS Suffix  . : 
   Description . . . . . . . . . . . : VMware Virtual Ethernet Adapter for VMnet8
   Physical Address. . . . . . . . . : 00-50-56-C0-00-08
   DHCP Enabled. . . . . . . . . . . : Yes
   Autoconfiguration Enabled . . . . : Yes
   Link-local IPv6 Address . . . . . : fe80::e9db:995e:e588:67ca%6(Preferred) 
   IPv4 Address. . . . . . . . . . . : 192.168.128.1(Preferred) 
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Lease Obtained. . . . . . . . . . : 202010117:17:09
   Lease Expires . . . . . . . . . . : 202010119:32:02
   Default Gateway . . . . . . . . . : 
   DHCP Server . . . . . . . . . . . : 192.168.128.254
   DHCPv6 IAID . . . . . . . . . . . : 251678806
   DHCPv6 Client DUID. . . . . . . . : 00-01-00-01-24-E9-11-5A-00-E0-1B-68-01-75
   DNS Servers . . . . . . . . . . . : fec0:0:0:ffff::1%1
                                       fec0:0:0:ffff::2%1
                                       fec0:0:0:ffff::3%1
   Primary WINS Server . . . . . . . : 192.168.128.2
   NetBIOS over Tcpip. . . . . . . . : Enabled

>>>

相關文章