重叠 命名管道-windows 重叠IO 命名管道程序疑问?

问题描述

windows 重叠IO 命名管道程序疑问?

我写了一个命名管道通信例子,但是现在有两个疑问?
疑问1 : 为什么我的程序只能由客户端向服务器发送数据,服务端不能向客户端发送数据呢?服务端显示发送成功,但是客户端相应的可读事件不能被触发。
疑问2 : 偶尔出现客户端向服务器发送数据的时候 前一两个包丢失。

服务端代码:

 #include "stdafx.h"

#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <strsafe.h>

#define CONNECTING_STATE 3
#define READING_STATE 1
#define WRITING_STATE 2
#define INSTANCES 1
#define PIPE_TIMEOUT 5000
#define BUFSIZE 4096

typedef struct
{
   OVERLAPPED oOverlap;
   HANDLE hPipeInst; 

} PIPEINST, *LPPIPEINST; 

VOID DisconnectAndReconnect(DWORD);
BOOL ConnectToNewClient(HANDLE, LPOVERLAPPED); 

bool PostRecvRequest(LPPIPEINST hInst)
{
    if (NULL == hInst)
        return false;

    char buf[1] = {0};
    DWORD dwBytesReaded = 0;
    if (!ReadFile(hInst->hPipeInst, buf, 1, &dwBytesReaded, &hInst->oOverlap))
    {
        DWORD err = GetLastError();
        if (err != ERROR_IO_PENDING)
        {
            printf("client ReadFile error : %d n", err);
            return false;
        }
    }

    return true;
}
bool IsNamedPipeCanRecv(LPPIPEINST hInst)
{
    if (NULL == hInst)
        return false;

    if (WAIT_OBJECT_0 ==WaitForSingleObject(hInst->oOverlap.hEvent, INFINITE))
    {
        return true;
    }
    ResetEvent(hInst->oOverlap.hEvent);

    return false;
}

DWORD WINAPI RecvThread(LPVOID param)
{
    LPPIPEINST hInst = (LPPIPEINST) param;
    if (hInst)
    {
        while(1)
        {
            if (IsNamedPipeCanRecv(hInst))
            {
                char buf[1024] = {0};
                DWORD dwBytesReaded = 0;
                ReadFile(hInst->hPipeInst, buf, 1024, &dwBytesReaded, NULL);
                printf("Server recv : %sn", buf);
            }

            PostRecvRequest(hInst);
        }

    }

    return 0;
}

PIPEINST Pipe[INSTANCES];
HANDLE hEvents[INSTANCES]; 

int _tmain(int argc, _TCHAR* argv[])
{
   LPTSTR lpszPipename = TEXT("\\.\pipe\mynamedpipe"); 

   for (int i = 0; i < INSTANCES; i++)
   { 

   // Create an event object for this instance.
      hEvents[i] = CreateEvent(
         NULL,    // default security attribute
         TRUE,    // manual-reset event
         TRUE,    // initial state = signaled
         NULL);   // unnamed event object 

      if (hEvents[i] == NULL)
      {
         printf("CreateEvent failed with %d.n", GetLastError());
         return 0;
      }

      Pipe[i].oOverlap.hEvent = hEvents[i]; 

      Pipe[i].hPipeInst = CreateNamedPipe(
         lpszPipename,            // pipe name
         PIPE_ACCESS_DUPLEX |     // read/write access
         FILE_FLAG_OVERLAPPED,    // overlapped mode
         PIPE_TYPE_MESSAGE |      // message-type pipe
         PIPE_READMODE_MESSAGE |  // message-read mode
         PIPE_WAIT,               // blocking mode
         INSTANCES,               // number of instances
         BUFSIZE*sizeof(TCHAR),   // output buffer size
         BUFSIZE*sizeof(TCHAR),   // input buffer size
         PIPE_TIMEOUT,            // client time-out
         NULL);                   // default security attributes 

      if (Pipe[i].hPipeInst == INVALID_HANDLE_VALUE)
      {
         printf("CreateNamedPipe failed with %d.n", GetLastError());
         return 0;
      }

     ConnectToNewClient(
         Pipe[i].hPipeInst,
         &Pipe[i].oOverlap); 

   } 

   HANDLE hThread = CreateThread(0, 0, RecvThread, &Pipe[0], 0, 0);

   while (1)
   {
       char buf[1024];
       scanf("%s", buf);
       DWORD dw;
       BOOL b =  WriteFile(Pipe[0].hPipeInst, buf, strlen(buf), &dw, &Pipe[0].oOverlap);
       printf("send(%d:%d) : %sn", dw, b, buf);
   }

  return 0;
} 

