2010-03-03 31 views
8

Tôi đang tìm hiểu về đường ống được đặt tên và được chơi với các đường ống client và server ví dụ đặt tên từ MSDN doc:Làm thế nào để phát hiện một khách hàng ngắt kết nối bằng cách sử dụng một máy khách ống/máy chủ được đặt tên?

Named Pipe Server

Named Pipe Client

tôi sửa đổi cho khách hàng vì vậy tôi có thể gõ vào thông điệp đến giao diện điều khiển và gửi chúng đến máy chủ nơi nó hiển thị thông báo và gửi trả lời. Về cơ bản tôi đã thêm một vòng lặp bắt đầu sau cuộc gọi SetNamedPipeHandleState() và kết thúc trước cuộc gọi CloseHandle() (tức là mở và đóng xảy ra bên ngoài vòng lặp, vì vậy tôi đang sử dụng cùng một tay cầm ống trong vòng lặp).

Câu hỏi của tôi là, nếu tôi giết khách hàng (bằng cách đóng nó hoặc kết thúc nó thông qua Task Manager) được Có cách nào cho phía máy chủ để phát hiện sự ngắt kết nối?

Tôi đã thử sử dụng GetNamedPipeHandleState() hy vọng nó trả về lỗi và một cuộc gọi đến GetLastError() sẽ trả về ERROR_PIPE_NOT_CONNECTED, nhưng đó không phải là trường hợp. Do cách máy chủ này được thiết lập, tôi phải thực hiện điều này trong hàm CompletedReadRoutine và tạo ra một lỗi "được kiểm soát". Những gì tôi đã làm được, với một breakpoint trên CompletedReadRoutine trong máy chủ:

  1. bắt đầu máy chủ
  2. bắt đầu cho khách hàng
  3. đã gửi một tin nhắn qua client (lượt truy cập các breakpoint trong máy chủ ở đây)
  4. giết client
  5. Stepped thông qua các GetNamedPipeHandleState

các cuộc gọi đến GetNamedPipeHandleState() trả về thành công hoàn toàn vì vậy tôi không bao giờ phải thực hiện cuộc gọi GetLastError(). Khi nó được gọi đến WriteFileEx nó thất bại và một cuộc gọi đến GetLastError tại thời điểm đó trả về một ERROR_NO_DATA.

Nhìn vào các chức năng ống Tôi không thể nhìn thấy bất cứ điều gì khác mà có thể sẽ giúp đây. Tôi thiếu một cái gì đó hoặc là một khách hàng ngắt kết nối chỉ không phát hiện được.

Điều duy nhất tôi có thể nghĩ đến là thu thập số lượng khách hàng kết nối (thông qua GetNamedPipeClientProcessId) và quay các chủ đề cơ quan giám sát để kiểm tra xem họ có còn sống hay không. Mặc dù, chỉ cần suy nghĩ về làm điều đó đặt ra ý nghĩa của tôi spidey.

Có cách nào để phát hiện khách hàng bị ngắt kết nối khi sử dụng ống được đặt tên?

Trả lời

5

Không trả lại và lỗi ReadFile()GetLastError() sau đó trả lại ERROR_BROKEN_PIPE?

+0

Chỉ khi tôi giết khách hàng một cách cẩn thận bằng cách sử dụng điểm ngắt trong máy chủ để tôi có thể giết khách hàng tại một piont cụ thể trong logic máy chủ. Ví dụ, nếu tôi khởi động máy khách và giết nó ngay sau khi kết nối ban đầu nhưng trước khi máy chủ gọi ReadFileEx lần đầu tiên, thì có, tôi nhận được ERROR_BROKEN_PIPE. Sự cố là máy chủ đang chờ cuộc gọi đến WaitForSingleObjectEx. Nếu phía máy khách đi xuống, nó sẽ không ghi vào hoặc đọc từ đó được kết nối tương ứng với cá thể đường ống. –

+3

Tôi không thực sự nghĩ rằng những mẫu đó là tốt một ví dụ về cách làm việc ... Cá nhân tôi luôn luôn có một đọc chồng chéo trên đường ống, theo cách đó bạn nên luôn luôn nhận được một thông báo khi khách hàng biến mất. .. –

+0

Tôi nghe bạn và đồng ý rằng các ví dụ tôi có không phải là những gì tôi nên xem xét theo cách tôi muốn giao tiếp làm việc. Cảm ơn vì đầu vào của bạn. –

1

ReadFile() + GetLastError() thực hiện công việc tốt. Dưới đây là làm thế nào họ có thể được sử dụng với I/cổng O hoàn thành (thực hiện của tôi là trong python + ctypes, nhưng ý tưởng phải rõ ràng):

def connect(): 
    GetQueuedCompletionStatus() 
    receive() 

def receive(): 
    while True: 
     ret_code = ReadFile() 
     if ret_code == 0 and GetLastError() == ERROR_BROKEN_PIPE: 
      # client disconnected 
     GetQueuedCompletionStatus() 

Chúng tôi đang chờ đợi một gói hoàn thành, và khi một connect khách hàng , chúng ta chuyển sang vòng lặp chính. Trong vòng lặp chính, chúng tôi đọc đường ống và kiểm tra xem khách hàng đã ngắt kết nối chưa bằng cách xem mã trả lại ReadFile()GetLastError(). Sau đó, một lần nữa, chúng tôi sẽ chờ đợi cho một gói hoàn thành.

Khách hàng có thể ngắt kết nối trên mọi giai đoạn. Gói hoàn thành sẽ được xếp hàng đợi và chúng tôi sẽ nhận được ERROR_BROKEN_PIPE.

+0

Ngôn ngữ lập trình nào? Nó trông hơi giống Python, nhưng AFAIK 'winapi' là C, C++, C# và Visual Basic. – wizzwizz4

+0

Vâng, đây là Python, nhưng bạn có thể gọi hàm winapi bằng thư viện ctypes. Một cơ chế cho phép điều này được gọi là FFI: https://en.wikipedia.org/wiki/Foreign_function_interface – wombatonfire

Các vấn đề liên quan