python udp socket解决服务端响应时间长的指数退避算法

UDP连接是一个不可靠的连接,也就是说,UDP通信过程中可能出现数据包丢失的情况,或者是服务端宕机后,客户端不知道服务端状态,仍然不停的访问服务端的情况。针对这一情况,UDP客户端必须选择一个等待时间,一旦超过这个时间间隔还未收到服务端的响应,就重新发送请求,若多次请求仍未收到服务端的响应,就认为服务端宕机。而且,由于数据丢包的主要原因在于网络拥塞,因此,客户端在等待时间内未收到服务端的应答,客户端重发不应该和上次一样,这样就会造成网络拥塞加剧,鉴于这种情况,客户端采用指数退避算法,使得重发数据包频率越来越低,逐渐的环境网络的拥塞。同时,如果客户端选择的等待时间不合理,如选择200毫秒,但是由于发送的请求可能200毫秒才能到达服务端,这时客户端在等待时间内永远都收不到服务端的应答报文,这时也需要调整等待时间。

为了模拟网络拥塞或者服务器宕机出现的丢包,在服务端使用random()随机drop客户端的请求。

服务端代码:

import socket
import random


def server(ipaddr, port):
    # 开启UDP服务
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind((ipaddr, port))
    print('Listening at {0}'.format(s.getsockname()))
    while True:
        data, addr = s.recvfrom(1024)
        print('From {0} Data:{1}'.format(addr, data.decode()))
        info = '12345'
        # 一半的概率会丢失客户端的请求
        if random.random() < 0.5:
            print('Drop packet from {0}'.format(addr))
            continue
        s.sendto(info.encode(), addr)


if __name__ == '__main__':
    server('127.0.0.1', 12345)

对于客户端,调用套接字的settimeout()方法,设置等待时间。若多次请求超时,就会终止接收。

客户端代码:

import socket


def client(ipaddr, port):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 设置初始的客户端等待响应时间
    delay = 0.1
    while True:
        send_data = input('enter info:')
        s.sendto(send_data.encode(), (ipaddr, port))
        print('waiting up to {0} seconds for a reply'.format(delay))
        s.settimeout(delay)
        try:
            data, addr = s.recvfrom(1024)
            print('From {0} Data:{1}'.format(addr, data.decode()))
            if data:
                delay = 0.1
        except socket.timeout:
            # 每次超时后,需要动态调整等待时间,当等待时间大于2秒时,就认为服务端宕机
            delay *= 2
            if delay > 2.0:
                print('Server down')
                break
            else:
                continue


if __name__ == '__main__':
    client('127.0.0.1', 12345)

 

当然!以下是一个简单的Python UDP客户端和服务端的代码示例: UDP服务端代码: ```python import socket # 创建一个UDP socket server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 绑定IP地址和端口号 server_address = ('localhost', 12345) server_socket.bind(server_address) print("UDP服务端已启动,等待客户端发送消息...") while True: # 接收客户端发送的数据和客户端地址 data, client_address = server_socket.recvfrom(1024) print(f"接收到来自客户端 {client_address} 的消息:{data.decode()}") # 处理接收到的数据,这里可以根据具体需求进行相应的处理逻辑 # 向客户端发送响应数据 response = "已收到你的消息!" server_socket.sendto(response.encode(), client_address) ``` UDP客户端代码: ```python import socket # 创建一个UDP socket client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 服务端地址 server_address = ('localhost', 12345) while True: # 发送数据到服务端 message = input("请输入要发送的消息:") client_socket.sendto(message.encode(), server_address) # 接收服务端的响应数据 data, server_address = client_socket.recvfrom(1024) print(f"接收到服务端的响应:{data.decode()}") ``` 以上代码示例中,服务端使用`socket.socket()`创建一个UDP socket对象,然后绑定IP地址和端口号,并在循环中接收客户端发送的数据。客户端同样使用`socket.socket()`创建一个UDP socket对象,然后通过`sendto()`方法发送数据到服务端,并通过`recvfrom()`方法接收服务端的响应数据。 请注意,UDP是一个无连接的协议,因此在UDP通信中,客户端和服务端之间并没有建立持久的连接。每次通信都是通过发送和接收数据报进行。此示例仅展示了一个简单的UDP客户端和服务端实现,并未处理异常情况和错误处理等复杂情况。在实际应用中,可能需要根据具体需求进行适当的扩展和改进。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

楊木木8023

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值