深入解析:【python】python进阶——网络编程

目录

引言

一、 网络编程基础

1.1 什么是网络编程?

1.2 基本概念

二、 Socket编程

2.1 创建Socket

2.2 TCP Socket工作流程

2.3 UDP Socket工作流程

三、高级网络编程框架

3.1 socketserver模块

3.2 异步网络编程

四、简单的聊天应用实现

五、常见问题与解决方案

5.1 端口占用问题

5.2 处理连接中断

5.3 设置超时

附录:Python网络编程API参考

socket模块核心API

Socket对象方法

socketserver模块核心类

asyncio网络编程核心API

select模块核心API

常见常量参数


引言

        网络编程是现代软件开发中不可或缺的一部分,而Python以其简洁的语法和强大的库支持,成为了网络编程的理想选择。

一、 网络编程基础

1.1 什么是网络编程?

        网络编程是指编写能够在网络环境中运行的程序,这些程序可以跨越不同的设备进行通信和数据交换。

1.2 基本概念

  • IP地址:设备的网络标识

  • 端口:应用程序的通信端点(0-65535)

  • 协议:通信规则(TCP、UDP、HTTP等)

  • Socket:网络通信的基础接口

二、 Socket编程

Socket是网络编程的核心,提供了不同主机间进程通信的端点。

2.1 创建Socket

import socket
​
# 创建TCP socket
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
​
# 创建UDP socket
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

参数说明:

  • AF_INET:IPv4地址族

  • SOCK_STREAM:TCP协议

  • SOCK_DGRAM:UDP协议

2.2 TCP Socket工作流程

服务器端:

import socket
​
# 创建TCP socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
​
# 绑定地址和端口
server_socket.bind(('localhost', 8888))
​
# 开始监听
server_socket.listen(5)
print("服务器启动,等待连接...")
​
while True:
# 接受客户端连接
client_socket, addr = server_socket.accept()
print(f"接收到来自 {addr} 的连接")
# 接收数据
data = client_socket.recv(1024)
print(f"收到数据: {data.decode()}")
# 发送响应
client_socket.send("你好,客户端!".encode())
# 关闭连接
client_socket.close()

客户端:

import socket
​
# 创建TCP socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
​
# 连接服务器
client_socket.connect(('localhost', 8888))
​
# 发送数据
client_socket.send("你好,服务器!".encode())
​
# 接收响应
response = client_socket.recv(1024)
print(f"服务器响应: {response.decode()}")
​
# 关闭连接
client_socket.close()

2.3 UDP Socket工作流程

服务器端:

import socket
​
# 创建UDP socket
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
​
# 绑定地址和端口
udp_socket.bind(('localhost', 9999))
​
print("UDP服务器启动,等待数据...")
​
while True:
# 接收数据
data, addr = udp_socket.recvfrom(1024)
print(f"收到来自 {addr} 的数据: {data.decode()}")
# 发送响应
udp_socket.sendto("收到消息!".encode(), addr)

客户端:

import socket
​
# 创建UDP socket
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
​
# 发送数据
udp_socket.sendto("你好,UDP服务器!".encode(), ('localhost', 9999))
​
# 接收响应
response, addr = udp_socket.recvfrom(1024)
print(f"服务器响应: {response.decode()}")
​
# 关闭socket
udp_socket.close()

三、高级网络编程框架

3.1 socketserver模块

Python提供了更高级的socketserver模块,简化了网络服务器的创建。

TCP服务器示例:

import socketserver
​
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
# 处理请求
self.data = self.request.recv(1024).strip()
print(f"{self.client_address[0]} 发送: {self.data.decode()}")
# 发送响应
self.request.sendall(self.data.upper())
​
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
# 创建TCP服务器
with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server:
print(f"服务器启动在 {HOST}:{PORT}")
server.serve_forever()

3.2 异步网络编程

对于高性能网络应用,Python提供了asyncio模块。

异步TCP服务器示例:

import asyncio
​
async def handle_client(reader, writer):
data = await reader.read(100)
message = data.decode()
addr = writer.get_extra_info('peername')
print(f"收到来自 {addr} 的消息: {message}")
writer.write(f"已接收: {message}".encode())
await writer.drain()
writer.close()
​
async def main():
server = await asyncio.start_server(
handle_client, '127.0.0.1', 8888)
addr = server.sockets[0].getsockname()
print(f'服务器运行在 {addr}')
async with server:
await server.serve_forever()
​
asyncio.run(main())

