socket源码
socket源代码位置:
python安装根目录/Lib/socket.py
导入_socket模块,socket类继承_socket.socket,
模块_socket的位置:
python安装根目录/DLLs/_socket.pyd
什么是.pyd文件?见下面链接:
http://www.malaoshi.top/show_1EF2Zg2nxB6r.html
socket 接口说明
导入socket模块
import socket
创建socket对象
socket编程中,无论实现服务器端还是客户端,首先要创建socket对象,然后才能进行操作
支持with语句
语法
socket([family], [type], [proto])
参数说明:
family:套接字家族,有三个值
- socket.AF_INET 使用IPv4(默认)。是Address Family Internet缩写
- socket.AF_INET6 使用IPv6
- socket.AF_UNIX 只用于单一的Unix系统进程间通信
type:套接字类型,有五个值:
- socket.SOCK_STREAM:流式socket , 即TCP (默认)
- socket.SOCK_DGRAM:数据报式socket ,即UDP。是socket_datagram缩写
- socket.SOCK_RAW 原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。
- socket.SOCK_RDM 是一种可靠的UDP形式,即保证交付数据报但不保证顺序。SOCK_RAM用来提供对原始协议的低级访问,在需要执行某些特殊操作时使用,如发送ICMP报文。SOCK_RAM通常仅限于高级用户或管理员运行的程序使用。
- socket.SOCK_SEQPACKET 可靠的连续数据包服务
protocol:协议。默认是0,与特定的套接字家族相关的协议,如果是 0 ,则系统就会根据地址格式和套接类别,自动选择一个合适的协议
例子
udp=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
支持with语句
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as udp:
pass
绑定地址、端口
接收端 创建socket对象后,将套接字绑定本机 网卡IP地址 和 端口号。地址格式取决于套接字族。
绑定本机端口号,一个端口号只能被一个进程绑定,当操作系统底层接收到数据后,通过识别 端口号,将数据 发送给相应的进程发送端 绑定本机地址和端口号后,使用该指定的 端口号 发送数据
语法
bind(address)
参数:
- address:在AF_INET下(即IPv4),以元组(ipaddr,port)的形式表示地址,ipaddr是本机网卡ip地址,port是本机要绑定该网卡的端口号
当有 多个网卡时,要绑定所有网卡,ip地址可设置成"0.0.0.0"
例子
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as udp:
# 绑定本机所有网卡的9999端口号
s.bind(('0.0.0.0', 9999))
绑定IP地址0.0.0.0,端口号是9999
关于IP地址0.0.0.0,见下面链接:
http://www.malaoshi.top/show_1EF2SXCO6P0v.html
或者
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as udp:
s.bind(('', 9999))#ip可空,同0.0.0.0
注意:
端口不能重复绑定,端口只能被一个进程绑定,同时执行2次本文开始处的接收端程序,会提示错误,如下:
OSError: [WinError 10048] 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。
原因:
假设一个端口可以被多个进程绑定,当操作系统接收到数据后,不知道发给哪个进程
接收UDP数据
接收UDP数据,执行本代码会 阻塞,直到接收数据为止。执行此方法前必须先执行bind()绑定
注意:
由于此方法会阻塞,所以在单线程的程序中,执行此方法后,程序将 不会执行其他操作
语法
s.recvfrom(buffersize)
参数
buffersize:接收数据的长度
返回值
返回值是tuple类型,如:(data,address)。其中data是包含接收数据的字符串,address是 发送方 的IP地址和端口号
发送UDP数据
语法
s.sendto(data,address)
参数
- data:发送数据,bytes类型
- address:tuple类型,如(ipaddr,port),第一个是接收地址,第二个是端口号
返回值
返回发送数据的长度,单位:byte
关闭套接字
使用后应及时关闭socket,回收资源。服务器端运行结束后,或者调用close()方法,才会释放端口
语法
close()
参数说明:
无
返回值:
无
更多api说明
见:
http://www.runoob.com/python3/python3-socket.html
优化
接收端
上面的接收端代码只能接收一次就结束运行了,通过死循环让其一直接收数据
import socket
udp=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp.bind(('0.0.0.0',8000))
print('绑定本机8000端口,开始接收数据...')
while True:
data,addr=udp.recvfrom(1024)
print('接收来自%s:%d的消息:%s'%(addr[0],addr[1],data.decode('utf-8')))
udp.close()
发送端
在上例中发送端只能发送一次数据,通过死循环让发送端可以一直发送数据
import socket
address=('127.0.0.1',8000)
udp=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
s=input('>')
udp.sendto(s.encode('UTF-8'),address)
udp.close()