查看: 99|回复: 3

Python Socket库TCP与UDP通信完整实战教程:从客户端到服务端

[复制链接]
发表于 1 小时前 | 显示全部楼层 |阅读模式
Socket(套接字)是网络编程的基石,Python内置的socket模块无需安装即可实现TCP和UDP通信。本文从零开始,详细讲解TCP与UDP客户端和服务端的完整实现、高频配置选项、粘包问题解决方案及三个实战案例,帮助你快速掌握Python网络编程。

一、Socket对象创建
导入模块后,通过socket.socket(family, type)创建套接字,family指定地址族(通常为socket.AF_INET代表IPv4),type指定协议类型:socket.SOCK_STREAM为TCP,socket.SOCK_DGRAM为UDP。
  1. import socket
  2. # TCP套接字
  3. tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  4. # UDP套接字
  5. udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
复制代码

二、TCP通信全套API
TCP是面向连接的可靠协议,通信前需建立三次握手。
1. TCP客户端
客户端需依次执行:创建套接字、设置超时(可选)、连接服务器、发送/接收数据、关闭连接。
  1. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  2. sock.settimeout(5)  # 5秒无响应超时
  3. sock.connect(("127.0.0.1", 8080))
  4. sock.send("你好服务端".encode("utf-8"))
  5. data = sock.recv(1024)
  6. print(data.decode("utf-8"))
  7. sock.close()
复制代码
2. TCP服务端
服务端创建后需绑定IP和端口、监听、等待客户端连接,然后处理收发。注意启用端口复用避免重启时报错。
  1. server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  2. server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # 端口复用
  3. server.bind(("0.0.0.0", 8080))
  4. server.listen(5)
  5. print("服务端已启动,等待连接...")
  6. conn, client_addr = server.accept()
  7. print("客户端地址:", client_addr)
  8. msg = conn.recv(1024)
  9. print("收到:", msg.decode())
  10. conn.send("收到消息".encode("utf-8"))
  11. conn.close()
复制代码

三、UDP通信全套API
UDP无连接,直接发数据包。核心方法为sendto和recvfrom。
1. UDP客户端(只发数据)
  1. sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  2. sock.sendto(b"心跳包", ("127.0.0.1", 9999))
  3. sock.close()
复制代码
2. UDP服务端接收数据
  1. sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  2. sock.bind(("0.0.0.0", 9999))
  3. while True:
  4.     data, addr = sock.recvfrom(1024)
  5.     print(f"来自{addr}: {data.decode()}")
  6.     sock.sendto(b"ok", addr)
复制代码
3. UDP广播设置(局域网设备发现)
  1. sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
  2. sock.sendto(b"online", ("255.255.255.255", 9999))
复制代码

四、高频通用配置选项
1. 端口复用:避免服务端重启时提示Address already in use。
  1. sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
复制代码
2. 设置阻塞超时:recv/accept默认永久阻塞,务必加超时。
  1. sock.settimeout(3)
  2. try:
  3.     data = sock.recv(1024)
  4. except socket.timeout:
  5.     print("接收超时")
复制代码
3. 关闭Nagle算法:小包立即发送,适合实时性场景。
  1. sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, True)
复制代码
4. 获取本机IP:socket.gethostbyname(socket.gethostname())
5. 域名解析为IP:socket.gethostbyname("www.baidu.com")

五、TCP粘包问题及解决方案
TCP是字节流,多次send的数据可能被合并接收。常用方案:固定长度、前置数据长度、使用分隔符。
示例:发送端添加分隔符"|||",接收端按分隔符切割。
  1. # 发送端
  2. sock.send(b"hello|||")
  3. # 接收端按分隔符切割数据
复制代码

六、实战案例
案例1:TCP端口存活检测
  1. def port_check(host, port, timeout=2):
  2.     try:
  3.         sock = socket.socket()
  4.         sock.settimeout(timeout)
  5.         sock.connect((host, port))
  6.         sock.close()
  7.         return True
  8.     except:
  9.         return False
复制代码
案例2:裸Socket发送HTTP请求
  1. sock = socket.socket()
  2. sock.connect(("www.baidu.com", 80))
  3. http_header = b"GET / HTTP/1.1\r\nHost:www.baidu.com\r\nConnection:close\r\n\r\n"
  4. sock.send(http_header)
  5. print(sock.recv(4096).decode("utf-8", errors="ignore"))
  6. sock.close()
复制代码

七、避坑总结
1. 所有收发数据必须是bytes,字符串需.encode("utf-8")。
2. TCP必须先连接再收发,UDP直接sendto。
3. recv缓冲区合理设置(如1024),太小会读不全。
4. 必须设置超时,避免无限阻塞。
5. 服务端绑定0.0.0.0才能对外网与局域网开放,绑定127.0.0.1仅本机。
6. 短连接收发完毕及时close,避免大量TIME_WAIT占用端口。

掌握以上内容,你已具备Python socket编程的核心能力。如需多线程TCP服务端、asyncio异步socket、自定义TCP分包协议等高级内容,欢迎探讨。
回复

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: Python Socket库TCP与UDP通信完整实战教程:从客户端到服务端

感谢楼主的详细教程,结构非常清晰,从基础API到粘包问题再到实战案例,对新手很友好。一个小细节补充:TCP客户端示例中用了`send()`,实际生产环境建议用`sendall()`确保完整发送,尤其在传输大文件时更可靠。另外UDP广播示例里目标地址用的是`"255.255.255.255"`,这是受限广播,适合局域网但某些路由器可能会过滤,如果需要更精确可以用子网广播地址(如`"192.168.1.255"`)。总体非常实用,收藏了!
回复 支持 反对

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: Python Socket库TCP与UDP通信完整实战教程:从客户端到服务端

很实用的入门教程,把TCP和UDP的核心流程、常用配置和踩坑点都讲清楚了。对刚接触网络编程的人来说,粘包问题的示例和端口检测的实战案例帮助很大。
回复 支持 反对

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: Python Socket库TCP与UDP通信完整实战教程:从客户端到服务端

感谢分享,非常详实的教程!尤其是粘包那部分,直接给分隔符和固定长度两种思路,很实用。想问下UDP广播用255.255.255.255,在路由器启用了隔离或客户端在不同子网时,是不是需要改用subnet定向广播地址?实际项目里有没有踩过坑?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-6-29 10:51 , Processed in 0.031192 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部