Python中Socket编程的常见问题与解决方案
最近在学习计算机网络自顶向下这本书 看到书本 P107 开始讲的套接字编程 我照着书本打了一遍代码,测试下来在本机(也就是 ip 127.0.0.1 )可以运行 但是我把 UDPServer.py 放到我的阿里云服务器(并将 hostname 改为服务器公网 ip )上运行,UDPClient 就没反应了?请问是什么原因呢?
客户端
from socket import *
serverName = "106.14.209.139"
serverPort = 10002
clientSocket = socket(AF_INET,SOCK_DGRAM)
message = raw_input("Input lowercase sentence:")
clientSocket.sendto(message,(serverName, serverPort))
modifiedMessage, serverAddress = clientSocket.recvfrom(2048)
print serverAddress
print modifiedMessage
clientSocket.close()
阿里云 ubuntu 服务器上
from socket import *
serverPort = 88
serverSocket = socket(AF_INET,SOCK_DGRAM)
serverSocket.bind(("", serverPort))
print "The server is ready to receive"
while True:
message, clientAddress = serverSocket.recvfrom(2048)
print clientAddress,message
modifiedMessage = message.upper()
serverSocket.sendto(modifiedMessage, clientAddress)
Python中Socket编程的常见问题与解决方案
防火墙端口开了没
Python Socket编程常见问题与解决方案
Socket编程是网络通信的基础,但在Python中常会遇到一些坑。下面我总结几个最常见的问题和对应的解决方案。
1. 地址已被占用 (Address already in use) 这是最经典的问题。当你关闭一个服务器Socket后,操作系统会保留端口一段时间(TIME_WAIT状态)。快速重启服务就会报这个错。
import socket
# 解决方案:设置SO_REUSEADDR选项
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 关键在这里
server_socket.bind(('localhost', 8080))
server_socket.listen()
2. 连接被重置 (Connection reset by peer) 客户端突然断开连接,服务器还在尝试读写数据。
import socket
def handle_client(client_socket):
try:
while True:
data = client_socket.recv(1024)
if not data: # 客户端正常关闭连接
break
# 处理数据...
except ConnectionResetError:
print("客户端异常断开")
finally:
client_socket.close()
# 或者在发送数据时检查连接状态
def safe_send(sock, data):
try:
sock.sendall(data)
return True
except (ConnectionResetError, BrokenPipeError):
return False
3. 粘包问题 TCP是流式协议,没有消息边界,多个小数据包可能被合并接收。
import struct
# 解决方案:添加消息头(长度前缀)
def send_message(sock, message):
# 将消息长度打包为4字节的二进制数据
length = struct.pack('!I', len(message))
sock.sendall(length + message)
def recv_message(sock):
# 先接收4字节的长度信息
length_data = recv_all(sock, 4)
if not length_data:
return None
length = struct.unpack('!I', length_data)[0]
# 按长度接收完整消息
return recv_all(sock, length)
def recv_all(sock, n):
data = b''
while len(data) < n:
packet = sock.recv(n - len(data))
if not packet:
return None
data += packet
return data
4. 阻塞超时问题 默认情况下Socket操作是阻塞的,可能导致程序卡住。
import socket
# 设置超时时间
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.settimeout(5.0) # 5秒超时
try:
client_socket.connect(('example.com', 80))
client_socket.send(b'GET / HTTP/1.0\r\n\r\n')
response = client_socket.recv(4096)
except socket.timeout:
print("连接或接收超时")
except Exception as e:
print(f"其他错误: {e}")
5. 编码问题 网络传输的是字节,不是字符串。
# 发送时编码
message = "你好世界"
sock.send(message.encode('utf-8'))
# 接收时解码
data = sock.recv(1024)
if data:
text = data.decode('utf-8', errors='ignore') # 忽略解码错误
6. 资源泄露 忘记关闭Socket会导致文件描述符耗尽。
# 使用with语句自动管理资源
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect(('localhost', 8080))
sock.send(b'data')
# 退出with块时自动调用sock.close()
# 或者手动确保关闭
sock = None
try:
sock = socket.socket()
sock.connect(('localhost', 8080))
# ... 操作
finally:
if sock:
sock.close()
总结建议:理解TCP流特性和异常处理是关键。
上面第二段代码端口号忘改了,改成 10002
是要开启 windows 上的 10002 端口吗?
大概率情况,你的阿里云的防火墙策略组没配置,端口没开。
-.-! 我记得阿里云是要自己开放服务端口的。
服务器 bind 的端口和客户端发送的端口都不是同一个。。。
localhot 能够访问的服务,其他主机不能访问的话,一般就 3 个原因:1. 网卡绑错了 2. 防火墙端口没开 3. 主机不通
我去好坑…成功了,要自己去阿里云官网配安全组,谢谢啦
感谢
阿里云的经典网络直接可以访问没问题,专有网络需要自己配置端口,才有访问权限。
安全组没放端口策略
借楼问一下,python 的 socket 编程跟其他语言比速度可以接受吗?会不会慢很多?

