UDP服务端&客户端编程

'''
udp编程
创建socket对象,socket.SOCK_DGRAM
绑定ip和port,bind()方法
传输数据
1.接收数据,socket.recvfrom(bufsize[,flags]),获得一个2元祖(string,address)
2.发送数据,socket.sendto(string,address) ,发送给某地址信息
释放资源
'''
import socket
server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('0.0.0.0',9999))
data = server.recv(1024) #阻塞等待数据
data = server.recvfrom(1024) #阻塞等待数据(value,(ip,port))
server.sendto(b'hello',('127.0.0.1',10000))
server.close() '''
udp客户端编程流程
创建socket对象,socket.SOCK_DGRAM
发送数据,socket.sendto(string,address)发送给某地址信息
接收数据,socket.recvfrom(bufsize[,flags]),获取一个2元祖(string,address)
释放资源
'''
client = socket.socket(type=socket.SOCK_DGRAM)
raddr = ('127.0.0.1',10000)
client.connect(raddr)
client.sendto(b'hello',raddr)
data = client.recv(1024) #阻塞等待数据
data = client.recvfrom(1024)#阻塞等待数据,(value,(ip,port))
client.close()
注意:udp时无连接协议,所以可以只有任何一端,例如客户端数据发往服务端,服务端存在与否不重要
udp的socket对象创建后,时没有占用本地地址和端口的
bind() 可以指定本地地址和端口laddr,会立即占用
connect() 可以立即占用本地地址和端口,填充远端地址和端口raddr
sendto() 可以立即占用本地地址和端口,并把数据发往指定远端,只有有了本地绑定端口,sendto就可以向任何远端发送数据
send() 需要和connect()配合使用,可以使用已经从本地端口把数据发往raddr指定的远端
recv() 要求一定要在占用可本地端口后,返回接收的数据
recvfrom() 要求一定要占用了本地端口后,返回接收数据和对端地址的二元组

 udp聊天server

import threading
import socket
import logging
FORMAT = '%(asctime)s,%(threadName)s %(thread)d,%(message)s'
logging.basicConfig(level=logging.INFO,format=FORMAT) class ChatUDPServer:
def __init__(self,ip='127.0.0.1',port=9999):
self.addr = (ip,port)
self.sock = socket.socket(type=socket.SOCK_DGRAM)
self.event = threading.Event()
self.clients = set()
def start(self):
self.sock.bind(self.addr)
threading.Thread(target=self.receive,name='receive').start() def receive(self):
while not self.event.is_set():
data,raddr= self.sock.recvfrom(1024)
print(data)
if data.strip() == b'quit':
if raddr in self.clients:
self.clients.remove(raddr)
logging.info('remove leave clients')
# self.sock.close() 面向无连接的 所以每天udp产生的时候不需要close
continue
self.clients.add(raddr)
for i in self.clients:
self.sock.sendto('ack {}'.format(data).encode(),i) def stop(self):
for i in self.clients:
self.sock.sendto(b'bye bye',i)
self.sock.close()
self.event.set() def main():
cs = ChatUDPServer()
cs.start()
while True:
cmd = input("please set stop command>>>>>>")
if cmd == 'quit':
cs.stop()
break
logging.info(cs.clients)
logging.info(threading.enumerate()) if __name__ == '__main__':
main()

心跳机制:客户端定时往服务端发送的,服务端不需要ack回复,只记录客户端存活

class ChatUDPServer:
def __init__(self,ip='127.0.0.1',port=9999,interval=10):
self.addr = (ip,port)
self.sock = socket.socket(type=socket.SOCK_DGRAM)
self.event = threading.Event()
self.clients = {}
self.interval = interval
def start(self):
self.sock.bind(self.addr)
threading.Thread(target=self.receive,name='receive').start() def receive(self):
while not self.event.is_set():
localset = set()      #迭代字典时不能操作字典,把超时的放在集合里面
data,raddr= self.sock.recvfrom(1024)
current = datetime.datetime.now().timestamp() #return float
if data.strip == b'^hb^': #从client接收到指定的字符串,做判断
print('~~~~~~~~',raddr)
self.clients[raddr] = current
continue
elif data.strip() == b'quit':
if raddr in self.clients:
self.clients.pop(raddr,None)
logging.info('remove leave clients')
# self.sock.close() 面向无连接的 所以不需要close
continue
self.clients[raddr] = current
for c,stamp in self.clients.items():
if current - stamp > self.interval:
localset.add(c)
else:
self.sock.sendto('ack {}'.format(data).encode(), i)
for i in localset:    
localset.pop(i) def stop(self):
for i in self.clients:
self.sock.sendto(b'bye bye',i)
self.sock.close()
self.event.set()

client端的更改

    def start(self):
self.sock.connect(self.addr)
self.sock.sendto(b'hello server',self.addr)
threading.Thread(target=self.reveive,name='receive').start()
threading.Thread(target=self._sendb,name="heartbeat",daemon=True).start()
     #daemon 随着主线程退出而退出,不用程序员关注线程退出的问题
