Socket模块
Python的标准库中提供了许多用于网络编程的模块,包括socket、urllib、http等。其中,socket也称“套接字”,是用于实现网络通信的基础模块,可以通过TCP和UDP等协议实现不同主机进程间的数据传输和网络通信。
socket模块允许程序在网络上进行通信,它提供了一种统一的网络通信接口,用于在不同平台上的计算机之间传递数据。在Python中,socket模块封装了操作系统提供的底层网络接口,提供了简单而强大的套接字(socket)接口,来创建网络连接、发送和接收数据,以及处理网络通信。
1、socket通信原理
socket是网络连接端点。例如当你的Web浏览器请求www.pyhint.com上的主页时,你的Web浏览器会创建一个socket并命令它去连接www.pyhint.com的Web服务器主机,Web服务器也对来自的请求在一个socket上进行监听。两端使用各自的socket来发送和接收信息。
当两个程序间传送信息的时候,通常会选择TCP或UDP协议。TCP协议会在两端间建立一个持续的连接,并且你所发送的信息有保证的按顺序到达它们的目的地。UDP协议不建立连接,它的速度快但不可靠。你发送的信息也可能到不了另一端;或它们没有按顺序到达。有时候即便你只发送了一次信息,该信息的多个复制信息也有可能到达接收端。
2、创建Socket
Socket模块提供了socket()函数,用于创建一个新的套接字。要在网络上进行通信,首先需要创建一个Socket对象来建立网络连接,例如:
动手练一练:
import socket
# 创建Socket对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
上面的例子中,我们创建了一个Socket对象,第一个参数指定了地址族为IPv4(socket.AF_INET),第二个参数指定了传输协议为TCP(socket.SOCK_STREAM)。这是一种常见的配置,适用于大多数网络通信场景。
其中,第一个参数指定了要使用的地址族,以下是常用的协议族:
地址族类型 | 描述 |
---|---|
socket.AF_INET | 使用IPv4协议(默认) |
socket.AF_INET6 | 使用IPv6协议 |
socket.AF_UNIX | 只能够用于单一的Unix系统进程间通信 |
第二个参数用来指明Socket类型,以下是常用的类型:
参数 | 类型 | 作用 |
---|---|---|
socket.SOCK_STREAM | TCP(默认) | 保证数据顺序及可靠性 |
socket.SOCK_DGRAM | UDP | 不保证数据接收的顺序,非可靠连接 |
socket.SOCK_RAW | 原始类型 | 允许对底层协议如IP或ICMP进行直接访问 |
socket.SOCK_RDM | 可靠的UDP形式 | 是一种可靠的UDP形式,即保证交付数据报但不保证顺序 |
socket.SOCK_SEQPACKET | 序列包 | 可靠的连续数据包服务 |
创建一个TCP套接字socket.socket()相当于socket.socket(socket.AF_INET,socket.SOCK_STREAM),因为“socket.AF_INET”和“socket.SOCK_STREAM”都是默认值,所以可以省略。
3、Socket常用函数
Socket类中主要提供如下所示常用的函数:
函数 | 作用 |
---|---|
bind() | 绑定地址(ip地址,端口)到套接字,参数必须是元组的格式例如:bind(('127.0.0.1',8080)) |
listen() | 监听所有socket对象创建的连接,并指定服务端可以监听的最大数量,这个参数最小为1,一般为5 |
accept() | 接收来自客户端的数据,返回一个新的socket对象和客户端地址 |
connect() | 连接服务器端,参数必须是元组格式例如:connect(('127,0.0.1',8080) |
connect_ex() | connect()函数的扩展版本,出错时返回出错码,而不是抛出异常 |
send() | 发送TCP数据,向已经连接的socket发送数据 |
recv() | 接收TCP数据,括号内传入的参数为一次数据接收的大小,例如recv(1024) |
sendto() | 可以向一个未连接的socket发送数据 |
sendall | 与send不同的是将会一直发送完全部数据 |
recvfrom() | 返回所接收的字符串和地址 |
close() | 完成通信后,应使用close方法关闭网络连接 |
makefile() | 创建一个与该套接字相关联的文件 |
gethostbyname() | 将主机名转换为IP地址 |
gethostname() | 获取本地主机名 |
4、Socket模块通过TCP协议实现简单的网络通信
TCP传输控制协议 (英语:Transmission Control Protocol,缩写为TCP) 是一种面向连接的、可靠的、基于字节流的传输层通信协议。TCP协议会在通信两端间建立一个持续的连接,并且所发送的信息有保证的按顺序到达它们的目的地。
Socket模块通过TCP协议可以实现不同计算机之间的通信,完成数据的发送和接收。下面是一个简单的示例,该示例演示了如何使用Socket模块创建一个服务器端和客户端。
(1)服务器端(server.py)
首先,我们创建一个服务器端程序。打开第2章【安装和运行Python】教程里面介绍的Pyhint编辑器,在Pyhint\Learn-Python\test文件夹下面新建一个文件server.py,输入以下内容并保存,然后点击Pyhint编辑器上面的“打开终端”按钮,在弹出的黑色cmd终端窗口中输人“python server.py”并按下Enter回车键即可打开服务器端程序,最后等待客户端的连接请求(注意:不要关闭cmd终端窗口)。
server.py:
import socket
# 创建一个socket对象
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定主机名和端口号
server.bind(("127.0.0.1", 9999))
# 设置最大连接数,超过后排队
server.listen(5)
# 建立客户端连接
client, addr = server.accept()
print("客户端ip地址为:%s 端口号为:%s" % addr)
# 向客户端发送一些数据
b = "这是server.py服务器端发送的数据" + "\r\n"
client.send(b.encode("utf-8"))
# 接收客户端发来的消息,a为bytes类型的数据
a = client.recv(1024)
# 将bytes类型数据转换成str字符型的数据,以utf-8的形式
print(a.decode("utf-8"))
# 关闭连接
client.close()
上面的例子中,服务器端程序使用Socket模块创建了一个Socket对象,并且需要绑定到本地的IP地址和端口,然后等待客户端的连接请求。当有客户端请求连接时,服务器会接受这个连接,然后就可以在服务器和客户端之间进行通信了。
(2)客户端(client.py)
接着,我们创建一个客户端程序。同样打开Pyhint编辑器,在Pyhint\Learn-Python\test文件夹下面新建一个文件client.py,输入以下内容并保存,然后再次点击Pyhint编辑器上面的“打开终端”按钮,在弹出的黑色cmd终端窗口中输人“python client.py”并按下Enter回车键即可打开客户端程序。这个时候,客户端程序就会向服务器端程序发送连接请求,服务器端程序接受连接请求后,同样会发送一条信息给客户端,最后关闭这个连接。
client.py:
import socket
# 创建一个socket对象
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 连接服务,指定主机和端口号
client.connect(("127.0.0.1", 9999))
# 一次接收小于1024字节数的数据
a = client.recv(1024)
# 将bytes类型数据转换成str字符型的数据,以utf-8的形式
print(a.decode("utf-8"))
# 向服务器端发送一些数据,并转换成bytes类型的数据
client.send("这是client.py客户端发送的数据".encode("utf-8"))
# 关闭连接
client.close()
上面的例子中,客户端同样使用Socket模块创建了一个Socket对象,并连接到服务器端指定的地址和端口,最后向服务器端发送连接请求。一旦连接建立,客户端程序和服务器端程序就可以相互发送数据。