7.1 什么是socket?
我们再往深挖一点。首先我们学会了操作request
,然后是http.client
,再后来是代理。那么接下来呢?接下来我们看看这些库的底层...
Socket(字面意思——插座)——是网络中的节点,通过它数据发送和接收。可以把Socket看作是两个程序之间通信的终端点,可以在同一台机器上运行,也可以在不同机器上。
Socket支持多种网络协议,但最常用的是两种:
-
TCP
(Transmission Control Protocol):可靠的协议,提供连接建立、数据完整性检查及其正确顺序。 -
UDP
(User Datagram Protocol):非连接导向协议,不保证数据传输,但在某些应用程序中更快、更高效。
为了识别Socket,使用IP地址(识别网络中的设备)和端口(识别设备上的应用程序或服务)。
重要!
IP地址和端口唯一标识网络中的程序。就像家庭地址和公寓号。家庭地址(IP地址)是计算机在网络中的地址,而端口是程序接收和发送消息的公寓号。
更详细的信息关于IP地址和端口的可以在专门讲解网络构造的讲座中找到。
使用Socket的主要步骤:
- 创建Socket:程序创建Socket,指定协议类型(TCP或UDP)。
- 绑定地址:Socket绑定到IP地址和端口,以便于连接或发送/接收数据。
-
监听和建立连接(对TCP):
- 监听:服务器端的Socket进入监听模式,等待传入连接。
- 建立连接:客户端发起与服务器的连接。服务器接受连接,创建新Socket来与客户端互动。
- 数据交换:客户端和服务器之间交换数据。对于TCP,数据是以可靠的顺序传输的。
- 关闭连接:数据交换完成后关闭连接。
使用Socket的优点:
- 灵活性:Socket允许应用程序进行数据交换,无论其位置和平台。
- 性能:Socket提供了一种快速且有效的数据传输方式,尤其是在使用UDP的情况下。
- 可靠性(对于TCP):TCP协议确保数据的可靠传输,并进行完整性检查及丢失包恢复。
7.2 创建Socket服务器
通过Python中的内建模块socket
可以操作Socket,它提供了低级网络编程的接口。
借助Socket可以创建socket服务器
——应用程序/对象,用于接收客户端请求并回应它们。以及socket客户端
——应用程序/对象,用于向socket服务器
发送请求并接收响应。
要创建一个socket服务器
,需要完成三个步骤:
- 创建socket服务器对象。
- 绑定(
bind
)到某个IP和端口。 - 开启监听模式(
listen
)接收传入消息。
代码看起来大概是这样:
import socket
# 创建socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定socket到地址和端口
server_socket.bind(('localhost', 12345))
# 监听传入连接
server_socket.listen(5)
print("服务器等待连接中...")
这里socket.AF_INET
表示我们使用IPv4进行网络协议,而socket.SOCK_STREAM
表示我们使用TCP。这些参数最常用于创建网络应用程序。
收到传入消息后,还需要做四件事:
- 与客户端建立
(accept)
连接。 - 从客户端接收
(receive)
请求(数据)。 - 发送
(send)
响应给客户端——也是一些数据。 - 关闭
(close)
连接。
代码看起来大概是这样:
# 接受新连接
client_socket, client_address = server_socket.accept()
print(f"已经与{client_address}建立连接")
# 从客户端接收数据
data = client_socket.recv(1024)
print(f"接收到: {data.decode('utf-8')}")
# 发送数据给客户端
client_socket.sendall(b'Hello, client!')
# 关闭与客户端的连接
client_socket.close()
使用sendall()
而不是send()
,因为它能确保所有数据被发送。send()
可能只发送部分数据,如果缓冲区已满。
数字1024在recv(1024)
中指示一次可以接收的最大字节数。这有助于控制单次操作处理的数据量。
最后一个例子的代码通常在一个无限循环中执行——服务器处理请求,等待下一个,然后再处理,如此循环。
如果你想在自己机器上运行或想看看完整示例,可以参考以下代码:
import socket
# 创建socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定socket到地址和端口
server_socket.bind(('localhost', 12345))
# 监听传入连接
server_socket.listen(5)
print("服务器等待连接中...")
while True:
# 接受新连接
client_socket, client_address = server_socket.accept()
print(f"已经与{client_address}建立连接")
# 从客户端接收数据
data = client_socket.recv(1024)
print(f"接收到: {data.decode('utf-8')}")
# 发送数据给客户端
client_socket.sendall(b'Hello, client!')
# 关闭与客户端的连接
client_socket.close()
7.3 创建Socket客户端
我们已经创建了Socket服务器,现在让我们编写自己的Socket客户端,它将与服务器通信并接收到来自服务器的数据作为响应。
为此需要完成五个步骤:
- 创建
socket客户端
对象。 - 与我们
socket服务器
的IP地址和端口建立连接(connect)
。 - 向服务器发送
(send)
消息。 - 从服务器接收
(receive)
数据。 - 关闭
(close)
连接。
实际上,这比听起来简单。代码如下:
import socket
# 创建socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 与服务器建立连接
client_socket.connect(('localhost', 12345))
# 向服务器发送数据
client_socket.sendall(b'Hello, server!')
# 从服务器接收数据
data = client_socket.recv(1024)
print(f"从服务器接收到: {data.decode('utf-8')}")
# 关闭socket
client_socket.close()
如果那边没有启动socket服务器
或者连接中断,将会引发socket.error
异常。所以不要忘记处理异常。
今天我们就到这里,结束Socket的操作了。
在进行任何网络操作时,主机、端口、IP地址、连接建立、请求监听等等会一再出现。因此,理解它们在底层的工作原理会大大简化你的生活,并帮助你将零散的知识拼接成一幅完整的画面。
GO TO FULL VERSION