Python网络编程笔记(一):UDP

IP层需要解决两个问题:

  1. 通过多路复用,区分不同应用程序的数据包
  2. 通过可靠传输,修复错误

两个主要协议:用户数据包协议(UDP)、传输控制协议(TCP),UDP用端口多路复用,解决问题一。TCP可以同时解决这两个问题。

UDP

不得不坦率的承认,我们不太可能在自己的任何一个应用程序中使用UDP,如果认为UDP适用于某个应用,不妨了解一下消息队列。

端口号

一共16位,0-65536之间

  • 知名端口0-1023
  • 注册端口1024-49151 有IANA推荐的端口,可能被占用
  • 其余49152-65536 可以随意使用,端口池

套接字socket

  • POSIX系统:可移植操作系统接口(Portable Operating System Interface), 比如Linux和Mac OS X
  • 套接字(socket):一个通信端点,操作系统使用整数来标识。Python使用socket.socket对象创建。是一个IP地址和端口号组成的元组。

UDP丢包可能由于网络媒介,或者网络繁忙,重发请求应该采取指数退避

请求ID是解决重复响应的好方法。重复响应问题是我们收到所有数据包后又收到一个被认为丢失的响应,此时可能误解这个是当前请求的响应。随机选择请求ID可以预防最简单的电子欺骗(spoofing)

区分服务端绑定bind()和客户端连接connnec(),绑定指定要使用的端口,而连接限制了客户端可以接受的响应。

运行在不同服务器上的UDP代码

argparse是用来处理arg的包

#!/usr/bin/env python3
# Foundations of Python Network Programming, Third Edition
# https://github.com/brandon-rhodes/fopnp/blob/m/py3/chapter02/udp_remote.py
# UDP client and server for talking over the network

import argparse, random, socket, sys

MAX_BYTES = 65535

def server(interface, port):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.bind((interface, port))
    print('Listening at', sock.getsockname())
    while True:
        data, address = sock.recvfrom(MAX_BYTES)
        if random.random() < 0.5:
            print('Pretending to drop packet from {}'.format(address))
            continue
        text = data.decode('ascii')
        print('The client at {} says {!r}'.format(address, text))
        message = 'Your data was {} bytes long'.format(len(data))
        sock.sendto(message.encode('ascii'), address)

def client(hostname, port):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.connect((hostname, port))
    print('Client socket name is {}'.format(sock.getsockname()))

    delay = 0.1  # seconds
    text = 'This is another message'
    data = text.encode('ascii')
    while True:
        sock.send(data)
        print('Waiting up to {} seconds for a reply'.format(delay))
        sock.settimeout(delay)
        try:
            data = sock.recv(MAX_BYTES)
        except socket.timeout as exc:
            delay *= 2  # wait even longer for the next request
            if delay > 2.0:
                raise RuntimeError('I think the server is down') from exc
        else:
            break   # we are done, and can stop looping

    print('The server says {!r}'.format(data.decode('ascii')))

if __name__ == '__main__':
    choices = {'client': client, 'server': server}
    parser = argparse.ArgumentParser(description='Send and receive UDP,'
                                     ' pretending packets are often dropped')
    parser.add_argument('role', choices=choices, help='which role to take')
    parser.add_argument('host', help='interface the server listens at;'
                        ' host the client sends to')
    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.host, args.p)

绑定接口

服务器bind()绑定接口时,可以使用:

  • 127.0.0.1 本机上其他应用程序接口
  • 空字符串或者0.0.0.0 该服务器的任意网络接口
  • 该服务器的一个外网IP
    • 客户端是同一台机器的自环接口127.0.0.1,不会响应
    • 客户端是本机外网IP,可以连通
    • 客户端是其他机器,可以连接

UDP分组

MTU:最大传输单元、最大数据包容量,以太网和无线网卡一般MTU为1500B

较大数据包会被分解,可以查看系统MTU

// import IN 已经被py3.6弃用了。。更新为手动写
class IN:
    IP_MTU = 14
    IP_MTU_DISCOVER = 10
    IP_PMTUDISC_DO = 2

sock.setsockopt(socket.IPPRPTO_IP, IN.IP_MTU_DISCOVER, IN.IP_PMTUDISC_DO)

套接字选项

getsockopt()setsockopt()来获取和设置,第一个参数为所属选项组,第二个参数为要设置的选项名

比如设置广播:

s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)

其他设置是否经过网关SO_DONTROUTE,判断套接字类型(UDP/TCP)SO_TYPE

广播

设置允许广播后,还需要客户端目标地址改为广播地址,用ifconfig查看,或者使用python中的特殊广播地址符<broadcast>, 如果使用普通地址,效果和未设置广播一样。

何时使用UDP

  • 历史原因
  • 对时间要求严格的媒体流
  • 设计使用LAN子网的多播

当我们发现有一种UDP协议能够适用于应用程序时,我们很可能已经重新实现了TCP。不过,实现的很糟糕。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,039评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,223评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,916评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,009评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,030评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,011评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,934评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,754评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,202评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,433评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,590评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,321评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,917评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,568评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,738评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,583评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,482评论 2 352

推荐阅读更多精彩内容

  • 本文主要通过整理网络上的资料,整理出的关于TCP方面的简单理论知识。作为Java程序员虽然更多的时候我们都是直接调...
    tomas家的小拨浪鼓阅读 5,541评论 1 100
  • 1.1 TCP/IP协议组 TCP/IP协议(传输控制协议)由网络层的IP协议和传输层的TCP协议组成 IP层负责...
    F麦子阅读 2,786评论 0 25
  • 1.这篇文章不是本人原创的,只是个人为了对这部分知识做一个整理和系统的输出而编辑成的,在此郑重地向本文所引用文章的...
    SOMCENT阅读 13,062评论 6 174
  • 定义 网络协议为计算机网络中进行数据交换而建立的规则、标准或约定的集合。网络协议主要由三个要素组成:语义、语法及时...
    FlyAndroid阅读 988评论 0 10
  • 2017年10月3号 蕙兰的咖啡冥想 感恩: 在国庆期间倍感祖国的伟大和强盛!感恩国家对我们民众的关怀!感恩祖国的...
    蕙兰坊阅读 168评论 0 2