Unix套接字下Python客户端与C服务端数据传输故障排查求助
排查Unix套接字C服务端与Python客户端通信失败的问题
我帮你梳理下代码里的几个关键问题,这些是导致双向收发失败的核心原因:
1. Accept语句的运算符优先级错误
这是最致命的问题——你的accept赋值语句因为运算符优先级搞错了,导致connection拿到的根本不是有效的套接字描述符:
原代码:
if (connection = accept(globSock, (struct sockaddr*) &addr, &len) < 0)
这里<的优先级高于=,实际执行逻辑是先判断accept(...) < 0,再把布尔结果(0或1)赋值给connection。正确写法需要给赋值语句加括号,确保先完成赋值再判断结果:
if ((connection = accept(globSock, (struct sockaddr*) &addr, &len)) < 0)
2. MakeSocket函数调用参数不匹配
你的makeSocket函数定义需要两个参数:struct sockaddr_un * addr和char* path,但初始化全局套接字时只传了字符串,这会直接导致编译错误。你需要先定义一个struct sockaddr_un变量,再传给函数:
struct sockaddr_un server_addr; int globSock = makeSocket(&server_addr, "socket.soc");
3. 非阻塞套接字的Recv错误处理不当
你把套接字设为非阻塞模式,但recv返回-1时不一定是真错误——如果是EAGAIN或EWOULDBLOCK,只是表示当前没有数据可读,应该忽略这种情况,而不是直接判定接收失败。
原recv逻辑可以修改为:
else { int rc = recv(connection, buffer, BUFFERSIZE-1, 0); // 留一个位置给字符串终止符 if (rc < 0) { // 非阻塞下无数据的情况,不属于错误 if (errno != EAGAIN && errno != EWOULDBLOCK) { perror("recv failed"); connected = 0; } } else if (rc == 0) { // 客户端主动关闭连接 printf("Client disconnected\n"); connected = 0; recevd = 0; } else { // 给接收的字符串加终止符,避免打印乱码 buffer[rc] = '\0'; recevd = 1; printf("Received: %s\n", buffer); } }
注意要包含errno.h头文件才能使用errno变量。
4. 发送数据后的返回值检查
原代码里的send(connection, "HI", strlen("HI"), 0);没有检查返回值,无法确认数据是否发送成功。可以添加检查逻辑:
ssize_t send_len = send(connection, "HI", strlen("HI"), 0); if (send_len < 0) { perror("send failed"); } else { printf("Sent %zd bytes: HI\n", send_len); }
5. Python客户端缺少接收逻辑
你的Python客户端只发送数据,没有处理C服务端发送的"HI"消息,即使C端修复后发送了数据,客户端也看不到。可以在连接成功后添加接收逻辑:
client.connect("socket.soc") print("Ready.") # 接收服务端的初始消息 init_msg = client.recv(1024).decode('utf-8') print(f"Server says: {init_msg}")
修正后的关键代码片段
C服务端Idle回调修正:
#include <errno.h> // 必须包含这个头文件 // 假设connection、connected、recevd、buffer、addr均已正确定义 if (!connected) { socklen_t len = sizeof(addr); // 注意这里要用socklen_t类型,不是int if ((connection = accept(globSock, (struct sockaddr*) &addr, &len)) < 0) { // 非阻塞下accept返回-1且errno为EAGAIN是正常情况,不是错误 if (errno != EAGAIN && errno != EWOULDBLOCK) { perror("accept failed"); } } else { printf("connected\n"); ssize_t send_len = send(connection, "HI", strlen("HI"), 0); if (send_len < 0) { perror("send failed"); } else { printf("Sent initial message\n"); } connected = 1; recevd = 0; } } else { int rc = recv(connection, buffer, BUFFERSIZE-1, 0); if (rc < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK) { perror("recv failed"); connected = 0; recevd = 0; } } else if (rc == 0) { printf("Client disconnected\n"); connected = 0; recevd = 0; } else { buffer[rc] = '\0'; recevd = 1; printf("Received: %s\n", buffer); } }
Python客户端修正:
# -*- coding: utf-8 -*- import socket import os print("Connecting...") if os.path.exists("socket.soc"): client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) client.connect("socket.soc") print("Ready.") # 接收服务端的初始HI消息 try: server_msg = client.recv(1024).decode('utf-8') print(f"Server: {server_msg}") except: print("Failed to receive initial message") print("Ctrl-C to quit.") print("Sending 'DONE' shuts down the server and quits.") while True: try: x = input("> ") if "" != x: print("SEND:", x) client.send(x.encode('utf-8')) if "DONE" == x: print("Shutting down.") break except KeyboardInterrupt as k: print("Shutting down.") client.close() break else: print("Couldn't Connect!") print("Done")
把这些问题修复后,应该就能正常实现双向通信了。
内容的提问来源于stack exchange,提问作者Yannik Nelson
相关产品推荐
相关产品推荐

