先來了解一下緩衝區:程序員
每一個 socket 被建立後,都會分配兩個緩衝區,輸入緩衝區和輸出緩衝區。
write()/send() 並不當即向網絡中傳輸數據,而是先將數據寫入緩衝區中,再由TCP協議將數據從緩衝區發送到目標機器。一旦將數據寫入到緩衝區,函數就能夠成功返回,無論它們有沒有到達目標機器,也無論它們什麼時候被髮送到網絡,這些都是TCP協議負責的事情。 TCP協議獨立於 write()/send() 函數,數據有可能剛被寫入緩衝區就發送到網絡,也可能在緩衝區中不斷積壓,屢次寫入的數據被一次性發送到網絡,這取決於當時的網絡狀況、當前線程是否空閒等諸多因素,不禁程序員控制。 read()/recv() 函數也是如此,也從輸入緩衝區中讀取數據,而不是直接從網絡中讀取。
這些I/O緩衝區特性可整理以下: 1.I/O緩衝區在每一個TCP套接字中單獨存在; 2.I/O緩衝區在建立套接字時自動生成; 3.即便關閉套接字也會繼續傳送輸出緩衝區中遺留的數據; 4.關閉套接字將丟失輸入緩衝區中的數據。 輸入輸出緩衝區的默認大小通常都是 8K,能夠經過 getsockopt() 函數獲取: 1.unsigned optVal; 2.int optLen = sizeof(int); 3.getsockopt(servSock, SOL_SOCKET, SO_SNDBUF,(char*)&optVal, &optLen); 4.printf("Buffer length: %d\n", optVal);
關於黏包:shell
MTU是Maximum Transmission Unit的縮寫。意思是網絡上傳送的最大數據包。MTU的單位是字節。 大部分網絡設備的MTU都是1500個字節,也就是1500B。若是本機一次須要發送的數據比網關的MTU大,大的數據包就會被拆開來傳送,這樣會產生不少數據包碎片,增長丟包率,下降網絡速度
模擬一個黏包現象:網絡
先學一個subprocess模塊。socket
import subprocess cmd = input('請輸入指令>>>') res = subprocess.Popen( cmd, #字符串指令:'dir','ipconfig',等等 shell=True, #使用shell,就至關於使用cmd窗口 stderr=subprocess.PIPE, #標準錯誤輸出,凡是輸入錯誤指令,錯誤指令輸出的報錯信息就會被它拿到 stdout=subprocess.PIPE, #標準輸出,正確指令的輸出結果被它拿到 ) print(res.stdout.read().decode('gbk')) print(res.stderr.read().decode('gbk'))