【问题标题】:Connection to named pipe连接到命名管道
【发布时间】:2020-04-30 13:31:31
【问题描述】:

我尝试在 C++ 中使用命名管道将消息从一台计算机传输到另一台计算机。但是客户端无法连接到服务器,它返回错误1326(无效的名称或密码),虽然服务器名称指定正确。

密码和频道有什么关系?如果代码中没有错误,那么还有什么可能导致通道连接错误?

另外,我在网上看到这样一个表格记录了频道名称\\servername\pipe\[path] pipenameservername是服务器名,pipe判断是频道,pipename是频道名,但[path]是什么?

服务器

#include <windows.h>
#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    HANDLE hNamedPipe;
    DWORD dwBytesRead; 
    DWORD dwBytesWrite; 
    char pchMessage[80];
    int nMessageLength;

    PSECURITY_DESCRIPTOR psd;
    SECURITY_ATTRIBUTES sa;
    psd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
    InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION);
    SetSecurityDescriptorDacl(psd, true, NULL, false);
    sa.nLength = sizeof(sa);
    sa.bInheritHandle = true;
    sa.lpSecurityDescriptor = psd;

    hNamedPipe= CreateNamedPipe("\\\\.\\pipe\\pipe", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | WRITE_OWNER, PIPE_READMODE_MESSAGE | PIPE_TYPE_MESSAGE| PIPE_ACCEPT_REMOTE_CLIENTS, PIPE_UNLIMITED_INSTANCES, 2048, 2048, INFINITE, &sa);
    if (hNamedPipe == INVALID_HANDLE_VALUE)
    {
            cerr << "Create named pipe failed." << endl
            << "The last error code: " << GetLastError() << endl;
        cout << "Press any key to exit.";
        cin.get();

        return 0;
    }
    cout << "The server is waiting for connection with a client." << endl;
    if (!ConnectNamedPipe(
        hNamedPipe,
        NULL 
    ))
    {
        cerr << "Connect named pipe failed." << endl
            << "The last error code: " << GetLastError() << endl;
        CloseHandle(hNamedPipe);
        cout << "Press any key to exit.";
        cin.get();

        return 0;
    }
    if (!ReadFile(
        hNamedPipe,
        pchMessage,
        sizeof(pchMessage),
        &dwBytesRead, 
        NULL))
    {
        cerr << "Data reading from the named pipe failed." << endl
            << "The last error code: " << GetLastError() << endl;
        CloseHandle(hNamedPipe);
        cout << "Press any key to exit.";
        cin.get();

        return 0;
    }

    cout << "The server received the message from a client: "
        << endl << '\t' << pchMessage << endl;

    cout << "Input a string: ";
    cin.getline(pchMessage, 80);
    nMessageLength = strlen(pchMessage) + 1;

        if (!WriteFile(
            hNamedPipe,
            pchMessage,
            nMessageLength,
            &dwBytesWrite,
            NULL
        ))
        {
            cerr << "Write file failed." << endl
                << "The last error code: " << GetLastError() << endl;
            CloseHandle(hNamedPipe);
            cout << "Press any key to exit.";
            cin.get();

            return 0;
        }

    cout << "The server sent the message to a client: "
        << endl << '\t' << pchMessage << endl;

    CloseHandle(hNamedPipe);
    cout << "Press any key to exit.";
    cin.get();

    return 0;
}

客户

#include <windows.h>
#include <iostream>
#include <string>
using namespace std;

int main()
{
    string machineName;
    getline(cin, machineName, '\n');
    machineName= "\\\\"+machineName+"\\pipe\\pipe";
    cout << machineName << endl;
    char pipeName[80];
    strcpy_s(pipeName, machineName.c_str());
    HANDLE hNamedPipe;
    DWORD dwBytesWritten;
    DWORD dwBytesRead;
    char pchMessage[80];
    int nMessageLength;

    hNamedPipe = CreateFile(
        pipeName, // имя канала
        GENERIC_READ | GENERIC_WRITE, 
        FILE_SHARE_READ | FILE_SHARE_WRITE, 
        NULL, 
        OPEN_EXISTING, 
        FILE_ATTRIBUTE_NORMAL, 
        NULL);

    if (hNamedPipe == INVALID_HANDLE_VALUE)
    {
        cerr << "Connection with the named pipe failed." << endl
            << "The last error code: " << GetLastError() << endl;
        cout << "Press any key to exit.";
        cin.get();
        return 0;
    }
    cin.get();
    cout << "Input a string: ";
    cin.getline(pchMessage, 80);
    nMessageLength = strlen(pchMessage) + 1;
    if (!WriteFile(
        hNamedPipe, 
        pchMessage, 
        nMessageLength,
        &dwBytesWritten,
        NULL)) 
    {
            cerr << "Write file failed: " << endl
            << "The last error code: " << GetLastError() << endl;
        CloseHandle(hNamedPipe);
        cout << "Press any key to exit.";
        cin.get();
        return 0;
    }
        cout << "The client sent the message to a server: "
        << endl << '\t' << pchMessage << endl;
    if (!ReadFile(
        hNamedPipe, 
        pchMessage,
        sizeof(pchMessage), 
        &dwBytesRead,
        NULL))
    {
        cerr << "Read file failed: " << endl
            << "The last error code: " << GetLastError() << endl;
        CloseHandle(hNamedPipe);
        cout << "Press any key to exit.";
        cin.get();
        return 0;
    }
    cout << "The client received the message from a server: "
        << endl << '\t' << pchMessage << endl;
    CloseHandle(hNamedPipe);
    cout << "Press any key to exit.";
    cin.get();
    return 0;
}

【问题讨论】:

  • 不相关:PSECURITY_DESCRIPTOR psd; psd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); InitializeSecurityDescriptor(psd, ... 最好这样:SECURITY_DESCRIPTOR sd; InitializeSecurityDescriptor(&amp;sd, ... - 不要使用指针和手动分配,除非你真的必须这样做。
  • 命名管道是安全对象。客户端的安全性必须与服务器的安全性相匹配,否则连接将失败。
  • 另外,您正在使用FILE_FLAG_OVERLAPPED 创建服务器管道,但您没有使用带有ConnectNamedPipe()(或ReadFile()WriteFile())的OVERLAPPED 结构,这是一个错误: "如果 hNamedPipe 是用 FILE_FLAG_OVERLAPPED 打开的,lpOverlapped 参数不能为 NULL。它必须指向一个有效的 OVERLAPPED 结构。如果 hNamedPipe 用 FILE_FLAG_OVERLAPPED 打开并且 lpOverlapped 为 NULL,函数可能会错误报告连接操作完成。"
  • "[path] 是什么?" - 一个错字。命名管道名称没有[path] 组件,因为pipename 组件中不允许使用反斜杠。阅读文档:Pipe Names.
  • 您需要先致电NetUseAdd 获取\\servername\IPC$

标签: c++ winapi network-programming


【解决方案1】:

经过我的测试,您的代码中有两个地方需要更正。

NetUseAdd 函数在本地之间建立连接 计算机和远程服务器。您可以指定本地驱动器号或 要连接的打印机设备。如果不指定本地驱动器 信件或打印机设备,该功能验证客户端 用于将来连接的服务器。

另外,file and print sharing需要开启。

参考:SMB named pipe with no connection restrictions

一切配置好之后,代码就可以正常工作了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多