簡體   English   中英

python socket並行收發

[英]python socket parallel sending and receiving

我正在開發一個簡單的項目,該項目使用 pstuil 庫向客戶端發送“服務器”cpu 和 ram 使用情況,但我被卡住了。 簡而言之,我的問題是我無法驗證客戶端收到的數據。
我的服務器代碼:

# Import Section
import socket
import threading
import psutil
import time

# TCP Socket Connection for server
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("127.0.0.1", 6767))
server.listen()
client, address = server.accept()


# Functions
def cpu():
    while True:
        cpu_usage = str(psutil.cpu_percent(1))
        client.send(cpu_usage.encode("ascii"))


def ram():
    while True:
        time.sleep(1)
        ram_usage = str(psutil.virtual_memory()[2])
        client.send(ram_usage.encode("ascii"))


# Threads
t1 = threading.Thread(target=cpu).start()
t2 = threading.Thread(target=ram).start()

我的客戶代碼:

# Import Section
import socket
import threading
import time

# TCP Socket Connection for server
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.connect(("127.0.0.1", 6767))


# Functions
def cpu():
    while True:
        server.send("cpu".encode("ascii"))
        cpu_usage = server.recv(1024).decode("ascii")
        print(f"cpu usage is {cpu_usage}")
        time.sleep(1)


def ram():
    while True:
        server.send("ram".encode("ascii"))
        ram_usage = server.recv(1024).decode("ascii")
        print(f"ram usage is {ram_usage}")
        time.sleep(1)


# Threads
t1 = threading.Thread(target=cpu).start()
t2 = threading.Thread(target=ram).start()

我預期的 Output:

cpu usage is cpu_usage
ram usage is ram_usage

example: 
cpu usage is 0.3
ram usage is 14.7

真正的 output:

randomly
cpu usage is ram_usage
ram usage is cpu_usage

or

cpu usage is cpu_usage
ram usage is ram_usage

example:
cpu_usage is 14.7
ram usage is 0.3
cpu usage is 0.3
ram usage is 14.7

似乎他們沒有被排成一行。 一個答案是通過服務器發送所有數據,但我只想發送原始 cpu 或 ram 數據並在客戶端代碼中對它們進行排序。

感謝您提供代碼,我能夠輕松地在我的 VM 上重現該問題。

簡短答案:您將 RAM 和 CPU 數據包發送到同一個套接字,當您調用 server.recv() 時,您可以獲得 RAM 或 CPU 數據包,無論您用於調用 recv() 的 function 是什么。

更多信息:雖然 TCP 保證數據包排序,但是當為每個功能使用不同的線程時,它們可能會嚴重不同步,以至於在調用 ram( )(或反之亦然)在服務器或客戶端。 您甚至可以看到這種情況發生,因為屏幕打印不一致,有時會連續兩次打印 CPU 或 RAM。

有幾種方法可以解決這個問題。 通過為每個功能使用不同的套接字,您可以確保永遠不會混淆(參見下面的代碼)。 另一種選擇是僅在客戶端請求時在服務器端運行測量。 我不確定這是否是您要在客戶端代碼上執行的操作:

在 cpu() 中:

cpu_server.send("cpu".encode("ascii"))

在 ram() 中:

ram_server.send("ram".encode("ascii"))

我可以在 tcpdump 中看到這些數據包 go,但我認為它們沒有做任何事情,因為服務器沒有從套接字中獲取它們。

您的每次測量帶有插座的代碼(隨意使用/修改):

服務器.py:

# Import Section
import socket
import threading
import psutil
import time

# Functions
def cpu():
    # TCP Socket Connection for CPU server
    cpu_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    cpu_server.bind(("127.0.0.1", 6767))
    cpu_server.listen()
    cpu_client, cpu_address = cpu_server.accept()
    while True:
        cpu_usage = str(psutil.cpu_percent(1))
        cpu_client.send(cpu_usage.encode("ascii"))


def ram():
    # TCP Socket Connection for RAM server
    ram_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    ram_server.bind(("127.0.0.1", 6768))
    ram_server.listen()
    ram_client, ram_address = ram_server.accept()
    while True:
        time.sleep(1)
        ram_usage = str(psutil.virtual_memory()[2])
        ram_client.send(ram_usage.encode("ascii"))

# Threads
t1 = threading.Thread(target=cpu).start()
t2 = threading.Thread(target=ram).start()

客戶端.py:

# Import Section
import socket
import threading
import time

# Functions
def cpu():
    # TCP Socket Connection for CPU server
    cpu_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    cpu_server.connect(("127.0.0.1", 6767))
    while True:
        cpu_usage = cpu_server.recv(1024).decode("ascii")
        print(f"cpu usage is {cpu_usage}")
        time.sleep(1)

def ram():
    # TCP Socket Connection for RAM server
    ram_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    ram_server.connect(("127.0.0.1", 6768))
    while True:
        ram_usage = ram_server.recv(1024).decode("ascii")
        print(f"ram usage is {ram_usage}")
        time.sleep(1)

# Threads
t1 = threading.Thread(target=cpu).start()
t2 = threading.Thread(target=ram).start()

請注意 - 我不得不在線程內進行 TCP 連接,因為操作被阻塞並且響應時間太慢。 當我嘗試從主進程連接時,客戶端出現問題,因為當它在第二個套接字上調用 connect() 時,服務器端可能尚未在其第二個套接字上偵聽。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM