Python Socket编程实战:从基础连接到对象传输

桃夭
桃夭
发布时间:2026-10-15| 4人浏览过
原创

本文详解Python中的Socket编程,涵盖服务器与客户端的创建、端口绑定、连接监听及数据收发。深入探讨缓冲区大小对传输的影响,演示如何通过循环处理分包数据,并介绍利用Pickle模块实现Python对象在网络间的序列化与反序列化传输。

Why use Sockets?

套接字(Socket)是网络通信的基石,它使得不同程序或设备间的信息传输成为可能。例如,当您打开浏览器时,客户端会与服务器建立连接以进行数据交换。

在深入探讨这种通信机制之前,让我们首先明确套接字的确切定义。

What are Sockets?

一般而言,套接字是用于发送和接收数据的内部端点。单个网络通信涉及两个套接字,分别位于通信的双方设备或程序中。套接字由IP地址和端口号组合而成。根据端口号的不同,单个设备可以拥有多个套接字,不同的端口可用于不同类型的协议。请参阅以下图片,了解常见端口号及其相关协议:

现在您已了解套接字的基本概念,接下来让我们查看Python中的Socket模块。

如何在Python中实现Socket编程:

要在Python中实现Socket编程,首先需要导入socket模块。该模块包含了创建套接字并使其相互关联所需的所有内置方法。

以下是一些关键的方法:

既然您已经了解了Socket模块的重要性,让我们继续查看它如何为Python中的Socket编程创建服务器和客户端。

什么是服务器?

服务器可以是程序、计算机或专门用于管理网络资源的设备。服务器可以位于同一台设备或计算机上,也可以连接到本地其他设备或远程计算机。服务器有多种类型,例如数据库服务器、网络服务器、打印服务器等。

服务器通常使用socket.socket()、socket.bind()、socket.listen()等方法来建立连接并绑定到客户端。现在,让我们编写一个程序来创建服务器。考虑以下示例:

例子:


import socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(),1234))          
#port number can be anything between 0-65535(we usually specify non-previleged ports which are > 1023)
s.listen(5)
 
while True:
    clt,adr=s.accept()
    print(f"Connection to {adr}established")  
   #f string is literal string prefixed with f which 
   #contains python expressions inside braces
    clt.send(bytes("Socket Programming in Python","utf-8 ")) #to send info to clientsocket

如代码所示,创建套接字的第一个必要条件是导入socket模块。随后,使用socket.socket()方法创建服务器端套接字。

NOTE:

AF_INET表示Internet地址族,它需要一对(主机,端口),其中主机可以是特定网站的URL或IP地址,端口号是一个整数。SOCK_STREAM用于创建TCP协议套接字。

bind()方法接受两个参数作为元组(主机,端口)。建议使用4位数的端口号,因为较小的端口号通常被系统保留。listen()方法允许服务器接受连接。这里的5表示同时处于等待状态的连接队列长度。如果提供的值小于1,系统会将其调整为0。如果未指定参数,则使用默认值。

while循环允许服务器无限期地接受连接。“clt”和“adr”分别代表客户端套接字对象和客户端地址。print语句用于打印客户端套接字的地址和端口号。最后,clt.send()用于发送字节数据。

现在我们的服务器已经准备就绪,让我们继续处理客户端部分。

什么是客户端?

客户端是从服务器接收信息或服务的计算机或软件。在客户端-服务器模型中,客户端向服务器请求服务。最好的例子是Web浏览器,如Google Chrome、Firefox等。这些浏览器向Web服务器请求用户指定的网页和服务。其他示例包括在线游戏、在线聊天等。

现在让我们看看如何用Python编程语言编写客户端程序:

例子:


import socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), 2346))
msg=s.recv(1024)
print(msg.decode("utf-8"))

第一步是导入socket模块,然后创建套接字,这与创建服务器时相同。接着,要通过指定(主机,端口)使用connect()方法在客户端和服务器之间建立连接。

注意:当客户端和服务器位于同一台计算机上时,可以使用gethostname()获取本地IP(LAN)或公网IP(WAN)。

在这里,客户端希望从服务器接收一些信息。为此,您需要使用recv()方法,并将接收到的信息存储在变量msg中。请注意,传递的信息将以字节为单位传输。在上述程序的客户端中,一次传输最多可接收1024个字节(缓冲区大小)。您可以指定任意数量,具体取决于传输的信息量。

最后,接收到的消息应进行解码并打印。

既然您已经知道如何创建客户端-服务器程序,让我们继续看看如何执行它们。

