python udp编程_Python-UDP编程

1、UDP编程:

测试命令:

windows:

netstat  -anp udp | findstr 9999

Linux: 发给服务器数据

echo '233' | nc -u 127.0.0.1 9999

2、UDP服务器端编程:

UDP服务器端编程流程:(从图中可以看到,服务器端只需要一个socket)

创建socket 对象,socket.SOCK_DGRAM

绑定IP 和 Port, bind() 方法

传输数据:

接受数据:socket.recvfrom(bufsize [, flags] ) ,获取一个二元组()

发送数据:socket.sendto(string, address) 发给某地址某信息

释放资源

1 importsocket2

3 socket = socket.socket(type=socket.SOCK_DGRAM)4

5 ip = '127.0.0.1'

6 port = 9999

7

8 laddr =ip, port9

10 socket.bind(laddr) #服务器端正式启动

11

12 data, raddr = socket.recvfrom(1024) #没有接收到,会处于阻塞状态

13

14 socket.sendto(data, raddr)15

16 socket.close()

UDP客户端编程流程:

注意:UDP是无连接协议,多以可以只有任何一端,例如客户端数据发往服务端,服务器端存在与否无所谓。

UDP编程中bind、connect、send、sendto、recv、recfrom方法使用

UDP的socket对象创建后,是么有占用本地地址额端口的

注意:

1、UDP 创建socket后,不能直接recv,recvfrom,,只有知道了本地地址和端口,服务器端才能知道数据应该发给你

2、send 和 connect 搭配使用。

心跳机制:

加一个ack机制 和 心跳 hearbeat

心跳,就是一端定时的发往另一端的信息,一般每次数据越少越好,心跳时间间隔约定好就行。

ack 即响应,一端收到另一端的消息后返回的确认消息

心跳机制:

一般来说是客户端定时发往服务器端的,服务器端并不需要ACK 回复客户端,只需要记录该客户端还活着就行(比如群聊,如果客户端不活着,就没必要回复)

如果是服务器端定时发往客户端的,一般需要 客户端ack 响应,表示活着,,如果没有收到ack的客户端,服务器端移除其信息,这种实现比较复杂,较少使用。

也就是双向都发送心跳,很少使用

UDP实现群聊:

server端:

1 importsocket2 importthreading3 importlogging4 importdatetime5

6

7 FORMAT = '%(asctime)s %(thread)s %(threadName)s %(message)s'

8 logging.basicConfig(format=FORMAT, level=logging.INFO)9

10 classChatServer:11 def __init__(self, ip='127.0.0.1', port=9999, interval=10):12 self.laddr =ip, port13 self.event =threading.Event()14 self.sock = socket.socket(type=socket.SOCK_DGRAM)15 self.clients ={}16 self.interval =interval17

18 defstart(self):19 self.sock.bind(self.laddr)20

21 threading.Thread(target=self.recv, name='recvive').start()22

23 defrecv(self):24 while notself.event.is_set():25 data, raddr = self.sock.recvfrom(1024)26 localkeys =set()27 logging.info(data)28

29 #心跳信息

30 if data.strip() == b'^hb^':31 self.clients[raddr] =datetime.datetime.now().timestamp()32 continue

33

34 if data.strip() == b'quit':35 #若一个客户端刚进来,还没有加到字典中,直接pop,会报KerryError

36 #if raddr in self.clients.keys():

37 self.clients.pop(raddr, None)38 continue

39 self.clients[raddr] =datetime.datetime.now().timestamp()40

41 #z再次发送数据的时间,如果之后没有再次进入,这次的时间就作为下次比较时间,所以这次的时间可以认为是最新的心跳信息

42 current =datetime.datetime.now().timestamp()43 msg = '{}--{}'.format(data.decode(), '******').encode()44

45 #过期的就不在发数据给客户端了,并且剔除掉

46 #z 字典不能再遍历的时候,删除内容

47 for r, t inself.clients.items():48 if current - t >self.interval:49 localkeys.add(r)50 self.sock.sendto(msg, r)51 for r inlocalkeys:52 self.clients.pop(r)53

54 defstop(self):55 self.sock.close()56 self.event.set()57

58

59 defmain():60 cs =ChatServer()61 cs.start()62

63 whileTrue:64 cmd = input(">>>")65 if cmd == 'quit':66 cs.stop()67 break

68 logging.info(threading.enumerate())69

70

71 if __name__ == "__main__":72 main()

群聊server端

client端:

1 importsocket2 importthreading3 importlogging4 importdatetime5

6

7 FORMAT = '%(asctime)s %(thread)s %(threadName)s %(message)s'

8 logging.basicConfig(format=FORMAT, level=logging.INFO)9

10 classChatClient:11 def __init__(self, ip='127.0.0.1', port=9999, interval=3):12 self.raddr =ip, port13 self.event =threading.Event()14 self.sock = socket.socket(type=socket.SOCK_DGRAM)15 self.interval =interval16

17 defstart(self):18 self.sock.connect(self.raddr)19

20 threading.Thread(target=self.recv, name='c-recv').start()21

22 #每隔interval 就发送一次心跳信息

23 threading.Thread(target=self.hearbeat, name='ht',daemon=True).start()24

25 defrecv(self):26 while notself.event.is_set():27 data, raddr = self.sock.recvfrom(1024)28 print(data)29 print(raddr)30 defhearbeat(self):31 while notself.event.wait(self.interval):32 self.send('^hb^')33

34

35

36 defsend(self, msg):37 self.sock.send(msg.encode())38

39 defstop(self):40 self.sock.close()41 self.event.set()42

43

44 defmain():45 cc =ChatClient()46 cc.start()47

48 whileTrue:49 cmd = input('>>')50 if cmd == 'quit':51 cc.stop()52 break

53 cc.send(cmd)54 logging.info(threading.enumerate())55

56

57

58 if __name__ == "__main__":59 main()

群聊client端

注意:

如果是如上图所示,是一个解释器进程,建立两个对象,但是这两个对象分别在不同的线程中跑。

如果直接运行两次 client,就是两个客户端进程

UDP 协议的应用:

UDP 是无连接的,它是基于以下假设:

网络足够好

消息不会丢包

包不会乱序

但是,即使在局域网,也不能保证不丢包,而且包到达的不一定有序。

应用场景:

视频,音频传输,一般来说丢一些包。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值