You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows下C程序通过命名管道传UINT32结构体客户端接收全零如何解决

问题根因汇总

  • 服务端发送长度计算错误
    你传输的是二进制结构体数据,第一个字段Height的值为0,你用strlen(msg)计算发送长度时,strlen遇到第一个0字节就会返回0,导致服务端实际上没有发送任何数据,客户端读到的就是初始化的全0缓存。
  • 命名管道路径转义错误
    C语言中字符串里的反斜杠需要转义,你定义的管道路径#define TestCoordinate_Pipe "\\.\pipe\TestCoordinates" 实际解析出来是错误的,应该写成\\\\.\\pipe\\TestCoordinates,否则两端无法成功建立管道连接。
  • 客户端返回局部变量指针(野指针)
    getObjectLocation 函数中buffer是栈上的局部数组,函数返回后栈空间会被回收,返回的buffer指针是野指针,main函数中用这个指针拷贝数据会读取到无效内容。
  • 客户端读管道逻辑错误
    你用了while (ReadFile(...))的死循环读取,会持续读直到管道断开,而且你给二进制数据末尾加\0的操作是字符串场景的用法,会破坏二进制结构体的有效数据,同时原代码未对管道句柄执行关闭操作,存在资源泄漏。

修复方案

1. 统一修改管道路径宏

两端的管道路径宏都改为正确的转义格式:

#define TestCoordinate_Pipe "\\\\.\\pipe\\TestCoordinates"

2. 修复服务端发送逻辑

把WriteFile的长度参数从strlen(msg)改为实际要发送的结构体大小sizeof(ObjectInfo):

WriteFile(
    hPipe,
    msg,
    sizeof(ObjectInfo),
    &dwWritten,
    NULL);

3. 修复客户端逻辑

  • 不返回局部栈内存指针,改为直接传入结构体指针填充结果
  • 去掉多余的读循环和加\0的操作,只读一次需要的结构体大小即可
  • 增加管道句柄关闭逻辑,避免资源泄漏

修复后的客户端参考代码:

#include <stdio.h>
#include <Windows.h>
#include <stdbool.h>

#define TestCoordinate_Pipe "\\\\.\\pipe\\TestCoordinates"
#define MESSAGE_MAX_LENGTH  1024

#pragma pack(push, 1)
typedef struct _ObjectInfo
{
    UINT32 Height;
    UINT32 XCoordinate;
    UINT32 YCoordinate;
    UINT32 Width;
}ObjectInfo;
#pragma pack(pop)

bool getObjectLocation(char* pipe, ObjectInfo* outInfo)
{
    HANDLE hPipe;
    char buffer[MESSAGE_MAX_LENGTH] = { 0 };
    DWORD dwRead;
    hPipe = CreateNamedPipe(
        pipe,
        PIPE_ACCESS_DUPLEX,
        PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
        1,
        MESSAGE_MAX_LENGTH,
        MESSAGE_MAX_LENGTH,
        NMPWAIT_USE_DEFAULT_WAIT,
        NULL);
    if (hPipe == INVALID_HANDLE_VALUE) {
        return false;
    }
    if (ConnectNamedPipe(hPipe, NULL) != FALSE) {
        // 只读一次需要的结构体大小即可
        if (ReadFile(hPipe, buffer, sizeof(ObjectInfo), &dwRead, NULL) != FALSE && dwRead == sizeof(ObjectInfo)) {
            RtlCopyMemory(outInfo, buffer, sizeof(ObjectInfo));
            DisconnectNamedPipe(hPipe);
            CloseHandle(hPipe);
            return true;
        }
    }
    DisconnectNamedPipe(hPipe);
    CloseHandle(hPipe);
    return false;
}

int main()
{
    ObjectInfo objectInfo = {0};
    if (getObjectLocation(TestCoordinate_Pipe, &objectInfo)) {
        printf("\n\tHeight: %d;\t X-Coordinate: %d\t Y-Coordinate: %d\tWidth: %d",
            objectInfo.Height,
            objectInfo.XCoordinate,
            objectInfo.YCoordinate,
            objectInfo.Width);
    } else {
        printf("读取管道失败");
    }
    return 0;
}

可选优化

上述代码已经在结构体定义前后加了#pragma pack编译指令,强制1字节对齐,可以避免两端结构体对齐规则不一致导致的解析错误。

内容的提问来源于stack exchange,提问作者Ganesh Kamath - 'Code Frenzy'

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 16:36:03