2011-12-16 7 views
5

मैंने नामित पाइप कनेक्शन को संभालने के लिए एक कक्षा लिखी है, और यदि मैं कोई उदाहरण बनाता हूं, इसे बंद करता हूं, और फिर एक और उदाहरण बनाने का प्रयास करें तो CreateFile() रिटर्न पर कॉल करें INVALID_HANDLE_VALUE, और GetLastError()ERROR_PIPE_BUSY देता है। यहाँ क्या चल रहा है? Connect() पर कॉल को बीमा करने के लिए मैं क्या कर सकता हूं?नामांकित पाइप CreateFile() INVALID_HANDLE_VALUE लौटाता है, और GetLastError() देता है ERROR_PIPE_BUSY

PipeAsync A, B; 

A.Connect("\\\\.\\pipe\\test",5000); 
A.Close(); 

cout << GetLastError(); // some random value 
B.Connect("\\\\.\\pipe\\test",5000); 
cout << GetLastError(); // 231 (ERROR_PIPE_BUSY) 
B.Close(); 

यहाँ Connect() की मेरी कार्यान्वयन और Close()

BOOL PipeAsync::Connect(LPCSTR pszPipeName, DWORD dwTimeout) 
{ 
    this->pszPipeName = pszPipeName; 
    this->fExisting = TRUE; 
    DWORD dwMode = this->fMessageMode ? PIPE_READMODE_MESSAGE : PIPE_READMODE_BYTE; 

    hPipe = CreateFile(
     this->pszPipeName, 
     GENERIC_READ | GENERIC_WRITE, 
     0, 
     NULL, 
     OPEN_EXISTING, 
     FILE_FLAG_OVERLAPPED, 
     NULL); 

    if(INVALID_HANDLE_VALUE == hPipe) 
     return FALSE; /* set break point here ; breaks here on second call to Connect() */ 

    if(GetLastError() == ERROR_PIPE_BUSY) 
     if(!WaitNamedPipe(this->pszPipeName, dwTimeout)) 
      return FALSE; /* set break point here */ 

    if(!SetNamedPipeHandleState(hPipe, &dwMode, NULL, NULL)) 
     return FALSE; /* set break point here */ 

    return TRUE; 

} 

VOID PipeAsync::Close() 
{ 

    if(fExisting) 
     DisconnectNamedPipe(hPipe); 

    CloseHandle(hPipe); 
} 
हैं



संपादित करें: मैं आपको बताना है कि कैसे मैं इस निष्कर्ष निकाला ... मैं संकेत दिया अंक तोड़ने सेट भूल गया टिप्पणियों में। जब दौड़ते हैं, तो यह पहले ब्रेक पॉइंट पर रुक जाता है।

संपादित करें: यह मेरा अपडेट किए गए कोड

