Python學習記錄之----網絡通訊(二)

 

網絡通訊   sockethtml

這一節太難了,仍是看TA的吧linux

http://www.cnblogs.com/alex3714/articles/5830365.htmlshell

 

  1. 不能執行top等相似的 會持續輸出的命令,這是由於,服務器端在收到客戶端指令後,會一次性經過os.popen執行,並獲得結果後返回給客戶,但top這樣的命令用os.popen執行你會發現永遠都不會結束,因此客戶端也永遠拿不到返回。(真正的ssh是經過select 異步等模塊實現的,咱們之後會涉及)
  2. 不能執行像cd這種沒有返回的指令, 由於客戶端每發送一條指令,就會經過client.recv(1024)等待接收服務器端的返回結果,可是cd命令沒有結果 ,服務器端調用conn.send(data)時是不會發送數據給客戶端的。 因此客戶端就會一直等着,等到天荒地老,結果就卡死了。解決的辦法是,在服務器端判斷命令的執行返回結果的長度,若是結果爲空,就本身加個結果返回給客戶端,如寫上"cmd exec success, has no output."
  3. 若是執行的命令返回結果的數據量比較大,會發現,結果返回不全,在客戶端上再執行一條命令,結果返回的仍是上一條命令的後半段的執行結果,這是爲何呢?這是由於,咱們的客戶寫client.recv(1024), 即客戶端一次最多隻接收1024個字節,若是服務器端返回的數據是2000字節,那有至少9百多字節是客戶端第一次接收不了的,那怎麼辦呢,服務器端此時不能把數據直接扔了呀,so它會暫時存在服務器的io發送緩衝區裏,等客戶端下次再接收數據的時候再發送給客戶端。 這就是爲何客戶端執行第2條命令時,卻接收到了第一條命令的結果的緣由。 這時有同窗說了, 那我直接在客戶端把client.recv(1024)改大一點不就行了麼, 改爲一次接收個100mb,哈哈,這是不行的,由於socket每次接收和發送都有最大數據量限制的,畢竟網絡帶寬也是有限的呀,不能一次發太多,發送的數據最大量的限制 就是緩衝區能緩存的數據的最大量,這個緩衝區的最大值在不一樣的系統上是不同的, 我實在查不到一個具體的數字,但測試的結果是,在linux上最大一次可接收10mb左右的數據,不過官方的建議是不超過8k,也就是8192,而且數據要能夠被2整除,不要問爲何 。anyway , 若是一次只能接收最多不超過8192的數據 ,那服務端返回的數據超過了這個數字怎麼辦呢?好比讓服務器端打開一個5mb的文件並返回,客戶端怎麼才能完整的接受到呢?那就只能循環收取啦。 

 

在開始解決上面問題3以前,咱們要考慮,客戶端要循環接收服務器端的大量數據返回直到一條命令的結果所有返回爲止, 但問題是客戶端知道服務器端返回的數據有多大麼?答案是不知道,那既然不知道服務器的要返回多大的數據,那客戶端怎麼知道要循環接收多少次呢?答案是不知道,擦,那咋辦? 總不能靠猜吧?呵呵。。。 固然不能,那隻能讓服務器在發送數據以前主動告訴客戶端,要發送多少數據給客戶端,而後再開始發送數據,yes, 機智如我,搞起。緩存

先簡單測試接收數據量大小服務器

 

 1 import socket
 2 import os,subprocess
 3 
 4 
 5 server = socket.socket() #得到socket實例
 6 server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
 7 
 8 server.bind(("localhost",9998)) #綁定ip port
 9 server.listen()  #開始監聽
10 
11 while True: #第一層loop
12     print("等待客戶端的鏈接...")
13     conn,addr = server.accept() #接受並創建與客戶端的鏈接,程序在此處開始阻塞,只到有客戶端鏈接進來...
14     print("新鏈接:",addr )
15     while True:
16 
17         data = conn.recv(1024)
18         if not data:
19             print("客戶端斷開了...")
20             break #這裏斷開就會再次回到第一次外層的loop
21         print("收到命令:",data)
22         #res = os.popen(data.decode()).read() #py3 裏socket發送的只有bytes,os.popen又只能接受str,因此要decode一下
23         res = subprocess.Popen(data,shell=True,stdout=subprocess.PIPE).stdout.read() #跟上面那條命令的效果是同樣的
24         if len(res) == 0:
25             res = "cmd exec success,has not output!"
26         conn.send(str(len(res)).endcode("utf-8")) #發送數據以前,先告訴客戶端要發多少數據給它
27         conn.sendall(res.encode("utf-8")) #發送端也有最大數據量限制,因此這裏用sendall,至關於重複循環調用conn.send,直至數據發送完畢
28 
29 server.close()

 

 

import socket

client = socket.socket()

client.connect(("localhost",9998))

while True:
    msg = input(">>:").strip()
    if len(msg) == 0:continue
    client.send( msg.encode("utf-8") )

    res_return_size  = client.recv(1024) #接收這條命令執行結果的大小
    print("getting cmd result , ", res_return_size)
    total_rece_size = int(res_return_size)
    print(total_rece_size)

    #print(data.decode()) #命令執行結果

client.close()
相關文章
相關標籤/搜索