VOID DisconnectAndReconnect(DWORD i)
{
// Disconnect the pipe instance. 

   if (! DisconnectNamedPipe(Pipe[i].hPipeInst) )
   {
      printf("DisconnectNamedPipe failed with %d.n", GetLastError());
   }

// Call a subroutine to connect to the new client. 

   ConnectToNewClient(
      Pipe[i].hPipeInst,
      &Pipe[i].oOverlap); 

} 

BOOL ConnectToNewClient(HANDLE hPipe, LPOVERLAPPED lpo)
{
   BOOL fConnected, fPendingIO = FALSE; 

// Start an overlapped connection for this pipe instance.
   fConnected = ConnectNamedPipe(hPipe, lpo); 

// Overlapped ConnectNamedPipe should return zero.
   if (fConnected)
   {
      printf("ConnectNamedPipe failed with %d.n", GetLastError());
      return 0;
   }

   switch (GetLastError())
   {
   // The overlapped connection in progress.
      case ERROR_IO_PENDING:
         fPendingIO = TRUE;
         break; 

   // Client is already connected, so signal an event. 

      case ERROR_PIPE_CONNECTED:
         if (SetEvent(lpo->hEvent))
            break; 

   // If an error occurs during the connect operation...
      default:
      {
         printf("ConnectNamedPipe failed with %d.n", GetLastError());
         return 0;
      }
   } 

   return fPendingIO;
}

客户端代码

 #include "stdafx.h"

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>

#define BUFSIZE 512

typedef struct
{
    OVERLAPPED oOverlap;
    HANDLE hPipeInst;
} PIPEINST, *LPPIPEINST; 

bool PostRecvRequest(LPPIPEINST hInst)
{
    if (NULL == hInst)
        return false;

    char buf[1] = {0};
    DWORD dwBytesReaded = 0;
    if (!ReadFile(hInst->hPipeInst, buf, 1, &dwBytesReaded, &hInst->oOverlap))
    {
        DWORD err = GetLastError();
        if (err != ERROR_IO_PENDING)
        {
            // 109 管道已结束
            printf("client ReadFile error : %d n", err);
            return false;
        }
    }

    return true;
}
bool IsNamedPipeCanRecv(LPPIPEINST hInst)
{
    if (NULL == hInst)
        return false;

    if (WAIT_OBJECT_0 ==WaitForSingleObject(hInst->oOverlap.hEvent, INFINITE))
    {
        return true;
    }
    ResetEvent(hInst->oOverlap.hEvent);

    return false;
}

