socket是什么?

socket–Berkeley Socket,俗称套接字,实质是一套应用程序API(编程接口,对TCP/IP协议的封装,传输层/网络层协议,http是应用层协议)。主要功能是实现进程间通信,在网络通信中广泛应用。

socket 的常见 api

普通的 socket 编程

# file: server.py

import socket
import select

# 创建socket, 使用ipv4协议(AF_INET), 流式协议
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("127.0.0.1", 64300))  # 绑定端口
server.listen(5)  # 最大可支持5个客户端连接

print("server start ...")

while True:
    # 接收连接并返回一个新的socket
    # 当没有连接时将会阻塞在这里
    conn, address = server.accept()
    conn.send(b"Welcome to test server! \\n")
    while True:
        data = conn.recv(128)
        if not data:
            print("client disconnect")
            conn.close()
            break
        else:
            print(data) 
# file: client.py

import socket

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
    client.connect(("127.0.0.1", 64300))
except:
    print("client connect fail")
    raise ConnectionError

print("client connect")
client.send(b"Hello !")
data = client.recv(128)
if data:
    print(data)

client.close()
print("client disconnect") 

这里是最简单的一个socket编程示例,服务器启动之后阻塞在accept中等待连接,此时启动客户端往服务器建立连接并发送了一条消息,并获取来自服务器的返回,这里是双工通道(读和写互不影响,数据会被放在各自的缓冲区),之后关闭连接,随后服务器发现再也读取不到数据也关闭连接。

不过这里的服务器是阻塞式的,假设客户端A在建立连接之后不会立马退出,此时启动另一个客户端B,可以看到服务器端此时仍在内层循环循环读取A的数据,保持与A的通信,从而导致必须等到客户端A的连接关闭之后,客户端B的连接才能建立。也就是说一次只能有一个连接存在。

借助 select 完成多客户连接

从上面的例子可以看出来,阻塞式的服务器无法满足多个客户端连接的需求,我们可以借助python中的select模块来实现多客户连接。