title: Windows named pipe client WriteFile fails with error 232 ERROR_NO_DATA only with first client
body: <p>I've implemented a named pipe server and client. the pipe is in <code>PIPE_READMODE_MESSAGE</code> mode. im trying to send a message from the client to the server using <code>WriteFile</code>. the operation fails and <code>GetLastError</code> returns error 232 <code>ERROR_NO_DATA</code> . if i connect a second client the operation is successful and the message is sent.
  i tried other operations on the same pipe handle with <code>SetNamedPipeHandleState</code> and the operation was succesful, so i think the pipe is ok. 
  a message is sent from the server to the client is also succesful.
  i don't think it's a buffer size problem because im trying to send 4 bytes with 512 byte buffer defined for the pipe.</p>
  
  <p>there is a similar topic : <a href="https://stackoverflow.com/questions/6105002/writefile-on-a-named-pipe-sometimes-returns-error-no-data">WriteFile on a named pipe sometimes returns ERROR_NO_DATA</a>
  but it does not solve my problem.
  I've searched the web for answers but i cant find anything like this. appreciate any help</p>
  
  <p>server code:</p>
  
  <pre><code>int CServer::Run(){
      BOOL   fConnected = FALSE;
      DWORD  dwThreadId = 0;
      HANDLE hPipe = INVALID_HANDLE_VALUE, hThread = NULL;
      //LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\IlyaPipe");
      LPTSTR lpszPipename = TEXT("IlyaPipe");
      CSingleLock ConnListLock(&amp;server.ConnManager.ConnListMutex);
      CConnection* NewConn;
      CWnd* pWnd = AfxGetMainWnd();
      ASSERT_VALID(pWnd);
      // The main loop creates an instance of the named pipe and 
      // then waits for a client to connect to it. When the client 
      // connects, a thread is created to handle communications 
      // with that client, and this loop is free to wait for the
      // next client connect request. It is an infinite loop.
  
      //start connection manager thread.
  
      server.ConnManager.CreateThread();
      SendMessage(pWnd-&gt;m_hWnd, WM_SERVER_ONLINE, 0, 0);
      for (;;)
      {
          NewConn = new CConnection;
          NewConn-&gt;Create(
              lpszPipename,             // pipe name 
              PIPE_ACCESS_DUPLEX,       // read/write access 
              PIPE_TYPE_MESSAGE |       // message type pipe 
              PIPE_READMODE_MESSAGE |   // message-read mode 
              PIPE_WAIT,                // blocking mode 
              PIPE_UNLIMITED_INSTANCES, // max. instances  
              BUFSIZE,                  // output buffer size 
              BUFSIZE,                  // input buffer size 
              0,                        // client time-out 
              NULL);
  
          // Wait for the client to connect; if it succeeds, 
          // the function returns a nonzero value. If the function
          // returns zero, GetLastError returns ERROR_PIPE_CONNECTED. 
  
          NewConn-&gt;ConnectClient(NULL);
          //after succesful initialization, set read/write mode to blocking message mode.
          NewConn-&gt;SetMode(FALSE, TRUE);
          NewConn-&gt;ClientProcessID = (ULONG)NewConn-&gt;m_hPipe; //temporary value
  
          if (ConnListLock.Lock(INFINITE))
          {
              server.ConnManager.AddConnection((*NewConn));
              NewConn-&gt;SendConnectionID();
              ConnListLock.Unlock();
          }
          SendMessage(pWnd-&gt;m_hWnd, WM_CLIENT_ADDED, 0, 0);
      }
      //notify of server shut down
      SendMessage(pWnd-&gt;m_hWnd, WM_SERVER_OFFLINE, 0, 0);
      return (0);
  }
  
  
  void CNamedPipe::Create(LPCTSTR lpszName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD dwMaxInstances, DWORD dwOutBufferSize, 
                          DWORD dwInBufferSize, DWORD dwDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
  {
    //Validate our parameters
    ASSERT(!IsOpen());
    ASSERT(_tcslen(lpszName));
  
    //the class encapsulates creating the pipe name, all that is required is
    //a simple name for the pipe e.g. lpName = PJPIPE will create the pipe
    //name "\\.\PIPE\PJPIPE"
    CString sPipeName;
    sPipeName.Format(_T("\\\\.\\PIPE\\%s"), lpszName);
  
    m_hPipe = ::CreateNamedPipe(sPipeName, dwOpenMode, dwPipeMode, dwMaxInstances, dwOutBufferSize, dwInBufferSize, dwDefaultTimeOut, lpSecurityAttributes);
    if (m_hPipe == INVALID_HANDLE_VALUE)
      ThrowNamedPipeException();
  }
  </code></pre>
  
  <p>client :</p>
  
  <pre><code>int CServerConnection::Run(){
  
      BOOL   fSuccess = FALSE;
      DWORD  cbRead, cbToWrite, cbWritten, dwMode, dwEvent, dwError;
      LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\IlyaPipe");
  
      // Try to open a named pipe; wait for it, if necessary. 
  
      while (1)
      {
          hConnPipe = 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 (hConnPipe != INVALID_HANDLE_VALUE)
          {
              // The pipe connected; change to message-read mode. 
  
              dwMode = PIPE_READMODE_MESSAGE;
              fSuccess = SetNamedPipeHandleState(
                  hConnPipe,    // pipe handle 
                  &amp;dwMode,  // new pipe mode 
                  NULL,     // don't set maximum bytes 
                  NULL);    // don't set maximum time 
              if (!fSuccess)
              {
                  _tprintf(TEXT("SetNamedPipeHandleState failed. GLE=%d\n"), GetLastError());
                  return (0);
              }
  
              //get ID from server, for creating 'message from server' event
              if (!ReadMessage())
                  return (0);
              //create event name string for message from server event.
              CString EventName;
              EventName.Format(_T("ILYA_PIPE_SERVER_SENT_"));
              EventName.AppendFormat(_T("%s"), m_ReplyBuff);
              //register to the event signaling a message was sent from server to client. should be created by server.
              hSendMsgEvent[1] = CreateEvent(NULL, TRUE, FALSE, EventName);
              if (GetLastError() != ERROR_ALREADY_EXISTS)
                  return (0);
              //register to the event signaling a message was sent from server to client. should be created by server.
              EventName.Format(_T("ILYA_PIPE_CLIENT_SENT_"));
              EventName.AppendFormat(_T("%s"), m_ReplyBuff);
              m_hAlertServerEvent = CreateEvent(NULL, TRUE, FALSE, EventName);
              if (GetLastError() != ERROR_ALREADY_EXISTS)
                  return (0);
  
              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 (0);
              //ExitInstance();
          }
  
          // 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 (0);
              //ExitInstance();
  
          }
      }
  
  
      //notify main window that connection to server established
      CWnd* pWnd = AfxGetMainWnd();
      ASSERT_VALID(pWnd);
      SendMessage(pWnd-&gt;m_hWnd, WM_CONNECTION_ESTABLISHED, 0, 0);
  
  
  
  
      //SendMessage(pWnd-&gt;m_hWnd, WM_CONNECTION_ESTABLISHED, 0, 0);
      //message send and receive loop
      while (1){
          dwEvent = WaitForMultipleObjects(1, hSendMsgEvent, FALSE, INFINITE);
          switch (dwEvent){
          //The application wants to send a request.
          case SEND_MSG_EVENT:
              if (SendMsg2Server())
                  //set event notifing the server of sent message
                  SetEvent(m_hAlertServerEvent);
              else
                  dwError = GetLastError();
              ResetEvent(hSendMsgEvent[0]);
              break;
  
          //A message is waiting for you at the server
          case RECEIVE_MSG_EVENT:
              ReadMessage();
              ResetEvent(hSendMsgEvent[1]);
              break;
  
          //Invalid return from wait
          default :
              ExitProcess(0);
  
          }
      }
  
  
  
      //connectionStatus = true;
  
      // Write the reply to the pipe. 
  
      //CloseHandle(hPipe);
  
      return (0);
  
  }
  
  
  
  int CServerConnection::DisconnectFromServer()
  {
      return 0;
  }
  
  void CServerConnection::PackMessage(const uint8 ActionType, const uint8 DeviceAddress,  const uint32 FileId,const uint32 Offset ){
  
      msg.ActionType = ActionType;
      msg.bSent = 1;
      msg.bReady = 0;
      msg.DeviceAddress = DeviceAddress;
      msg.FileId = FileId;
      msg.Offset = Offset;
  }
  
  BOOL CServerConnection::SendMsg2Server(){
      BOOL   fSuccess = FALSE;
      DWORD  cbWritten = 0, cbReplyBytes = 0, cbToWrite, dwMode;
      CString MsgStr;
      LPTSTR lpvMessage = TEXT("Default");
  
      //MsgStr.Format(_T("%d*%d"), msg.FileId, msg.ActionType);
      //cbToWrite = 2*sizeof(TCHAR)*(MsgStr.GetLength() + 1);
  
      cbToWrite = (lstrlen(lpvMessage) + 1)*sizeof(TCHAR);
      MsgStr.Format(TEXT("%d"), 1);
      cbToWrite = sizeof(MsgStr);
  
      dwMode = PIPE_READMODE_MESSAGE;
      fSuccess = SetNamedPipeHandleState(
          hConnPipe,    // pipe handle 
          &amp;dwMode,  // new pipe mode 
          NULL,     // don't set maximum bytes 
          NULL);    // don't set maximum time 
  
      fSuccess = WriteFile(
          hConnPipe,              // pipe handle 
          MsgStr,
          cbToWrite,              // message length 
          &amp;cbWritten,             // bytes written 
          NULL);
  
      return fSuccess;
  
  }
  
  
  //Read message from server
  BOOL CServerConnection::ReadMessage(){
      BOOL   fSuccess = FALSE;
      DWORD cbBytesRead = 0;
  
      fSuccess = ReadFile(
          hConnPipe,              //pipe handle
          (LPVOID)m_ReplyBuff,    //Message buffer
          BUFSIZE,                //Maximal message size
          &amp;cbBytesRead,           //actual bytes read
          NULL);
  
      return fSuccess;
  
  }
  </code></pre>