if(INVALID_HANDLE_VALUE == hPipe) 
    if(GetLastError() == ERROR_PIPE_BUSY) 
    { 
     if(!WaitNamedPipe(this->pszPipeName, dwTimeout)) 
      return FALSE; /* break-point: breaks here on second call */ 
    } 
    else 
     return FALSE; /* break-point /* 

अब, WaitNamedPipe() लौटने Connect() और GetLastError() को दूसरी कॉल 2, या ERROR_FILE_NOT_FOUND लौटने पर झूठा?

+1

सलाह का एक शब्द: '\\', '\ p' और' \ t' को बचने वाले पात्रों के रूप में व्याख्या करने जा रहे हैं। या तो "बच निकलने" से बचने के लिए स्लैश या डबल बैकस्लैश को आगे बढ़ाने के लिए स्विच करें: '"\\\\। \\ पाइप \\ test" '। – Xeo

+0

वह एक टाइपो था ... मैंने इसे सही किया ... –

उत्तर

2

Named Pipe Client से:

पाइप मौजूद है, लेकिन इसके उदाहरणों में से सभी में व्यस्त हैं, तो CreateFile रिटर्न INVALID_HANDLE_VALUE और GetLastError समारोह ERROR_PIPE_BUSY देता है। जब ऐसा होता है, नामित पाइप क्लाइंट WaitNamedPipe फ़ंक्शन का उपयोग करता है ताकि नामित पाइप का उदाहरण पर उपलब्ध हो।

लिंक में ERROR_PIPE_BUSY के साथ मुकाबला करने के लिए उदाहरण कोड है।

संपादित करें:

छोटे compilable उदाहरण है कि को स्वीकार करने और एक नामित पाइप पर जोड़ने दर्शाता:

const char* const PIPE_NAME = "\\\\.\\pipe\\test"; 
const int MAX_CONNECTIONS = 10; 

void client_main() 
{ 
    DWORD last_error; 
    unsigned int elapsed_seconds  = 0; 
    const unsigned int timeout_seconds = 5; 

    HANDLE handle = CreateFile(PIPE_NAME, 
           GENERIC_READ | GENERIC_WRITE, 
           0, 
           0, 
           OPEN_EXISTING, 
           FILE_ATTRIBUTE_NORMAL, 
           0); 

    while (INVALID_HANDLE_VALUE == handle && 
      elapsed_seconds < timeout_seconds) 
    { 
     last_error = GetLastError(); 

     if (last_error != ERROR_PIPE_BUSY) 
     { 
      break; 
     } 

     Sleep(1 * 1000); 
     elapsed_seconds++; 

     handle = CreateFile(PIPE_NAME, 
          GENERIC_READ | GENERIC_WRITE, 
          0, 
          0, 
          OPEN_EXISTING, 
          FILE_ATTRIBUTE_NORMAL, 
          0); 
    } 

    if (INVALID_HANDLE_VALUE == handle) 
    { 
     std::cerr << "Failed to connect to pipe " << PIPE_NAME << 
      ": last_error=" << last_error << "\n"; 
    } 
    else 
    { 
     std::cout << "Connected to pipe " << PIPE_NAME << "\n"; 
     CloseHandle(handle); 
    } 
} 

HANDLE _get_server_handle() 
{ 
    // Error handling omitted for security descriptor creation. 
    SECURITY_DESCRIPTOR sd; 
    InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); 
    SetSecurityDescriptorDacl(&sd, TRUE, static_cast<PACL>(0), FALSE); 

    SECURITY_ATTRIBUTES sa; 
    sa.nLength    = sizeof(sa); 
    sa.lpSecurityDescriptor = &sd; 
    sa.bInheritHandle  = FALSE; 

    // Create a bi-directional message pipe. 
    HANDLE handle = CreateNamedPipe(PIPE_NAME, 
            PIPE_ACCESS_DUPLEX, 
            PIPE_TYPE_MESSAGE  | 
             PIPE_READMODE_MESSAGE | 
             PIPE_NOWAIT, 
            PIPE_UNLIMITED_INSTANCES, 
            4096, 
            4096, 
            0, 
            &sa); 

    if (INVALID_HANDLE_VALUE == handle) 
    { 
     std::cerr << "Failed to create named pipe handle: last_error=" << 
      GetLastError() << "\n"; 
    } 

    return handle; 
} 

void server_main() 
{ 
    HANDLE handle = _get_server_handle(); 

    if (INVALID_HANDLE_VALUE != handle) 
    { 
     int count = 0; 
     while (count < MAX_CONNECTIONS) 
     { 
      BOOL result = ConnectNamedPipe(handle, 0); 

      const DWORD last_error = GetLastError(); 

      if (ERROR_NO_DATA == last_error) 
      { 
       count++; 
       std::cout << "A client connected and disconnected: count=" << 
        count << "\n"; 
       CloseHandle(handle); 
       handle = _get_server_handle(); 
      } 
      else if (ERROR_PIPE_CONNECTED == last_error) 
      { 
       count++; 
       std::cout << "A client connected before call to " << 
        "ConnectNamedPipe(): count=" << count << "\n"; 
       CloseHandle(handle); 
       handle = _get_server_handle(); 
      } 
      else if (ERROR_PIPE_LISTENING != last_error) 
      { 
       std::cerr << "Failed to wait for connection: last_error=" << 
        GetLastError() << "\n"; 
       CloseHandle(handle); 
       break; 
      } 
      Sleep(100); 
     } 
    } 
} 

int main(int a_argc, char** a_argv) 
{ 
    if (2 == a_argc) 
    { 
     if (std::string("client") == *(a_argv + 1)) 
     { 
      for (int i = 0; i < MAX_CONNECTIONS; i++) 
      { 
       client_main(); 
      } 
     } 
     else if (std::string("server") == *(a_argv + 1)) 
     { 
      server_main(); 
     } 
    } 
    return 0; 
} 

निष्पादित सर्वर साइड पहले:

pipetest.exe server 

तो क्लाइंट साइड निष्पादित करें:

pipetest.exe client 

मैं नहीं बता सका कि पोस्ट कोड से समस्या क्या थी। उम्मीद है कि यह छोटा उदाहरण आपको इस मुद्दे को खोजने में सहायता करेगा।

+0

मैंने उस तर्क का पालन करने के लिए अपना कोड बदल दिया, और अब 'WaitNamedPipe()' झूठी वापसी कर रहा है, और GetLastError() 'ERROR_FILE_NOT_FOUND' –

+0

वापस लौटा रहा है मैंने लूपिंग तर्क की भी कोशिश की एमएसडीएन उदाहरण में, और मुझे एक ही परिणाम मिलता है।'CreateFile() '' EVVALID_HANDLE_VALUE' लौटाता है, फिर' GetLastError() 'रिटर्न' ERROR_PIPE_BUSY', 'WaitNamedPipe()' 'FALSE' लौटाता है, और 'GetLastError()' रिटर्न 'ERROR_FILE_NOT_FOUND' देता है। –

+0

क्या आप नामित पाइप बनाते हैं जिसे "\\\\। \\ पाइप \\ test" कहा जाता है? एक नामित पाइप [CreateNamedPipe()] (http://msdn.microsoft.com/en-us/library/windows/desktop/aa365150%28v=vs.85%29.aspx) का उपयोग कर बना रहा है। – hmjd

संबंधित मुद्दे