gpt4 book ai didi

python - 如果 TCP 通信中丢失数据包,如何将客户端重新连接到服务器?

转载 作者:行者123 更新时间:2023-12-01 00:19:07 25 4
gpt4 key购买 nike

我正在使用两台不同的计算机(两个不同的 IP)在服务器和客户端之间创建通信,但是当我在将数据包发送到服务器的过程中丢失数据包时,我的客户端无法重新连接到服务器,因此它停止发送数据包。

我尝试使用另一个 sock.connect(server_address) 但即使这样它也不起作用。

这是我的代码(来自 Stack Overflow 上一位乐于助人的程序员的结构提示):

import socket
import threading
import time

class Server(threading.Thread):

def run(self) -> None:
MY_IP = "10.0.0.113" # Other computer running this class
PORT_NUMBER = 13000


# socket TCP/IP
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)


server_address = (MY_IP, PORT_NUMBER)
print('Server starting up on {} port {}'.format(*server_address))
sock.bind(server_address)

sock.listen(1)

while True:

print('Waiting a connection')
connection, client_address = sock.accept()
try:
print('Connection from ', client_address)

while True:
data = connection.recv(16)
#print('received {!r}'.format(data))
if data:
#print('sending data back to the client')
connection.sendall(data)
else:
print('no data came from ', client_address)
break

finally:
connection.close()

class Client(threading.Thread):

def run(self) -> None:
#MY_IP = "10.0.0.112" won't be used because it will send to the server IP.
OTHER_IP = "10.0.0.113"
PORT_NUMBER = 13000

g_windowTime = 0

# socket TCP/IP
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server_address = (OTHER_IP, PORT_NUMBER)
sock.connect(server_address)

def execute():
global g_windowTime
g_windowTime = time.time()
sizeWindow = 1
id_packet = "1"
packets_resend = []

while True:
packets_sent = []

# Send data
sizeWindow, packets_sent, id_packet = send_packets(sizeWindow, packets_sent, packets_resend, id_packet)
print(f"Send packet returned: {sizeWindow}")

# Waits for the amount
amount_received = 0
amount_expected = len(packets_sent)

while amount_received < amount_expected:
try:
sock.settimeout(5.0)
data = sock.recv(16)
amount_received += len(data)
except:
print("The packet needs to be resend")
print(f"execute: {sizeWindow} -> {sizeWindow*2}")
sizeWindow = sizeWindow * 2
currentTime = (time.time() - g_windowTime) * 1000
print(f'{str(round(currentTime, 2)).replace(".", ",")}; {int(sizeWindow)}')
if currentTime > 10000:
exit()


def send_packets(sizeWindow, packets_sent, packets_resend, id_packet):
global g_windowTime
i = 0
j = 0
timer = 0

while i < sizeWindow:

if packets_resend == []:
packet = id_packet.encode('utf-8')
id_packet = str(int(id_packet) + 1)
elif packets_resend != []:
packet = packets_resend.pop(0)

if packet not in packets_sent:
packets_sent.append(packet)

# Send the packet
try:
sock.sendall(packet)
except:
# Here is the problem, it cannot connect to the server if it looses a packet
connected = False
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while not connected:
try:
print("Problem with sendall")
connect()
connected = True
print('re-connection successful')
except socket.error:
time.sleep(2)

# Timer
if (i == 0):
timer = time.time()
elif (i > 0) and (time.time() > (timer + 0.01)):
if sizeWindow > 1:
j = i + 1
while j < sizeWindow:
packet = id_packet.encode('utf-8')
id_packet = str(int(id_packet) + 1)
packets_resend.append(packet)
j += 1
print(f"send packets: {sizeWindow} -> {sizeWindow/2}")
sizeWindow = sizeWindow / 2
currentTime = (time.time() - g_windowTime) * 1000
print(f'{str(round(currentTime, 2)).replace(".", ",")}; {int(sizeWindow)}')

send_packets(sizeWindow, packets_sent, packets_resend, id_packet)

i += 1

return sizeWindow, packets_sent, id_packet

def connect():
sock.connect(server_address)

execute()

sock.close()

if __name__ == '__main__':
#server = Server() needs to be executed in another computer to see the problem, in the same computer it works fine
#server.start()
time.sleep(1)

client = Client()
client.start()

当客户端丢失数据包时,我无法将其重新连接到服务器,是否有另一种方法可以在不丢失连接的情况下重新连接它们?

如果有人可以帮助我,我真的可以帮忙......

谢谢。

最佳答案

正如@user207421所述,由于您仍在使用TCP连接,您通常不必自己处理传输错误,因为无错数据传输是key features of TCP之一反对UDP。

此外,我建议使用 socketserver用于构建某种客户端/服务器应用程序的 Python 模块。它使您无需编写许多用于连接建立和管理以及线程管理的样板代码。

最后,只有在 sock.accept() 方法中,您才能连接到服务器。我担心当您失去连接时,服务器会在 connection.recv()connection.sendall() 函数中被阻止,因此不接受任何新连接;这就是为什么我们经常将服务器工作负载委托(delegate)给其他线程或进程;来自 socketserver 文档:

These four classes process requests synchronously; each request must be completed before the next request can be started. This isn’t suitable if each request takes a long time to complete, because it requires a lot of computation, or because it returns a lot of data which the client is slow to process. The solution is to create a separate process or thread to handle each request; the ForkingMixIn and ThreadingMixIn mix-in classes can be used to support asynchronous behaviour.

所以,总结一下我的回答:您正在经历一种您不希望遇到的行为。这可能是错误观念的症状。因此,请使用可用的工具来解决此问题。

关于python - 如果 TCP 通信中丢失数据包,如何将客户端重新连接到服务器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59082128/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com