Echo Client-Server:

要执行这些程序,请打开命令提示符,进入包含客户端和服务器程序的文件夹,然后键入:

py server.py(在这里,server.py是服务器的文件名,您也可以使用py -3.7 server.py)

完成此操作后,服务器将开始运行。要执行客户端,请打开另一个cmd窗口,然后键入:

py client.py(此处,client.py是客户端的文件名)

输出(服务器):

(客户)

让我们通过将缓冲区大小减小到7来尝试相同的程序,然后看看我们得到什么输出: 输出:

如您所见,连接在传输7个字节后终止。但这是一个问题,因为您尚未收到完整的信息,并且连接已关闭。让我们继续解决这个问题。

Multiple Communications:

为了使连接一直持续到客户端收到完整的信息,可以使用while循环:

例子:


import socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), 2346))
while True:
msg=s.recv(7)
print(msg.decode("utf-8"))

完成此操作后,每次传输将以7个字节的形式接收完整的消息。

但是这一次,如您所见,连接不会终止,您也不知道何时会发生连接。除此之外,如果您实际上不知道客户端将从服务器接收到的消息或信息有多大,该怎么办。在这种情况下,您实际上可以在客户端使用以下代码:

例子:


complete_info=''
while True:
    msg = s.recv(7)  
    if len(msg)<=0:
        break
    complete_info += msg.decode("utf-8")
print(complete_info)

在服务器端,使用close()方法,如下所示:


clt.close()

输出如下图所示:

输出:

上面的代码块所做的全部工作是,检查信息的大小,并一次将其打印在两个字节的缓冲区中,再在完成连接后将其关闭。

传输Python对象:

直到这里,您已经有了传输字符串的技巧。但是,Python中的Socket编程也允许您传输Python对象。这些对象可以是列表、元组、字典等任何对象。要实现此目的,您将需要导入Python的pickle模块。

Python pickle模块:

当您在Python中序列化或反序列化对象时,Python pickle模块便派上用场。让我们看一个小例子,

例子:


import pickle
 
mylist=[1,2,'abc']
mymsg = pickle.dumps(mylist) 
print(mymsg)

输出:

b'x80x03] qx00(Kx01Kx02Xx03x00x00x00abcqx01e。

如您所见,在上面的程序中,使用pickle模块的dumps()函数对'mylist'进行了序列化。还要注意,输出以“b”开头,这意味着它已转换为字节。在Socket编程中,可以实现此模块以在客户端和服务器之间传输Python对象。

如何使用pickle模块传递python对象结构?

当您将pickle与Socket一起使用时,您绝对可以通过网络传输任何内容。让我们写下服务器端和客户端对应项,以将列表从服务器传输到客户端:

服务器端:


import socket
import pickle
 
a=10
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 2133))        #binding tuple
s.listen(5)
while True:
    clt , adr = s.accept()
    print(f"Connection to {adr}established")
 
    m={1:"Client", 2:"Server"}
    mymsg = pickle.dumps(m)  #the msg we want to print later
    mymsg = {len(mymsg):{a}}"utf-8") + mymsg
    clt.send(mymsg)

在这里,m是一个字典,它基本上是一个Python对象,需要从服务器发送到客户端。这是通过首先使用dumps()序列化对象,然后将其转换为字节来完成的。现在让我们写下客户端对应的内容:

客户端:


import socket
import pickle
a=10
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), 2133))
 
while True:
    complete_info = b''
    rec_msg = True
    while True:
        mymsg = s.recv(10)
       if rec_msg:
            print(f"The length of message = {mymsg[:a]}")
            x = int (mymsg[:a ] )
            rec_msg = False
            complete_info += mymsg
            if len(complete_info)-a == x:
            print("Recieved the complete info")
            print(complete_info[a:])
            m = pickle.loads(complete_info[a:])
            print(m)
            rec_msg = True
complete_info = b''
print(complete_info)

第一个while循环将帮助我们跟踪完整消息(complete_info)以及正在使用缓冲区接收的消息(rec_msg)。通过设置rec_msg,然后,在接收消息时,我所做的就是打印每个消息,并在大小为10的缓冲区中接收该消息。此大小可以是任何值,具体取决于您的个人选择。

然后,如果收到的消息等于完整的消息,那么我只是将消息打印为已接收的完整信息,然后使用loads()将消息反序列化。上面程序的输出如下:

到此这篇关于Python中的套接字编程是什么?的文章就介绍到这了,更多相关Python套接字编程内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。