# 网络编程
# socket
又称套接字,程序通过其向网络发出或者应答请求,也可以用户主机间或者进程间的通讯
创建
socket.socket([family[, type[, proto]]]) | |
#都是可选值,family 默认 AF_INET |
family:
套接字家族,可以是 AF_UNIX 或者 AF_INET (6)
前者表示进程间通信,后者表示使用 IPv4 (6)
type:
类型,面向连接 SOCK_STREAM (默认值); 非连接 SOCK_DGRAM
前者是流式套接字,对应 TCP 协议,或者是数据报套接字,对应 UDP
proto:
协议号。一般不填,默认为 0,表示自动匹配。这个值取决于前两个值
当使用 AF_INET 以及 SOCK_RAW(原始套接字,需要 root 权限)时才需指定。
存在:IPPROTO_TCP(6)
IPPROTO_UDP(17)
IPPROTO_ICMP(1)
IPPROTO_IP(0)ICMP 可以用于处理 ping 命令时
内建方法
服务端 | |
s.bind() | |
#绑定地址到套接字,在 AF_INET 下时元组形式保存(host,port) | |
s.listen() | |
#TCP 监听。只有在转为监听后才能 accept | |
s.accept() | |
#被动接受 | |
-------------------- | |
客户端 | |
s.connect() | |
#主动初始化 TCP 服务连接,一般格式是元组(hostname,port) | |
s.connect_ex() | |
#上一个的扩展,遇到错误不抛异常,而是返回出错码,没有错误返回 0 | |
-------------------- | |
公用 | |
s.recv() | |
#接受 TCP 数据 | |
s.send() | |
s.sendall() | |
s.recvfrom() | |
#接受 UDP 数据 | |
s.sendto() | |
#发送 UDP 数据 | |
s.close() | |
#关闭套接字 | |
s.getpeername() | |
#返回连接的远程地址,元组(ipaddr,port) | |
s.getsockname() | |
#返回套接字自己的地址,元组(ipaddr,port) |
10061/111:connect refused
10060: time out
# 实例
import socket | |
import sys | |
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
host = socket.gethostname() | |
port = 9999 | |
serversocket.bind((host, port)) | |
# 设置最大连接数,超过后排队 | |
serversocket.listen(5) | |
while True: | |
# 建立客户端连接 | |
clientsocket,addr = serversocket.accept() | |
print("连接地址: %s" % str(addr)) | |
msg='欢迎访问菜鸟教程!'+ "\r\n" | |
clientsocket.send(msg.encode('utf-8')) | |
clientsocket.close() |
可能不是那么重要的:
s.setblocking(True/False) | |
#默认为 True,阻塞模式,send/recv/accept 都要等待返回才继续执行,非阻塞反之 | |
#非阻塞中,若操作无法完成,会报错 socket.error | |
s.setsockopt(level,optname,value) | |
#设置给定套接字选项的值 | |
s.getsockopt(level,optname[.buflen]) | |
#返回套接字选项的值 |
level
选项所属协议层级,指定对什么类型的套接字生效,SOL_SOCKET 表示所有
此外就是 IPPROTO_TCP 一类的optname
选项名称,是 socket 模块定义的常量。包括 SO_REUSEADDR(端口重用)等value
选项值,整数(一般是 1/0,表示开启关闭)或者字节流
选项:
SO_REUSEADDR
通过 fork 子进程来继承 socket,实现多个进程共用一个 socketSO_REUSEPORT
通过多个 socket 共用一个端口实现,可以多个进程同时监听使用,而不是同一时间能有一个,这些进程必须有相同的 euid(有效用户 id)和 uidtip: 有配置 SUID 的文件在运行时会强制 euid 为文件所有者,需要注意