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. js 类数组对象arguments

    function Add() { for (var i = 0; i < arguments.length; i++) { console.log(arguments[i]); } } Add( ...

  2. winform 利用Http向服务器上传与下载文件

    利用在服务器端的IIS,布置“请求处理映射”.从而处理,本地发出Post请求.Url指向web网站所在路径的请求映射.由映射代码实现服务器保存文件. winform里面使用,WebClient的对象, ...

  3. css display:flex 属性

    一:display:flex 布局 display:flex 是一种布局方式.它即可以应用于容器中,也可以应用于行内元素.是W3C提出的一种新的方案,可以简便.完整.响应式地实现各种页面布局.目前,它 ...

  4. Android 基础知识

    system/app   与   system/priv-app Android4.4系统在system目录下新增了priv-app目录,在该目录下的apk一般都是系统核心应用如Launcher.sy ...

  5. Web Service学习(一)

    1.WebMethod特性包含哪些属性,都有什么用? 1.BufferResponse属性 该属性表明是否启用对Web Service方法响应的缓冲.当设置为true时,Web Service方法将响 ...

  6. 【Python基础】lpthw - Exercise 44 继承与组合

    一.继承 原则:大部分使用继承的场合都可以用组合取代或者简化,而多重继承则需要不惜一切的避免. 1. 什么是继承 继承:用于指明一个类的大部分或者全部功能都是从一个父类获得的.此时,父类的实例的所有动 ...

  7. JS数组reduce()方法详解及高级技巧

    1.语法 arr.reduce(callback,[initialValue]) reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值(或者上 ...

  8. ide phpStorm 配置PHP路径并本地执行PHP脚本

    1.打开设置(File - Settings) 2. 3. 4.到需要执行脚本的文件处,右击 - Run 5.如果本地还未安装PHP,可以下载Xampp,并将PHP目录新增至系统环境变量Path处,重 ...

  9. 【感悟】一次不太好的寻找bug的体验,RecyclerView

    最近在网上看Android的学习视频的时候,视频中使用了RecyclerView这个组件,我按照视频中的指示对RecyclerView进行配置. 程序编译通过了,但是在运行时程序会崩溃.我复制了日志里 ...

  10. 洛谷P4778 Counting swaps 数论

    正解:数论 解题报告: 传送门! 首先考虑最终的状态是固定的,所以可以知道初始状态的每个数要去哪个地方,就可以考虑给每个数$a$连一条边,指向一个数$b$,表示$a$最后要移至$b$所在的位置 显然每 ...