为什么Python客户端socket收到回复但在某些线程中仍然抛出异常?

问题描述 投票:0回答:1

这是我的Python代码。它是一个 pinger 客户端。它会向服务器发送一条消息,并期望在 1 秒内收到大写字母的回复。

from socket import *
import threading
import time


def ping_thread(num, clientSocket):
    try:
        clientSocket.settimeout(1)
        t1 = time.perf_counter()
        message = "Ping " + str(num) + " " + str(time.time())
        clientSocket.sendto(message.encode(), (serverName, serverPort))
        modifiedMessage, serverAddress = clientSocket.recvfrom(2048)
        t2 = time.perf_counter()
        lag = t2 - t1
        print(f"{modifiedMessage.decode()}: {lag:.8f}s")
    except TimeoutError:
        print(f"ping {num} time out!")


if __name__ == "__main__":
    threads = []
    clientSocket = socket(AF_INET, SOCK_DGRAM)
    serverName = "localhost"
    serverPort = 12000
    for i in range(1, 11):
        t = threading.Thread(target=ping_thread, args=(i, clientSocket))
        threads.append(t)
        t.start()

    for t in threads:
        t.join()

    clientSocket.close()

这是运行代码的结果。

PING 2 1710845145.1677558: 0.00191080s
PING 5 1710845145.169752: 0.00126800sPING 6 1710845145.169752: 0.00098610s

PING 1 1710845145.1658478: 0.00588400s
PING 3 1710845145.1677558: 0.00067630s
PING 8 1710845145.1719148: 0.00477900s
PING 10 1710845145.172912: 0.00083350s
ping 10 time out!
ping 4 time out!
ping 2 time out!

我想知道为什么有些线程(如上面的 Ping 2)收到回复但仍然抛出超时异常。 非常感谢!

240320 这是服务器代码。它来自计算机网络:自上而下的方法

中的lab2
# We will need the following module to generate randomized lost packets
import random
from socket import *

# Create a UDP socket
# Notice the use of SOCK_DGRAM for UDP packets
serverSocket = socket(AF_INET, SOCK_DGRAM)
# Assign IP address and port number to socket
serverSocket.bind(('', 12000))

while True:
    # Generate random number in the range of 0 to 10
    rand = random.randint(0, 10)
    # Receive the client packet along with the address it is coming from
    message, address = serverSocket.recvfrom(1024)
    # Capitalize the message from the client
    message = message.upper()
    # If rand is less than 4, we consider the packet lost and do not respond
    if rand < 4:
        continue
    # Otherwise, the server responds
    serverSocket.sendto(message, address)
python sockets udp timeout python-multithreading
1个回答
0
投票

您的服务器代码显示您随机忽略了大约 40% 的消息。由于所有 10 条消息使用同一个套接字,因此返回的 ~6 条消息可以由 10 个线程中的任何一个处理。

如果更改服务器代码以添加打印语句:

if rand < 4:
    print('ignored', message)
    continue

然后你会发现〜4条消息被忽略,但〜6个线程将以混合顺序获得响应。然后〜4个线程将因未接收消息而超时。

为了确保正确的线程获得正确的响应,请为每个线程使用单独的套接字:

def ping_thread(num):  # don't pass common socket
    try:
        clientSocket = socket(AF_INET, SOCK_DGRAM) # unique socket for thread
        clientSocket.settimeout(1)
        t1 = time.perf_counter()
        message = "Ping " + str(num) + " " + str(time.time())
        clientSocket.sendto(message.encode(), (serverName, serverPort))
        modifiedMessage, serverAddress = clientSocket.recvfrom(2048)
        t2 = time.perf_counter()
        lag = t2 - t1
        print(f"{modifiedMessage.decode()}: {lag:.8f}s")
    except TimeoutError:
        print(f"ping {num} time out!")


with socket(AF_INET, SOCK_DGRAM) as clientSocket:
    serverName = "localhost"
    serverPort = 12000

    # Create threads passing only the thread number.
    threads = [threading.Thread(target=ping_thread, args=(i,)) for i in range(10)]

    for t in threads:
        t.start()

    for t in threads:
        t.join()

输出。在本例中,3 个响应被忽略 (2,3,8),这些是超时的响应。

ignored b'PING 3 1710957710.7031364'
PING 0 1710957710.7031364: 0.00558820s
PING 6 1710957710.7031364: 0.00411860s
PING 4 1710957710.7031364: 0.00456480s
PING 1 1710957710.7031364: 0.00579830s
PING 5 1710957710.7031364: 0.00471390s
ignored b'PING 8 1710957710.7031364'
PING 7 1710957710.7031364: 0.00405850s
ignored b'PING 2 1710957710.7031364'
PING 9 1710957710.7031364: 0.00469280s
ping 3 time out!
ping 8 time out!
ping 2 time out!
© www.soinside.com 2019 - 2024. All rights reserved.