C++ PipeServer不每秒发送文本

C++ PipeServer不每秒发送文本,c++,winapi,pipe,C++,Winapi,Pipe,这是第一个应用程序中的“PipeServer”: // Open Pipe and wait until ControlProgram is connecting Pipe.Out = INVALID_HANDLE_VALUE; const wchar_t *data = L"*** Hello Pipe World ***"; DWORD numBytesWritten = 0; DWORD timerinit = GetTickCount();; while (1) { DWOR

这是第一个应用程序中的“PipeServer”:

  // Open Pipe and wait until ControlProgram is connecting
Pipe.Out = INVALID_HANDLE_VALUE;
const wchar_t *data = L"*** Hello Pipe World ***";
DWORD numBytesWritten = 0;
DWORD timerinit = GetTickCount();;
while (1)
{
    DWORD timer = GetTickCount();
    if ((timer - timerinit) > 1000)
    {
        timerinit = timer;
        if (ConnectNamedPipe(Pipe.Out, NULL))
        {
            WriteFile(
                Pipe.Out, // handle to our outbound pipe
                data, // data to send
                wcslen(data) * sizeof(wchar_t), // length of data to send (bytes)
                &numBytesWritten, // will store actual amount of data sent
                NULL // not using overlapped IO
            );
        }
        else
        {
            CloseHandle(Pipe.Out);
            Pipe.Out = INVALID_HANDLE_VALUE;
            do
            {
              Pipe.Out = CreateNamedPipeW(
                L"\\\\.\\pipe\\mypipe", // name of the pipe
                PIPE_ACCESS_OUTBOUND, // 1-way pipe -- send only
                PIPE_TYPE_BYTE, // send data as a byte stream
                1, // only allow 1 instance of this pipe
                0, // no outbound buffer
                0, // no inbound buffer
                0, // use default wait time
                NULL // use default security attributes
                );
            }
            while (Pipe.Out == INVALID_HANDLE_VALUE);
        }
    }
}
///// CLIENT PROGRAM /////

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

using namespace std;

int main(int argc, const char **argv)
{
    wcout << "Connecting to pipe..." << endl;

    // Open the named pipe
    // Most of these parameters aren't very relevant for pipes.
    HANDLE pipe = CreateFileW(
                      L"\\\\.\\pipe\\mypipe",
                      GENERIC_READ, // only need read access
                      FILE_SHARE_READ | FILE_SHARE_WRITE,
                      NULL,
                      OPEN_ALWAYS,
                      FILE_ATTRIBUTE_NORMAL,
                      NULL
                  );

    if (pipe == INVALID_HANDLE_VALUE)
    {
        wcout << "Failed to connect to pipe." << endl;
        // look up error code here using GetLastError()
        system("pause");
        return 1;
    }

    wcout << "Reading data from pipe..." << endl;
    while (1)
    {
        // The read operation will block until there is data to read
        wchar_t buffer[128];
        DWORD numBytesRead = 0;
        BOOL result = ReadFile(
                          pipe,
                          buffer, // the data from the pipe will be put here
                          127 * sizeof(wchar_t), // number of bytes allocated
                          &numBytesRead, // this will store number of bytes actually read
                          NULL // not using overlapped IO
                      );

        if (result)
        {
            buffer[numBytesRead / sizeof(wchar_t)] = '\0'; // null terminate the string
            wcout << "Number of bytes read: " << numBytesRead << endl;
            wcout << "Message: " << buffer << endl;
            FlushFileBuffers(pipe);
        }
        else
        {
            wcout << "Failed to read data from the pipe." << endl;
            wcout << result << endl;
            CloseHandle(pipe);
            break;
        }
    }
    // Close our pipe handle

    wcout << "Done." << endl;

    system("pause");
    return 0;
}
这是“PipeClient”应用程序:

  // Open Pipe and wait until ControlProgram is connecting
Pipe.Out = INVALID_HANDLE_VALUE;
const wchar_t *data = L"*** Hello Pipe World ***";
DWORD numBytesWritten = 0;
DWORD timerinit = GetTickCount();;
while (1)
{
    DWORD timer = GetTickCount();
    if ((timer - timerinit) > 1000)
    {
        timerinit = timer;
        if (ConnectNamedPipe(Pipe.Out, NULL))
        {
            WriteFile(
                Pipe.Out, // handle to our outbound pipe
                data, // data to send
                wcslen(data) * sizeof(wchar_t), // length of data to send (bytes)
                &numBytesWritten, // will store actual amount of data sent
                NULL // not using overlapped IO
            );
        }
        else
        {
            CloseHandle(Pipe.Out);
            Pipe.Out = INVALID_HANDLE_VALUE;
            do
            {
              Pipe.Out = CreateNamedPipeW(
                L"\\\\.\\pipe\\mypipe", // name of the pipe
                PIPE_ACCESS_OUTBOUND, // 1-way pipe -- send only
                PIPE_TYPE_BYTE, // send data as a byte stream
                1, // only allow 1 instance of this pipe
                0, // no outbound buffer
                0, // no inbound buffer
                0, // use default wait time
                NULL // use default security attributes
                );
            }
            while (Pipe.Out == INVALID_HANDLE_VALUE);
        }
    }
}
///// CLIENT PROGRAM /////

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

