第二章中主要介绍了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)客户端,在这里是一种问题。但是当我们进行网络监控时,需要监控到达某一接口的所有数据包时会故意使用这种客户端。

  优秀的加密方法,才可以保证程序与正确的服务器进行通信。但是当无法做到时,可以使用以下两种方案

  1. 设计或使用在请求中包含唯一标识符或请求ID的协议
  2. 检查响应数据包的地址与请求数据包的地址是否相同,也可以使用connect()来阻止其他地址向客户端发送数据包

  

《Python网络编程》学习笔记--UDP协议的更多相关文章

  1. python 网络编程 tcp和udp 协议

    1. 网络通信协议 osi七层,tcp\ip五层 tcp\ip五层 arp协议:通过IP地址找到mac地址 2.tcp和udp的区别 tcp协议:面向连接,消息可靠,相对udp来讲,传输速度慢,消息是 ...

  2. python网络编程学习笔记(三):socket网络服务器(转载)

    1.TCP连接的建立方法 客户端在建立一个TCP连接时一般需要两步,而服务器的这个过程需要四步,具体见下面的比较. 步骤 TCP客户端 TCP服务器 第一步 建立socket对象  建立socket对 ...

  3. python网络编程学习笔记(10):webpy框架

    转载请注明:@小五义http://www.cnblogs.com/xiaowuyi django和webpy都是python的web开发框架.Django的主要目的是简便.快速的开发数据库驱动的网站. ...

  4. 转 网络编程学习笔记一:Socket编程

    题外话 前几天和朋友聊天,朋友问我怎么最近不写博客了,一个是因为最近在忙着公司使用的一些控件的开发,浏览器兼容性搞死人:但主要是因为这段时间一直在看html5的东西,看到web socket时觉得很有 ...

  5. python网络爬虫学习笔记

    python网络爬虫学习笔记 By 钟桓 9月 4 2014 更新日期:9月 4 2014 文章文件夹 1. 介绍: 2. 从简单语句中開始: 3. 传送数据给server 4. HTTP头-描写叙述 ...

  6. JAVA UDP网络编程学习笔记

    一.UDP网络编程概述 采用TCP协议通信时,客户端的Socket必须先与服务器建立连接,连接建立成功后,服务器端也会持有客户端连接的Socket,客户端的Socket与服务器端的Socket是对应的 ...

  7. python 之 网络编程(基于UDP协议的套接字通信)

    8.5 基于UDP协议的套接字通信 UDP协议:数据报协议 特点:无连接,一发对应一收,先启动哪一端都不会报错 优点:发送效率高,但有效传输的数据量最多为500bytes 缺点:不可靠:发送数据,无需 ...

  8. python网络编程学习《一》

    最近,刚实习完,很喜欢实验楼,但是自己的方向仍然不能确定,自己觉得可选择的空间很大,尽管已经是大四的人了,想到别人都在忙着买职业装,买高跟鞋面试,学习化妆什么的,看看自己,反而开始慢慢关注运动,食疗以 ...

  9. python网络爬虫学习笔记(一)Request库

    一.Requests库的基本说明 引入Rquests库的代码如下 import requests 库中支持REQUEST, GET, HEAD, POST, PUT, PATCH, DELETE共7个 ...

随机推荐

  1. 1492: [NOI2007]货币兑换Cash

    Description 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和 B纪念券(以下 简称B券).每个持有金券的顾客都有一个自己的帐户.金券的数目可以是一个 ...

  2. map映照容器的使用

    map映照容器可以实现各种不同类型数据的对应关系,有着类似学号表的功能. 今天在做并查集的训练时,就用上了map映照容器. 题目就不上了,直接讲一下用法.顺便说一下,实现过程是在C++的条件下. #i ...

  3. POJ 3041 Asteroids(模板——二分最大匹配(BFS增广))

    题目链接: http://poj.org/problem?id=3041 Description Bessie wants to navigate her spaceship through a da ...

  4. Python 使用 virtualenvwrapper 安装虚拟环境

    装载于https://www.jianshu.com/p/9f47a9801329 Python 使用 virtualenvwrapper 安装虚拟环境 Tim_Lee 关注 2017.05.04 2 ...

  5. ECharts插件的使用

    ECharts插件:官网下载echarts.js开发者可以选择源码.下载地址:http://echarts.baidu.com/download.html 下载之后,echarts.js放在js文件夹 ...

  6. mybatis sql循环的使用

    foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合. foreach元素的属性主要有 item,index,collection,open,separator,close. ...

  7. Oracle_索引

    Oracle_索引 索引类似字典的和课本目录,是为了加快对数据的搜索速度而设立的.索引有自己专门的存储空间,与表独立存放. 索引的作用:在数据库中用来加速对表的查询,通过使用快速路径访问方法快速定位数 ...

  8. Android 问题

    1.Cannot refer to a non-final variable 解决方法 内部类如果要引用外部类的变量,则该变量必须为final,这是规定 2.error: No resource id ...

  9. JavaScript对象的valueOf()方法

    js对象中的valueOf()方法和toString()方法非常类似,但是,当需要返回对象的原始值而非字符串的时候才调用它,尤其是转换为数字的时候.如果在需要使用原始值的上下文中使用了对象,JavaS ...

  10. iterator_category

    /* * 迭代器类型 * 1. input ierator * 2. write iterator * 3. forward iterator 在迭代器所形成的区间上进行读写操作 * 4. bidir ...