《Python网络编程》学习笔记--UDP协议
第二章中主要介绍了UDP协议
UDP协议的定义(转自百度百科)
UDP是OSI参考模型中一种无连接的传输层协议,它主要用于不要求分组顺序到达的传输中,分组传输顺序的检查与排序由应用层完成,提供面向事务的简单不可靠信息传送服务。UDP 协议基本上是IP协议与上层协议的接口。UDP协议适用端口分别运行在同一台设备上的多个应用程序。
UDP提供了无连接通信,且不对传送数据包进行可靠性保证,适合于一次传输少量数据,UDP传输的可靠性由应用层负责。常用的UDP端口号有:
DNS(53) TFTP(69) SNMP(161)
UDP报文没有可靠性保证、顺序保证和流量控制字段等,可靠性较差。但是正因为UDP协议的控制选项较少,在数据传输过程中延迟小、数据传输效率高,适合对可靠性要求不高的应用程序,或者可以保障可靠性的应用程序,如DNS、TFTP、SNMP等。
UDP在IP报文中的位置如图所示。
端口号
无符号16位数(0-65536)其中知名端口(0-1023)、注册端口(1024-49151)、其余端口(49152-65535)
Source(IP:port number) ->Destination(IP:port number)
在python中可以使用socket模块的getservbyname()函数获取知名端口名对应的端口号例如
import socket socket.getservbyname('domain')
Out[4]: 53
socket.getservbyname('http')
Out[5]: 80
套接字
在设计网络编程API时,Python标准库在底层对兼容POSIX操作系统(注:可移植操作系统接口(Portable Operating System Interface of UNIX,缩写为 POSIX ),如LInux和MacOS)网络操作的底层系统调用进行了封装,并未所有普通的原始调用提供了一个简单的基于对象的系统。封装后的Python函数名与原始系统调用名相同。Python的这种设计使开发者可以使用早已熟知的方法来调用传统系统。
无论对于WIndows还是POSIX系统,网络操作背后的系统调用斗神围绕着套接字(Socket)这一概念进行的。
套接字是一个通信端点,操作系统使用整数标识套接字,而Python使用socket.socket对象来更方便的表示套接字,该对象内部维护了操作系统标识套接字的整数(可以调用它的fileno()方法来查看),每当调用socket.socket对象的方法请求使用该套接字的系统调用时,该对象都会自动使用内部维护的套接字整数标识符。
根据书上的代码,我们可以建立一个简单的UDP客户端
#!/usr/bin/env python3
# Foundations of Python Network Programming, Third Edition
# https://github.com/brandon-rhodes/fopnp/blob/m/py3/chapter02/udp_local.py
# UDP client and server on localhost import argparse, socket
from datetime import datetime MAX_BYTES = 65535 def server(port):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('127.0.0.1', port))
print('Listening at {}'.format(sock.getsockname()))
while True:
data, address = sock.recvfrom(MAX_BYTES)
text = data.decode('ascii')
print('The client at {} says {!r}'.format(address, text))
text = 'Your data was {} bytes long'.format(len(data))
data = text.encode('ascii')
sock.sendto(data, address) def client(port):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
text = 'The time is {}'.format(datetime.now())
data = text.encode('ascii')
sock.sendto(data, ('127.0.0.1', port))
print('The OS assigned me the address {}'.format(sock.getsockname()))
data, address = sock.recvfrom(MAX_BYTES) # Danger! See Chapter 2
text = data.decode('ascii')
print('The server {} replied {!r}'.format(address, text)) if __name__ == '__main__':
choices = {'client': client, 'server': server}
parser = argparse.ArgumentParser(description='Send and receive UDP locally')
parser.add_argument('role', choices=choices, help='which role to play')
parser.add_argument('-p', metavar='PORT', type=int, default=1060,
help='UDP port (default 1060)')
args = parser.parse_args()
function = choices[args.role]
function(args.p)
使用powshell(Windows下(目录有空格转义居然是用`,试了\半天0.0)定位到当前目录
输入
python udp_local.py server #udp_local.py是本文件名
当然如果端口被占用(例如本例子中的1060)会提示
Traceback (most recent call last):
File "udp_local.py", line 44, in <module>
function(args.p)
File "udp_local.py", line 14, in server
sock.bind(('127.0.0.1', port))
OSError: [WinError 10048] 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。
之后再打开一个shell定位到当前页面输入
python udp_local.py client
会显示
The OS assigned me the address ('0.0.0.0', 59457)
The server ('127.0.0.1', 1060) replied 'Your data was 38 bytes long'
而server窗口同时显示
The client at ('127.0.0.1', 59457) says 'The time is 2018-01-15 16:24:19.498818'
而如果server已关闭本条指令会在powershell显示
The OS assigned me the address ('0.0.0.0', 50859)
Traceback (most recent call last):
File "udp_local.py", line 44, in <module>
function(args.p)
File "udp_local.py", line 31, in client
data, address = sock.recvfrom(MAX_BYTES) # Danger! See Chapter 2
ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。
程序中使用了sock.sendto()函数(需要指定地址和端口)
使用了sock.getsockname()调用查看IP地址和端口号,在输出中我们可以看出在这里分配的是59457端口
混杂客户端与垃圾回复
从上面的程序中我们也能明显看出,这样的程序实际上是相当危险的,在客户端等待服务器的响应时(在windows下可以通过发送响应中添加time.sleep()实现)我们可以向客户端程序发送一个‘伪造的信息’,如
>>>import socket
>>>sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
>>>sock.sendto('FAKE'.encode('ascii'),('127.0.0.1',59457))
客户端会立即结束等待,并将此响应看为服务器的响应
像这样不考虑地址是否正确,接受并处理所有收到的数据包的网络监听客户端在技术上叫做混杂(promiscuous)客户端,在这里是一种问题。但是当我们进行网络监控时,需要监控到达某一接口的所有数据包时会故意使用这种客户端。
优秀的加密方法,才可以保证程序与正确的服务器进行通信。但是当无法做到时,可以使用以下两种方案
- 设计或使用在请求中包含唯一标识符或请求ID的协议
- 检查响应数据包的地址与请求数据包的地址是否相同,也可以使用connect()来阻止其他地址向客户端发送数据包
《Python网络编程》学习笔记--UDP协议的更多相关文章
- python 网络编程 tcp和udp 协议
1. 网络通信协议 osi七层,tcp\ip五层 tcp\ip五层 arp协议:通过IP地址找到mac地址 2.tcp和udp的区别 tcp协议:面向连接,消息可靠,相对udp来讲,传输速度慢,消息是 ...
- python网络编程学习笔记(三):socket网络服务器(转载)
1.TCP连接的建立方法 客户端在建立一个TCP连接时一般需要两步,而服务器的这个过程需要四步,具体见下面的比较. 步骤 TCP客户端 TCP服务器 第一步 建立socket对象 建立socket对 ...
- python网络编程学习笔记(10):webpy框架
转载请注明:@小五义http://www.cnblogs.com/xiaowuyi django和webpy都是python的web开发框架.Django的主要目的是简便.快速的开发数据库驱动的网站. ...
- 转 网络编程学习笔记一:Socket编程
题外话 前几天和朋友聊天,朋友问我怎么最近不写博客了,一个是因为最近在忙着公司使用的一些控件的开发,浏览器兼容性搞死人:但主要是因为这段时间一直在看html5的东西,看到web socket时觉得很有 ...
- python网络爬虫学习笔记
python网络爬虫学习笔记 By 钟桓 9月 4 2014 更新日期:9月 4 2014 文章文件夹 1. 介绍: 2. 从简单语句中開始: 3. 传送数据给server 4. HTTP头-描写叙述 ...
- JAVA UDP网络编程学习笔记
一.UDP网络编程概述 采用TCP协议通信时,客户端的Socket必须先与服务器建立连接,连接建立成功后,服务器端也会持有客户端连接的Socket,客户端的Socket与服务器端的Socket是对应的 ...
- python 之 网络编程(基于UDP协议的套接字通信)
8.5 基于UDP协议的套接字通信 UDP协议:数据报协议 特点:无连接,一发对应一收,先启动哪一端都不会报错 优点:发送效率高,但有效传输的数据量最多为500bytes 缺点:不可靠:发送数据,无需 ...
- python网络编程学习《一》
最近,刚实习完,很喜欢实验楼,但是自己的方向仍然不能确定,自己觉得可选择的空间很大,尽管已经是大四的人了,想到别人都在忙着买职业装,买高跟鞋面试,学习化妆什么的,看看自己,反而开始慢慢关注运动,食疗以 ...
- python网络爬虫学习笔记(一)Request库
一.Requests库的基本说明 引入Rquests库的代码如下 import requests 库中支持REQUEST, GET, HEAD, POST, PUT, PATCH, DELETE共7个 ...
随机推荐
- [bzoj1700]: [Usaco2007 Jan]Problem Solving 解题
不能贪心!不能贪心!不能贪心! 反正有反例(有的题目月初支付款很少,月末支付款很大,和前面的题凑到一个月的话可能导致下个月写不了= =这时放后一个月,和后面的题一起开始写可能更优) 比如: 50 44 ...
- 数位dp初探
我这种蒟蒻就一直不会写数位dp.. 于是开了个坑.. 1833: [ZJOI2010]count 数字计数 这道被KPM大爷说是入门题..嗯似乎找找规律然后减掉0的情况后乱搞就可以了..(但是还是写了 ...
- DFS入门__poj1979
Red and Black Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 26944 Accepted: 14637 D ...
- Choose the best route(最短路)dijk
http://acm.hdu.edu.cn/showproblem.php?pid=2680 Choose the best route Time Limit: 2000/1000 MS (Java/ ...
- castle之动态代理
动态代理 DynamicProxy,这里说的动态代理是直接使用Castle.net 中提供的,并非自己实现的,因为别人写的很好,拿着用就行了. 动态代理的工作模式: 一般我们获取一个类型的实例都是通过 ...
- 微信小程序监听input输入并取值
小程序的事件分为两种,冒泡和非冒泡事件,像<form/>的submit事件,<input/>的input事件,<scroll-view/>的scroll事件等非冒泡 ...
- UEP-弹窗
注意:弹出窗口Action中的dataWrap属性要加上set方法 默认情况下为GET方式传递参数,此方法对参数的长度有限制,若是长度超过范围的话请使用POST方式 function testPopW ...
- 邓_Excal
--------------------------------------------------------------------- 快速输入固定文字 有一些固定的词组,输入 1 个.2 个,貌 ...
- 如何 Scale Up/Down Deployment?- 每天5分钟玩转 Docker 容器技术(126)
伸缩(Scale Up/Down)是指在线增加或减少 Pod 的副本数.Deployment nginx-deployment 初始是两个副本. k8s-node1 和 k8s-node2 上各跑了一 ...
- Java高级工程师——面试总结
面试技巧 1.背熟你的简历 原因:面试的第一个问题,一般都是让你简单介绍下你自己,或者介绍一下你最近的项目,而一个面试者,如果连自己的简历都无法熟知,对里面提到的项目.技术都无法描述清楚的话,我想没有 ...