def _sendb(self):
while True:
self.sock.sendto(b'^hb^',self.addr)

Python之socket_udp的更多相关文章

  1. Python中的多进程与多线程(一)

    一.背景 最近在Azkaban的测试工作中,需要在测试环境下模拟线上的调度场景进行稳定性测试.故而重操python旧业,通过python编写脚本来构造类似线上的调度场景.在脚本编写过程中,碰到这样一个 ...

  2. Python高手之路【六】python基础之字符串格式化

    Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...

  3. Python 小而美的函数

    python提供了一些有趣且实用的函数,如any all zip,这些函数能够大幅简化我们得代码,可以更优雅的处理可迭代的对象,同时使用的时候也得注意一些情况   any any(iterable) ...

  4. JavaScript之父Brendan Eich,Clojure 创建者Rich Hickey,Python创建者Van Rossum等编程大牛对程序员的职业建议

    软件开发是现时很火的职业.据美国劳动局发布的一项统计数据显示,从2014年至2024年,美国就业市场对开发人员的需求量将增长17%,而这个增长率比起所有职业的平均需求量高出了7%.很多人年轻人会选择编 ...

  5. 可爱的豆子——使用Beans思想让Python代码更易维护

    title: 可爱的豆子--使用Beans思想让Python代码更易维护 toc: false comments: true date: 2016-06-19 21:43:33 tags: [Pyth ...

  6. 使用Python保存屏幕截图(不使用PIL)

    起因 在极客学院讲授<使用Python编写远程控制程序>的课程中,涉及到查看被控制电脑屏幕截图的功能. 如果使用PIL,这个需求只需要三行代码: from PIL import Image ...

  7. Python编码记录

    字节流和字符串 当使用Python定义一个字符串时,实际会存储一个字节串: "abc"--[97][98][99] python2.x默认会把所有的字符串当做ASCII码来对待,但 ...

  8. Apache执行Python脚本

    由于经常需要到服务器上执行些命令,有些命令懒得敲,就准备写点脚本直接浏览器调用就好了,比如这样: 因为线上有现成的Apache,就直接放它里面了,当然访问安全要设置,我似乎别的随笔里写了安全问题,这里 ...

  9. python开发编译器

    引言 最近刚刚用python写完了一个解析protobuf文件的简单编译器,深感ply实现词法分析和语法分析的简洁方便.乘着余热未过,头脑清醒,记下一点总结和心得,方便各位pythoner参考使用. ...

随机推荐

  1. linux抓包工具tcpdump使用总结

    tcpdump采用命令行方式对接口的数据包进行筛选抓取,其丰富特性表现在灵活的表达式上 1.格式 # tcpdump --help tcpdump version 4.1-PRE-CVS_2012_0 ...

  2. 我的 FPGA 学习历程(04)—— 练习 verilog 硬件描述语言

    这篇讲的是使用 verilog 硬件描述语言编写一个 3 - 8 译码器. 3 - 8 译码器是一个简单的组合逻辑,用于实现并转串,其输入输出关系如下: | 输入  |  输出  | -------- ...

  3. XVII Open Cup named after E.V. Pankratiev. GP of Tatarstan

    A. Arithmetic Derivative 形如$p^p(p是质数)$的数的比值为$1$,用$k$个这种数相乘得到的数的比值为$k$,爆搜即可. #include<cstdio> # ...

  4. 【自动化测试】使用Java+selenium填写验证码成功登录

    这是我第一次发博客,若有问题,请多多指教! 本次是为了帮忙解决,如果在平时自动化遇到有验证码填写的情况,我们如何成功登录情况. 思路: 首先我们先将验证码复制并保存成一个图片,然后使用tesserac ...

  5. Java Web 禁用Cookie对Session的影响

    如果客户端禁用了Cookie,那么服务端就不能得到Session了.因为通过Session ID来确定当前会话对应的服务端Session,而Session ID通过Cookie来传递,所以禁用Cook ...

  6. Wireshark简单使用教程1——附视频

    目录 Wireshark的简介 Wireshark面向的用户 Wireshark的下载安装 Wireshark抓取一个流量包 内容 1.Wireshark的简介 Wireshark(前称Etherea ...

  7. Android学好Shape不再依赖美工

    原创 2014年03月27日 15:33:41 标签: Android Shape用法 20427 先上图 其实以上效果没有让美工提供任何图片 只要学会Shape你就能实现 想怎么样就怎么样 下面介绍 ...

  8. BEM的命名规则

    给自己提个醒,别乱命名了

  9. js文档就绪函数

    $(function(){ //执行的内容 }): $().ready(function(){ //执行的内容 }); $(document).ready(function(){ //执行的内容 }) ...

  10. awk 复习

    awk 的再次学习!!!! awk 的一般模式 awk '{parttern + action }' {filename} , 提取/etc/passwd 的用户 awk -F ":&quo ...