using namespace std;

int main(int argc, const char **argv)
{
    wcout << "Connecting to pipe..." << endl;

    // Open the named pipe
    // Most of these parameters aren't very relevant for pipes.
    HANDLE pipe = CreateFileW(
                      L"\\\\.\\pipe\\mypipe",
                      GENERIC_READ, // only need read access
                      FILE_SHARE_READ | FILE_SHARE_WRITE,
                      NULL,
                      OPEN_ALWAYS,
                      FILE_ATTRIBUTE_NORMAL,
                      NULL
                  );

    if (pipe == INVALID_HANDLE_VALUE)
    {
        wcout << "Failed to connect to pipe." << endl;
        // look up error code here using GetLastError()
        system("pause");
        return 1;
    }

    wcout << "Reading data from pipe..." << endl;
    while (1)
    {
        // The read operation will block until there is data to read
        wchar_t buffer[128];
        DWORD numBytesRead = 0;
        BOOL result = ReadFile(
                          pipe,
                          buffer, // the data from the pipe will be put here
                          127 * sizeof(wchar_t), // number of bytes allocated
                          &numBytesRead, // this will store number of bytes actually read
                          NULL // not using overlapped IO
                      );

        if (result)
        {
            buffer[numBytesRead / sizeof(wchar_t)] = '\0'; // null terminate the string
            wcout << "Number of bytes read: " << numBytesRead << endl;
            wcout << "Message: " << buffer << endl;
            FlushFileBuffers(pipe);
        }
        else
        {
            wcout << "Failed to read data from the pipe." << endl;
            wcout << result << endl;
            CloseHandle(pipe);
            break;
        }
    }
    // Close our pipe handle

    wcout << "Done." << endl;

    system("pause");
    return 0;
}

您的客户端失败,因为服务器每秒调用
ConnectNamedPipe()
,如果
ConnectNamedPipe()
失败,则关闭连接,因为已经连接了一个客户端,并且您一次只允许连接一个客户端。文件中说明了这一点:

命名管道服务器进程可以将ConnectNamedPipe与新创建的管道实例一起使用它还可以与以前连接到另一个客户端进程的实例一起使用;在这种情况下,服务器进程必须首先调用DisconnectNamedPipe函数,断开句柄与以前客户端的连接,然后才能将句柄重新连接到新客户端。否则,ConnectNamedPipe返回零,GetLastError返回ERROR\u NO\u数据(如果前一个客户端已关闭其句柄),或返回ERROR\u PIPE\u数据(如果未关闭其句柄)。

ConnectNamedPipe()
成功创建新连接时,您只需编写一次消息。在这一点之后,您不会循环编写,下一次迭代将再次调用
ConnectNamedPipe()
,并失败

您没有检查
GetLastError()
中的任何错误代码,否则在阅读文档以了解错误代码的含义后,您可能会注意到这种情况

请尝试类似以下内容:

const wchar_t *data = L"*** Hello Pipe World ***";
DWORD numBytesWritten;

Pipe.Out = CreateNamedPipeW(
    L"\\\\.\\pipe\\mypipe", // name of the pipe
    PIPE_ACCESS_OUTBOUND, // 1-way pipe -- send only
    PIPE_TYPE_BYTE, // send data as a byte stream
    1, // only allow 1 instance of this pipe
    0, // no outbound buffer
    0, // no inbound buffer
    0, // use default wait time
    NULL // use default security attributes
    );

if (Pipe.Out == INVALID_HANDLE_VALUE)
{
    // error creating pipe
}
else
{
    while (should wait for a client to connect)
    {
        if (!ConnectNamedPipe(Pipe.Out, NULL))
        {
            // if ERROR_PIPE_CONNECTED then a client is actually connected!
            if (GetLastError() != ERROR_PIPE_CONNECTED)
            {
                // error connecting a client
                break;
            }
        }

        DWORD timerinit = GetTickCount();
        while (should write to the client)
        {
            DWORD timer = GetTickCount();

            // GetTickCount() wraps back to 0 every 49.7 days, so account for that...
            DWORD elapsed = (timer >= timerinit) ? (timer - timerinit) : ((MAXDWORD - timerinit) + timer);

            if (elapsed >= 1000)
            {
                timerinit = timer;
                if (!WriteFile(
                    Pipe.Out, // handle to our outbound pipe
                    data, // data to send
                    wcslen(data) * sizeof(wchar_t), // length of data to send (bytes)
                    &numBytesWritten, // will store actual amount of data sent
                    NULL // not using overlapped IO
                )
                {
                    // error writing to client
                    break;
                }
            }
        }

        DisconnectNamedPipe(Pipe.Out);
    }

    CloseHandle(Pipe.Out);
}