四、简单的聊天应用实现

一个简单的多客户端聊天服务器示例:

import socket
import threading
​
class ChatServer:
def __init__(self, host='localhost', port=8888):
self.host = host
self.port = port
self.clients = []
self.nicknames = []
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
def broadcast(self, message):
for client in self.clients:
try:
client.send(message)
except:
self.remove_client(client)
def remove_client(self, client):
if client in self.clients:
index = self.clients.index(client)
self.clients.remove(client)
nickname = self.nicknames[index]
self.nicknames.remove(nickname)
self.broadcast(f"{nickname} 离开了聊天室!".encode())
def handle_client(self, client):
while True:
try:
message = client.recv(1024)
self.broadcast(message)
except:
self.remove_client(client)
break
def receive(self):
self.server_socket.bind((self.host, self.port))
self.server_socket.listen()
print(f"服务器运行在 {self.host}:{self.port}")
while True:
client, address = self.server_socket.accept()
print(f"连接到: {str(address)}")
client.send("NICK".encode())
nickname = client.recv(1024).decode()
self.nicknames.append(nickname)
self.clients.append(client)
print(f"用户昵称: {nickname}")
self.broadcast(f"{nickname} 加入了聊天室!".encode())
client.send("连接到服务器!".encode())
thread = threading.Thread(target=self.handle_client, args=(client,))
thread.start()
​
if __name__ == "__main__":
server = ChatServer()
server.receive()

五、常见问题与解决方案

5.1 端口占用问题

# 设置SO_REUSEADDR选项解决端口占用
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

5.2 处理连接中断

try:
data = client_socket.recv(1024)
if not data:
print("连接已关闭")
break
except ConnectionResetError:
print("客户端连接中断")

5.3 设置超时

# 设置接收超时
client_socket.settimeout(30.0)  # 30秒超时

附录:Python网络编程API参考

下面表格提供了Python网络编程中最常用API的完整参考,包括参数和返回值信息,可以帮助开发者更高效地使用Python进行网络编程。

socket模块核心API

API描述参数返回值示例
s.socket(family, type, proto)创建新的socket对象

family: 地址族(AF_INET/AF_INET6)

type: socket类型(SOCK_STREAM/

SOCK_DGRAM)

proto: 协议号(通常为0)

socket对象

s = socket.socket

(socket.AF_INET, socket.SOCK_STREAM)

s.gethostname()获取当前主机名字符串形式的主机名host = socket.gethostname()
s.gethostbyname(hostname)通过主机名获取IP地址hostname: 主机名字符串IP地址字符串ip = socket.gethostbyname('www.example.com')
s.gethostbyaddr(ip_address)通过IP地址获取主机信息ip_address: IP地址字符串(hostname, aliaslist, ipaddrlist)元组info = socket.gethostbyaddr('8.8.8.8')
s.getservbyname(servicename, protocolname)通过服务名获取端口号

servicename: 服务名称(如'http')

protocolname: 协议名称(如'tcp')

端口号整数port = socket.getservbyname('http', 'tcp')
s.getservbyport(port, protocolname)通过端口号获取服务名

port: 端口号整数

protocolname: 协议名称(如'tcp')

服务名字符串service = socket.getservbyport(80, 'tcp')
s.inet_aton(ip_string)将IPv4地址转换为32位打包二进制格式

ip_string:

IPv4地址字符串

打包的二进制数据(4字节)packed = socket.inet_aton('192.168.1.1')
s.inet_ntoa(packed_ip)将32位打包的IPv4地址转换为字符串格式packed_ip: 打包的二进制IP地址IPv4地址字符串ip = socket.inet_ntoa(packed)
s.inet_pton(address_family, ip_str)将IP地址转换为打包二进制格式

address_family: AF_INET或AF_INET6

ip_str: IP地址字符串

打包的二进制数据packed = socket.inet_pton(socket.AF_INET6, '::1')
s.inet_ntop(address_family, packed_ip)将打包的二进制IP地址转换为字符串格式

address_family: AF_INET或AF_INET6 packed_ip: 打包的

二进制IP地址

IP地址字符串

ip=socket.inet_ntop

(socket.AF_INET6, packed)

Socket对象方法

