我正在尝试学习命名管道如何工作,并创建了2个控制台来测试服务器和客户端之间的连接。客户端将向服务器发送消息,服务器将显示消息,但它不是消息,而是返回值“nullptr”,如VS的错误异常中断所示。
下面是我的代码,如果您发现我的代码有任何问题,请告诉我,我还在学习..
Server.cpp
#include "cust_ostream.hpp"
#include <Windows.h>
#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
LPVOID buffer = NULL;
DWORD readbyte;
cout << "---Named Pipe Server Test---" << endl << endl;
cout << "Creating named pipe: \\\\.\\pipe\\mypipe" << endl;
HANDLE hPipe = CreateNamedPipeA("\\\\.\\pipe\\mypipe", PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES, 1024, 1024, 0, NULL);
if (!hPipe || hPipe == INVALID_HANDLE_VALUE)
{
cout << "Pipe creation failed." << endl;
return 0;
}
cout << "Connecting pipe to client..." << endl;
BOOL connect = ConnectNamedPipe(hPipe, NULL);
if (!connect)
{
cout << "Connect named pipe failed" << endl;
}
cout << "Success! Reading pipe message from client..." << endl;
ReadFile(hPipe, buffer, sizeof(buffer), &readbyte, NULL);
c_cout << "Pipe message = " << *(int *)buffer << endl;
_getch();
return 0;
}
cust_ostream.hpp
#include <Windows.h>
#include <iostream>
#include <sstream>
using namespace std;
#define endl "\n"
class cust_ostream
{
public:
~cust_ostream()
{
cout << m_buffer.str();
}
template <typename T>
cust_ostream &operator<<(T const &value)
{
m_buffer << value;
return *this;
}
private:
ostringstream m_buffer;
};
#define c_cout cust_ostream()
和我的客户
#include <Windows.h>
#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
LPVOID data;
DWORD writebyte;
int i = 2;
cout << "---Named Pipe Client---" << endl << endl;
cout << "Creating pipe file: \\\\.\\pipe\\mypipe" << endl;
HANDLE pipe = CreateFileA("\\\\.\\pipe\\mypipe", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (!pipe || pipe == INVALID_HANDLE_VALUE)
{
cout << "Pipe client failed." << endl;
return 0;
}
cout << "Pipe connected to server, sending data..." << endl;
WriteFile(pipe, &i, sizeof(i), &writebyte, NULL);
_getch();
return 0;
}
答案 0 :(得分:0)
您需要等待NamedPipe上有一个ConnectPipeReady事件。就目前而言,您正在尝试创建管道而不会实际看到它是否成功。请在此处查看命名管道的MSDN文档:https://msdn.microsoft.com/en-ca/library/windows/desktop/aa365592(v=vs.85).aspx
具体来说,这个块:
while (1)
{
hPipe = CreateFile(
lpszPipename, // pipe name
GENERIC_READ | // read and write access
GENERIC_WRITE,
0, // no sharing
NULL, // default security attributes
OPEN_EXISTING, // opens existing pipe
0, // default attributes
NULL); // no template file
// Break if the pipe handle is valid.
if (hPipe != INVALID_HANDLE_VALUE)
break;
// Exit if an error other than ERROR_PIPE_BUSY occurs.
if (GetLastError() != ERROR_PIPE_BUSY)
{
_tprintf( TEXT("Could not open pipe. GLE=%d\n"), GetLastError() );
return -1;
}
// All pipe instances are busy, so wait for 20 seconds.
if ( ! WaitNamedPipe(lpszPipename, 20000))
{
printf("Could not open pipe: 20 second wait timed out.");
return -1;
}
}
此外,您不应使用#define endl "\n"
,请使用std::endl
答案 1 :(得分:0)
您已将缓冲区初始化为NULL,这意味着默认情况下其长度为零。现在,当您在服务器中的read函数中使用sizeof运算符(以检索服务器从客户端接收的消息)时,您要求Read函数中的sizeof运算符读取0个字节!这意味着什么都不会被阅读。
要解决此问题,您可以声明一个大小为100的字符数组或一个您确定不会被客户端超出的消息大小。就像你假设客户端的消息不会超过60个字符一样,那么你可以创建一个大小为100的char缓冲区,以确保你能够容纳客户端的所有消息。
还有一件事,如果问题仍然存在,而不是在读取中使用sizeof,请使用100或任何大小的char缓冲区数组。这应该可以解决你的问题。