socket介绍及UDP协议

在python语言中有一个名为socket的标准库模块,这个模块提供了访问 BSD 套接字 的接口。在所有平台上都通用。

套接字协议族

本质上是模块类中定义的属性变量,作用是套接字对象需要的地址格式需要这些套接字协议族进行定义。

- **socket.AF_INET**           IPv4协议
- **socket.AF_INET6**          IPv6协议
- **socket.AF_UNIX**           unix系统中的进程间通信
- **socket.SOCK_STREAM**       TCP协议
- **socket.SOCK_DGRAM**        UDP协议
- **socket.SOCK_RAW**          原始套接字
- **socket.SOCK_SEQPACKET**    可靠的连续数据包

基本函数

- socket.socket()          创建套接字
- socket.bind()            绑定地址和端口号
- socket.sendto()          发送数据
- socket.recvfrom()        接收数据
- socket.close()           关闭套接字

socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)

  • family: 地址族; type: 套接字类型; proto: 协议号; fileno: 指定文件;

创建一个套接字。其中可选参数详细解释如下:

- family: 选择一个地址族,可选地址族有:AF_INET(默认值), AF_INET6, AF_UNIX, AF_CAN, AF_PACKET, AF_RDS 
- type: 选择一个协议族, 可选协议族有:SOCK_STREAM, SOCK_DGRAM, SOCK_RAM 或其他 SOCK_ 前缀的常量
- proto: 协议号,通常为0,使用AF_CAN协议族时需要填写协议号(CAN_RAW, CAN_BCM, CAN_ISOTP, CAN_J1939)
- fileno: 从指定文件的文件描述符中获取 family, type, proto的值(此功能基本可以忽略)

socket.bind(address)

  • address: 套接字地址;

将套接字绑定到地址上。进行此操作的套接字必须未绑定过地址。套接字地址的格式取决于地址族的格式要求。如 AF_INET 是二元元组 (host, port)

socket.sendto(bytes, address) socket.sendto(bytes, flags, address)

  • bytes: 二进制数据; flags: 从套接字中接收的数据; address: 目标套接字地址

发送数据给套接字,此套接字不能是远程套接字。返回已发送字节数。目标套接字地址的格式取决于地址族的格式要求。如 AF_INET 是二元元组 (host, port)

socket.recvfrom(bufsize[, flags])

  • bufsize: 最大可接收字节数; flags: 从套接字中接收的数据;

从套接字中接收数据,返回一个二元元组(bytes, address),第一个元素是数据,第二个元素是发送方套接字地址,此返回值的格式通用取决于地址族的格式要求。

socket.close(fd)

关闭套接字对象。

socket使用范例

socket的使用流程就是创建,使用,关闭。基本与文件的使用流程相似。下面的例子是创建一个TCP协议的套接字:

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 创建一个TCP协议的套接字
# 正常使用套接字,省略...
s.close()  # 关闭套接字

使用UDP协议在本机上进行发送,接收操作:

**文件1     UDP发送.py**
import socket

# 创建套接字,并使用IPv4地址族与UDP协议
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp_socket.bind(('', 7777))  # 绑定IP地址为本机,端口号为7777

# 无限输入发送数据,如果输入 exit则会退出
while True: 
    data = input('请输入发送内容:')
    if data == 'exit':
        break
    # 向本机的7778端口发送数据,数据编码格式为utf-8
    udp_socket.sendto(data.encode('utf-8'), ('127.0.0.1', 7778))

# 关闭套接字,程序结束
udp_socket.close()


**文件2     UDP接收.py**
import socket

# 创建套接字,并使用IPv4地址族与UDP协议
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp_socket.bind(('', 7778))  # 绑定IP地址为本机,端口号为7777

# 无限接收数据
while True:
    # 接收数据,最大可接收1024字节的数据,这是一个阻塞函数,也就是说如果没有数据接收,此程序将一直卡在这个位置
    data = udp_socket.recvfrom(1024)
    # 打印数据,获取的数据格式为 (数据, (IP, 端口号)),其中端口号是数字类型
    print('收到来自%s:%s的消息:%s' % (data[1][0], data[1][1], data[0].decode('utf-8')))

# 关闭套接字,程序结束
udp_socket.close()

运行以下两个程序,并进行操作:

> UDP发送.py
请输入发送内容:hello world
请输入发送内容:中文测试
请输入发送内容:1
请输入发送内容:exit

> UDP接收.py
收到来自127.0.0.1:7777的消息:hello world
收到来自127.0.0.1:7777的消息:中文测试
收到来自127.0.0.1:7777的消息:1