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. Python开发技术详解PDF

    Python开发技术详解(高清版)PDF 百度网盘 链接:https://pan.baidu.com/s/1F5J9mFfHKgwhkC5KuPd0Pw 提取码:xxy3 复制这段内容后打开百度网盘手 ...

  2. Tornado-Ajax

    介绍 AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML).AJAX 不是新的编程语言,而是一种使用现有标准的新方法.AJAX是在不 ...

  3. ECMA Script 6_ 类 class

    类 class ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板. 通过 class 关键字,可以定义类 class 新的 class 写法只是让对象原型的写法更加 ...

  4. tomcat错误The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path

    在更换tomcat版本后,原来的项目文件中jsp会出现错误The superclass "javax.servlet.http.HttpServlet" was not found ...

  5. thinkphp框架,数据动态缓存后,或数据已读取出来,想分页怎么办

    //读取缓存后赋值到数组,通过array_slice函数处理,如: $blog = S('blogname'); //赋值 $count = count($blog); //条数统计 $page = ...

  6. OSS内文件如何设置为无时间限制的下载链接

    OSS内文件如何设置为无时间限制的下载链接 想把一些文件上传到OSS里,把OSS当网盘用,做成分享的下载链接 发现获取的链接都是有时间限制的 有没有取消这个时间限制的功能或者方法 请将object的权 ...

  7. Java作业四(2017-10-8)

    import java.util.Scanner; public class Helloworld { public static void main(String[] args) { System. ...

  8. dtIntersectSegmentPoly2D 2D上的线段与多边形相交计算 产生结果:是否相交,线段跨越的开始和结束百分比,相交的边

    dtIntersectSegmentPoly2D(startPos, endPos, verts, nv, tmin, tmax, segMin, segMax): http://geomalgori ...

  9. 区块链侧链应用开发平台Asch节点安装及区块生产教程

    1 系统要求 必须是linux系统 必须有公网ip 建议使用ubuntu 14.04 64位 建议内存1G以上 建议带宽2Mb以上 2 安装 2.1 下载 wget https://www.asch. ...

  10. 虚拟机设置IP

    方式NAT 版本信息VMware(14.1.1 build-7528167)和centos7 一,设置网络适配器: 二.设置虚拟网络 三.配置虚拟机(/etc/sysconfig/network-sc ...