Python网络编程入门:Socket基础、通信流程与代码实现

栗子
栗子
发布时间:2026-10-15 | 2人浏览过
原创

本文详解Python网络编程基础,涵盖Socket库的核心语法、常用函数及通信流程。通过服务端与客户端的交互示例,演示如何绑定IP端口、建立连接、收发数据,并逐步实现通信循环与多客户端并发处理,帮助开发者掌握Python网络编程的核心技能。

一、什么是网络编程

网络编程涉及计算机基础理论与操作系统差异。由于示例基于Windows环境,后续内容均适用于Windows系统,且需注意Windows与macOS在字符编码上的区别。本文首先实现简单的服务端发送、客户端接收功能,后续将扩展至模拟SSH远程命令处理及粘包问题,最终实现文件下载功能。

网络编程的核心理论包括网络基础与五层协议模型。这些理论解释了文件在客户端与服务端之间的传输机制及接收过程。本质上,这是客户端(接收方)与服务端(发送方)之间的交互过程。建议读者结合专业教程深入理解,但无论细节如何,核心始终在于建立这种交互连接。

二、Socket套接字

Python的强大功能很大程度上得益于丰富的第三方库,其中Socket(套接字)库是实现网络通信的关键。专业而言,应用程序通过“套接字”向网络发出请求或应答,从而实现主机间或同一计算机上进程间的通信。利用Socket库,即可实现前文所述的客户端与服务端交互。

1. Socket的基本语法

socket(family,type,[protocol])

创建Socket时,family参数有三种可选值。

socket.AF_UNIX 仅适用于单一Unix系统进程间通信。

socket.AF_INET 用于服务器之间的网络通信。

socket.AF_INET6 IPv6

type参数同样有三种选项。

socket.SOCK_STREAM 流式Socket,使用TCP协议时选择此项。

socket.SOCK_DGRAM数据报式Socket,使用UDP协议时选择此项。

socket.SOCK_RAW 原始套接字。普通套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;此外,SOCK_RAW也能处理特殊的IPv4报文。利用原始套接字,可通过IP_HDRINCL选项由用户构造IP头。

protocol参数指明接收的协议类型,通常为0或不填,一般无需设置。

2. 与Socket相关的常用函数

服务端相关函数

address通常指本机IP地址,可通过Windows命令提示符输入ipconfig命令查看IPv4地址获取。

s.bind(address)将套接字绑定到地址。在客户端程序中,需绑定IP和端口才能实现交互。

s.listen(backlog)设置操作系统允许挂起的最大连接数量,即服务端最多能处理的并发连接数。

s.accept()接受TCP连接并返回(conn, address)。其中conn是新的套接字对象,用于接收和发送数据;address是连接客户端的地址。

客户端相关函数

s.connect(address)连接到指定address处的套接字。

s.recv(bufsize)接收TCP套接字的数据。数据以字符串形式返回,bufsize指定接收的最大数据量。

公共函数

s.send(string)

发送TCP数据。将string中的数据发送到连接的套接字,返回值为实际发送的字节数,可能小于string的字节大小。

s.sendall(string)

完整发送TCP数据。将string中的数据发送到连接的套接字,在返回前会尝试发送所有数据。成功返回None,失败则抛出异常。

s.recvfrom(bufsize)

