1 简介
Python 提供两个级别的服务:
- Socket(低级别)
- SocketServer(高级别)
什么是 Socket?俗称「套接字」,对 TCP 协议的抽象,可以用于主机之间或者进程之间的通信。
首先用一个简单实例来了解 socket 创建、连接、通信的基本步骤。server 端的基本步骤:
- 绑定 hostname、port
- 使用 accept 方法进行等待
- 将消息发送给 client 端
# 引入模块
import socket
import sys
# 创建socket对象,套接字家族选用AF_INET,套接字类型选用面向连接。
server_socket = socket.socket(
family=socket.AF_INET,
type=socket.SOCK_STREAM
)
# 获取本机主机名:MacBook-Pro.local
host = socket.gethostname()
port = 9999
# 绑定端口号
server_socket.bind((host, port))
# 设置最大连接数,超过后排队
server_socket.listen(5)
while True:
# 建立客户端连接
client_socket, addr = server_socket.accept()
print(f'连接地址:{addr}')
message = 'Hello world, socket!'
client_socket.send(
message.encode('UTF-8')
)
client_socket.close()
client端的基本步骤:
- 指定 hostname、port 连接到服务
- 接受消息
import socket
import sys
# 创建socket对象
s = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
# 获取本机名,设置端口号
hostname = socket.gethostname()
port = 9999
# 连接到服务
s.connect(
(hostname, port)
)
# 接受消息
message = s.recv(1024)
print(message.decode('UTF-8'))
2 端口
一个套接字只是用户程序和内核信息交互的枢纽,他自身没有太多信息,也没有网络协议和端口号。在进行网络通信时,必须把一个套接字和一个地址相关联,这个过程就是地址绑定的过程。
许多时候内核会自动绑定一个地址,然而很多时候为了方便记忆和管理,都会进行手动绑定。最典型的情况就是服务器进程绑定一个端口,等待其他的进程进行连接。
下面进行简单的验证,server端的代码:
# 引入模块
import socket
import sys
# 创建socket对象,套接字家族选用AF_INET,套接字类型选用面向连接。
server_socket = socket.socket(
family=socket.AF_INET,
type=socket.SOCK_STREAM
)
# 获取本机主机名:MacBook-Pro.local
host = socket.gethostname()
port = 9999
# 绑定端口号
server_socket.bind((host, port))
# 设置最大连接数,超过后排队
server_socket.listen(5)
count = 0
while True:
# 建立客户端连接
client_socket, addr = server_socket.accept()
count += 1
print(f'连接地址:{addr}')
print(count)
message = 'Hello world, socket!'
client_socket.send(
message.encode('UTF-8')
)
client_socket.close()
每次连接之后都会输出对方的 IP 和端口,这样就能比较清晰的观察端口的变化。
client端(未绑定固定的端口)
import socket
import sys
# 创建socket对象
s = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
# 获取本机名,设置端口号
hostname = socket.gethostname()
port = 9999
# 连接到服务
s.connect(
(hostname, port)
)
# 接受消息
message = s.recv(1024)
print(message.decode('UTF-8'))
首先启动server端,然后启动client端,就可以看到client端回显下面的字母:Hello world, socket!
多次运行之后就能清楚的发现client.py的端口在发生变化,说明其端口是由系统自动分配的。
可以考虑手动绑定端口,让ip的端口固定为自己想要的端口,在 connect 之前执行如下代码即可。
s.bind(
(hostname, 59446)
)
最后代码为:
import socket
import sys
# 创建socket对象
s = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
# 获取本机名,设置端口号
hostname = socket.gethostname()
port = 9999
# 连接到服务
s.bind(
(hostname, 59446)
)
s.connect(
(hostname, port)
)
# 接受消息
message = s.recv(1024)
print(message.decode('UTF-8'))
可以发现自己手动绑定端口之后,端口固定不变
结果正如上文所说,如果不绑定端口,系统则会自动分配端口。
附录
参考教程:
- Python3 网络编程:https://www.runoob.com/python3/python3-socket.html
- 网络编程socket之bind函数:https://blog.csdn.net/dongliqiang2006/article/details/5824651