Python中的网络编程之Socket模块(第2节)


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对象,并连接到服务器端指定的地址和端口,最后向服务器端发送连接请求。一旦连接建立,客户端程序和服务器端程序就可以相互发送数据。