DWORD WINAPI RecvThread(LPVOID param)
{
    LPPIPEINST hInst = (LPPIPEINST) param;
    if (hInst)
    {
        while(1)
        {
            if (IsNamedPipeCanRecv(hInst))
            {
                char buf[1024] = {0};
                DWORD dwBytesReaded = 0;
                ReadFile(hInst->hPipeInst, buf, 1024, &dwBytesReaded, NULL);
                printf("Client recv : %sn", buf);
            }

            PostRecvRequest(hInst);
        }
    }

    return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
    PIPEINST Pipe;
    Pipe.oOverlap.hEvent =   CreateEvent(
        NULL,    // default security attribute
        TRUE,    // manual-reset event
        FALSE,    // initial state = signaled
        NULL);   // unnamed event object
   LPTSTR lpvMessage=TEXT("Default message from client.");
   BOOL   fSuccess = FALSE;
   DWORD dwMode;
   LPTSTR lpszPipename = TEXT("\\.\pipe\mynamedpipe"); 

   if( argc > 1 )
      lpvMessage = argv[1];

// Try to open a named pipe; wait for it, if necessary. 

   while (1)
   {
      Pipe.hPipeInst = CreateFile(
         lpszPipename,   // pipe name
         GENERIC_READ | GENERIC_WRITE,  // read and write access
         0,              // no sharing
         NULL,           // default security attributes
         OPEN_EXISTING,  // opens existing pipe
         FILE_FLAG_OVERLAPPED,              // default attributes
         NULL);          // no template file 

   // Break if the pipe handle is valid. 

      if ( Pipe.hPipeInst != 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=%dn"), 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;
      }
   } 

// The pipe connected; change to message-read mode. 

   dwMode = PIPE_READMODE_MESSAGE | PIPE_WAIT;
   fSuccess = SetNamedPipeHandleState(
       Pipe.hPipeInst,    // pipe handle
      &dwMode,  // new pipe mode
      NULL,     // don't set maximum bytes
      NULL);    // don't set maximum time
   if ( ! fSuccess)
   {
      _tprintf( TEXT("SetNamedPipeHandleState failed. GLE=%dn"), GetLastError() );
      return -1;
   }

// Send a message to the pipe server.
    PostRecvRequest(&Pipe);
   HANDLE hThread = CreateThread(0, 0, RecvThread, &Pipe, 0, 0);

   while (1)
   {
       char buf[1024];
       scanf("%s", buf);
       DWORD dw;
       WriteFile(Pipe.hPipeInst, buf, strlen(buf), &dw, NULL);
       printf("send(%d) : %sn", dw, buf);
   }

   return 0;
}

解决方案

你客户端也要像服务端那样也创建一个对应事件的管道,然后让服务端反向给你数据。

解决方案二:

管道是单向的。不然要设置两个双向的管道

解决方案三:

不是单向的啊,只要我不等待事件触发就可以正常接收,现在就是客户端事件没有被置信

时间: 2024-12-26 21:23:12

重叠 命名管道-windows 重叠IO 命名管道程序疑问?的相关文章

linux系统编程之管道(三) 命名管道FIFO和mkfifo函数

进程间通信必须通过内核提供的通道,而且必须有一种办法在进程中标识内核提供的某个通道,前面讲过的匿名管道是用打开的文件描述符来标识的.如果要互相通信的几个进程没有从公共祖先那里继承文件描述符,它们怎么通信呢?内核提供一条通道不成问题,问题是如何标识这条通道才能使各进程都可以访问它?文件系统中的路径名是全局的,各进程都可以访问,因此可以用文件系统中的路径名来标识一个IPC通道. FIFO和UNIX Domain Socket这两种IPC机制都是利用文件系统中的特殊文件来标识的. FIFO文件在磁盘上

抛开命名,Windows Phone的软肋在哪里?

摘要: 自6月份传出微软即将重组的消息以来,业界关于重组方案的猜测络绎不绝.一种猜测认为微软的业务将划分为设备.服务.软件三条线,另一种则认为会重新规划为4个业务部门:企业 自6月份传出微软即将重组的消息以来,业界关于重组方案的猜测络绎不绝.一种猜测认为微软的业务将划分为设备.服务.软件三条线,另一种则认为会重新规划为4个业务部门:企业.硬件.应用和服务.操作系统.这两个版本差别不大,而有一个事情则近乎板上定钉,那就是Windows Phone部门与Windows部门的合并.与此大概率事件相对应