接收UDP套接字的数据。与recv()类似,但返回值为(data, address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。

s.sendto(string,address)

发送UDP数据。将数据发送到套接字,address为(ipaddr, port)形式的元组,指定远程地址。返回值为发送的字节数。

s.close()

关闭套接字。

三、程序需求分析

网络交互可类比生活中的打电话:发送数据相当于拨号,接收数据相当于接听。由此区分服务端和客户端,以下场景将演示这种交互过程。

服务端分析

要实现数据发送,首先需引入Socket库。服务端需执行一系列绑定操作,利用前述函数实现。具体流程包括:模拟手机(引入Socket)、绑定IP端口(插卡)、开机监听、等待连接、收发消息及挂断电话。

注意事项:

1. 绑定操作前,需通过命令提示符输入ipconfig命令获取本机IPv4地址。

2. 绑定地址时需指定端口号,端口号可任意选择,但若被占用需更换其他端口。

3. 在接收消息后,可使用upper()函数将客户端发送的数据转换为大写后返回给客户端。

4. 客户端使用accept()接收TCP连接并返回(conn, address)。

--------------------------------服务端----------------------
import socket
#1.买手机
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# print(phone)         #测试你的手机
 
#2.插卡 绑定手机卡
phone.bind(("192.168.2.18",3234))
 
#3.开机
phone.listen(5)   #5代表最大挂起的连接数
 
#4.等电话链接
print("starting")
conn,client_add = phone.accept()
 
# 5.收发消息
data=conn.recv(1024)         #1024代表接收数据的最大数,单位是bits
print("客户端数据",data)
 
conn.send(data.upper())
 
#6.挂电话
conn.close()
 
#7.关机
phone.close()

客户端分析

服务端与客户端是一一对应的。在收发消息环节,客户端发送小写“hello”,服务端则返回大写“HELLO”。

-------------------------------客户端-----------------------------
import socket
#1.买手机
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# print(phone)
 
#2.拨号
phone.connect(("192.168.2.18",3234))
 
#3.发收消息
 
phone.send("hells".encode("utf"))
data=phone.recv(1024)
print(data)
 
 
phone.close()

四、代码升级与优化

加入通信循环

前述代码仅实现固定收发,功能过于简单。为实现客户端与服务端之间的循环通信及自定义内容交互,需加入输入处理与循环逻辑。

----------------------------服务端------------------------
import socket
 
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# print(phone)
phone.bind(("172.20.10.4",3234))
phone.listen(5)   print("starting")
conn,client_add = phone.accept()
print(client_add)
 
while True:
    data=conn.recv(1024)        
    print("客户端数据",data)
 
    conn.send(data.upper())
 
conn.close()
phone.close()
----------------------------------客户端------------------------
import socket
 
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# print(phone)
phone.connect(("172.20.10.4",3234))
 
while True:
    msg = input(">>>:").strip()
    phone.send(msg.encode("utf-8"))
    data=phone.recv(1024)
    print(data)
 
phone.close()

如前所述,我们在客户端加入了循环输入功能。在服务端加入相应循环后,即可实现持续的循环输入与响应。

加入连接循环及完善处理

之前的程序是一个客户端对应一个服务端。实际应用中,服务端应能同时处理多个客户端的数据收发。主要修改服务端代码,客户端代码变化不大,仅需增加数据发送判断。

1. 由于未学习并发编程,代码通过循环实现:服务端接收完一个客户端数据后,可继续接收另一个客户端的数据。

2. 增加一行代码判断端口是否被占用,以减少错误发生。

3. 增加客户端后,需判断是否需要接收其他客户端的数据,或多客户端是否都发送了数据。因此,需使用try和except进行异常处理与判断。

--------------------------------服务端-----------------------
import socket
 
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)  #判断接口是否被占用
phone.bind(("172.20.10.4",3234))
phone.listen(5)   
print("starting")
while True:       #没有学习并发编程 没办法执行代码后返回到这继续执行,所以用循环解决
    conn,client_add = phone.accept()
    print(client_add)
    while True:
        try:
            data=conn.recv(1024)         
            if not data:break         
            print("客户端数据",data)
            conn.send(data.upper())
        except ConnectionResetError :
            break
            conn.close()
phone.close()
-----------------客户端1-----------------
import socket
 
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(("172.20.10.4",3234))
 
while True:
    msg = input(">>>:").strip()
    if not msg: continue          #若输入空则继续循环
    phone.send(msg.encode("utf-8"))
    # print("if send none")
    data=phone.recv(1024)
    print(data)
    # print(data.decode("utf-8"))
 
phone.close()
-----------------------------客户端2---------------------
import socket
 
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(("172.20.10.4",3234))
 
while True:
    msg = input(">>>:").strip()
    if not msg: continue          #若输入空则继续循环
    phone.send(msg.encode("utf-8"))
    # print("if send none")
    data=phone.recv(1024)
    print(data)
    # print(data.decode("utf-8"))
 
phone.close()

总结

本文到此结束,希望能对您有所帮助。欢迎继续关注本站获取更多内容!

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表