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编程的常见问题与解决方案

13 回复

防火墙端口开了没


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 编程跟其他语言比速度可以接受吗?会不会慢很多?

回到顶部