windows下安装php应用程序服务器

安装 PHP 应用程序服务器 (Windows) 若要处理动态 Web 页,您需要应用程序服务器.应用程序服务器是一种软件,它帮助 Web 服务器处理包含服务器端脚本或标签的 Web 页.当浏览器请求这样一个页时,Web 服务器先将该页传递给应用程序服务器进行处理,然后再发送到浏览器.有关更多信息,请参见了解 Web 应用程序. 确保运行 IIS 的系统上安装了 PHP 应用程序服务器并且正在运行.(IIS 可能位于您的硬盘或远程 Windows 计算机上.)您可以从 PHP Web 站点(网址

Windows 7开始菜单默认程序列表

列表-win7默认程序列表"> Windows 7 Build 7232和Windows 7 build 7260已经相继泄漏到网络上,俄国网站Wzor已经预测,微软将在6月15日至19日间完成Windows 7 RTM的开发. 同时,微软官方此前已表示,Windows 7将于10月22日正式上市. 当我们关注Windows 7开发进程的同时,我们还应该注意六大版本Windows 7间的差别,比如开始菜单.在预发布版Windows 7(旗舰版)中,开始菜单中的图标包括开始图标,Window

Windows XP更改屏幕保护程序

  登录到Windows后,你应该有加载桌面.在较低的屏幕的左上角,单击"开始"按钮.一个垂直的菜单会弹出. 向上弹出开始菜单上的权利,有许多常用的物品.图为'控制面板'是其中一个项目. 点击"控制面板"选项,在开始菜单上. 控制面板将显示所有可用的设置加载.你会看到我们在画面中突出一个"显示"图标. 用鼠标双击"显示"图标. 会出现"显示属性"窗口. 沿着"显示属性"窗口的顶部,你会看

mingw-Code::Blocks Windows环境下编译HelloWorld程序报错,求高手支招!

问题描述 Code::Blocks Windows环境下编译HelloWorld程序报错,求高手支招! 很简单的Hello World 程序,编译时提示: D:MinGWincludec++3.4.5bitscodecvt.h|475 这个文件中引用的 bits/codecvt_specializations.h 文件找不到 请问是哪里出了问题? ?

vc++-windows如何获取当前应用程序使用的网络类型

问题描述 windows如何获取当前应用程序使用的网络类型 请问各位,Windows下如何获取当前应用程序使用的网络类型?是WIFI还是有线网络. 1.目前实在是没找到类似安卓或者IOS那样的直接就可以读取的API.有的话跪求 2.现在所能想到的就是使用GetAdaptersInfo遍历获取到所有的网卡类型和对应的IP地址, 然后根据gethostbyname得到本地地址,用这个本地地址去匹配遍历得到的网卡IP.这样是否会有问题呢(考虑多网卡的情况) 解决方案 windows上面没有直接提供这一

关于在windows下部署发布QT程序的总结

关于在windows下部署发布QT程序的总结 文章出处:http://www.diybl.com/course/3_program/c++/cppjs/200869/123842.html 以下包括了部分网上收集的,以及qt帮助里的内容(Deploying an Application on Qt/Windows) 首先,打开windows控制台,然后,找到vs安装目录下的bin里,执行 vcvars32.bat 这个脚本.执行完之后,vs需要的所有环境变量就已经设置好了. 然后,做下面的操作:

怎样在Windows Azure中部署应用程序

这篇文章,我们主要围绕怎样在Windows Azure中部署应用程序这个来开展,想要在Azure中部署应用程序,说简单不简单,说难也不难,不过有两个文件是必需的:一个包文件,另一个则是配置文件.要创建包文件,可以在CloudService项目上"右击",然后点击"Publish".它会询问你是创建一个包文件还是把它发布到Azure中.如果选择第一个选项,它会创建包文件,并打开这个浏览器.而第二个配置文件则在CloudService1中,叫作ServiceConfig