方法描述参数返回值适用协议
bind(address)将socket绑定到地址address: (host, port)元组TCP/UDP
listen(backlog)启动TCP监听backlog: 最大挂起连接数TCP
accept()接受TCP连接(socket, address)元组TCP
connect(address)连接到远程socketaddress: (host, port)元组TCP
connect_ex(address)connect()的扩展版本,出错时返回错误码而非异常address: (host, port)元组错误代码(成功时为0)TCP
send(data)发送TCP数据data: 要发送的字节数据已发送的字节数TCP
recv(bufsize)接收TCP数据bufsize: 最大接收字节数接收到的数据字节TCP
sendall(data)完整发送TCP数据data: 要发送的字节数据无(成功)/抛出异常(失败)TCP
sendto(data, address)发送UDP数据

data: 要发送的字节数据

address: (host, port)元组

已发送的字节数UDP
recvfrom(bufsize)接收UDP数据bufsize: 最大接收字节数(data, address)元组UDP
close()关闭socketTCP/UDP
settimeout(value)设置超时时间(秒)value: 超时时间(浮点数)TCP/UDP
gettimeout()获取超时设置

超时时间(秒),

未设置返回None

TCP/UDP
setsockopt(level, optname, value)设置socket选项

level: 选项级别

optname: 选项名称

value: 选项值

TCP/UDP
getsockopt(level, optname)获取socket选项

level: 选项级别

optname: 选项名称

选项值TCP/UDP
setblocking(flag)设置阻塞或非阻塞模式

flag: True为阻塞,

False为非阻塞

TCP/UDP
getpeername()返回远程地址(ip, port)元组TCP
getsockname()返回socket自己的地址(ip, port)元组TCP/UDP
shutdown(how)关闭连接的一部分

how: SHUT_RD/

SHUT_WR/

SHUT_RDWR

TCP

socketserver模块核心类

描述主要方法返回值
server.TCPServerTCP同步服务器基类serve_forever(): 持续处理请求 handle_request(): 处理单个请求 shutdown(): 停止服务
server.UDPServerUDP同步服务器基类同上同上
server.ThreadingMixIn线程混合类,用于创建多线程服务器与服务器类混合使用
server.ForkingMixIn进程混合类,用于创建多进程服务器与服务器类混合使用
server.BaseRequestHandler请求处理程序基类

handle(): 必须重写的方法,处理请求 setup(): 初始化方法

finish(): 清理方法

asyncio网络编程核心API

API描述参数返回值
asyncio.start_server(client_connected_cb, host, port)创建TCP服务器

client_connected_cb:

客户端连接回调

host: 主机地址

port: 端口号

Server对象
asyncio.open_connection(host, port)创建TCP客户端连接

host: 服务器主机地址

port: 服务器端口号

(reader, writer)元组
asyncio.start_unix_server(client_connected_cb, path)创建Unix域套接字服务器

client_connected_cb: 客户端连接回调

path: 套接字路径

Server对象
asyncio.open_unix_connection(path)创建Unix域套接字客户端连接path: 套接字路径(reader, writer)元组
asyncio.StreamReader.read(n)从流中读取数据n: 要读取的字节数读取的数据(bytes)
asyncio.StreamReader.readline()从流中读取一行读取的行(bytes)
asyncio.StreamWriter.write(data)向流中写入数据data: 要写入的数据(bytes)
asyncio.StreamWriter.drain()等待写入操作完成
asyncio.StreamWriter.close()关闭流

select模块核心API

API描述参数返回值
select.select(rlist, wlist, xlist[, timeout])等待I/O就绪

rlist: 等待读取的对象列表

wlist: 等待写入的对象列表

xlist: 等待异常的对象列表

timeout: 超时时间(秒)

(rready, wready, xready)三元组
select.poll()创建poll对象poll对象
poll.register(fd[, eventmask])注册文件描述符到poll对象

fd: 文件描述符

eventmask: 事件掩码

poll.unregister(fd)从poll对象中取消注册文件描述符fd: 文件描述符
poll.poll([timeout])等待事件timeout: 超时时间(毫秒)[(fd, event), ...]列表

常见常量参数

常量描述
socket.AF_INET2IPv4地址族
socket.AF_INET610IPv6地址族
socket.SOCK_STREAM1TCP协议类型
socket.SOCK_DGRAM2UDP协议类型
socket.SOL_SOCKET1Socket选项级别
socket.SO_REUSEADDR2地址重用选项
socket.SO_KEEPALIVE9保持连接选项
socket.SHUT_RD0关闭接收方向
socket.SHUT_WR1关闭发送方向
socket.SHUT_RDWR2关闭双向连接

参考

posted @ 2025-09-15 11:42  yjbjingcha  阅读(13)  评论(0)    收藏  举报