【发布时间】:2020-04-30 13:31:31
【问题描述】:
我尝试在 C++ 中使用命名管道将消息从一台计算机传输到另一台计算机。但是客户端无法连接到服务器,它返回错误1326(无效的名称或密码),虽然服务器名称指定正确。
密码和频道有什么关系?如果代码中没有错误,那么还有什么可能导致通道连接错误?
另外,我在网上看到这样一个表格记录了频道名称\\servername\pipe\[path] pipename。 servername是服务器名,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(&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