2012-07-05 47 views
5

Đây không phải là câu hỏi về cách thực hiện việc này, nhưng là câu hỏi về việc đó có phải là điều tôi đang làm không đúng. Tôi đã đọc rằng không thể phát hiện xem ổ cắm có bị đóng đột ngột hay không (như giết chết quy trình máy chủ/máy khách, kéo cáp mạng) trong khi chờ dữ liệu (BeginReceive), không sử dụng bộ hẹn giờ hoặc tin nhắn được gửi thông thường, v.v. trong một thời gian dài, tôi đã sử dụng các thiết lập sau để làm điều này, và cho đến nay nó đã luôn luôn làm việc hoàn hảo.Phát hiện ngắt kết nối không mong muốn

public void OnReceive(IAsyncResult result) 
{ 
    try 
    { 
     var bytesReceived = this.Socket.EndReceive(result); 

     if (bytesReceived <= 0) 
     { 
      // normal disconnect 
      return; 
     } 

     // ... 

     this.Socket.BeginReceive...; 
    } 
    catch // SocketException 
    { 
     // abnormal disconnect 
    } 
} 

Bây giờ, vì tôi đã đọc nó không dễ dàng, tôi tự hỏi nếu có điều gì sai với phương pháp của tôi. Lanhung? Hay có sự khác biệt giữa quá trình giết và kéo cáp và tương tự?

Trả lời

12

Hoàn toàn có thể và OK để thực hiện việc này. Ý tưởng chung là:

Nếu EndReceive trả về bất kỳ thứ gì khác ngoài số, bạn có dữ liệu đến để xử lý.

Nếu EndReceive trả lại số không, máy chủ từ xa đã đóng hết kết nối. Điều đó có nghĩa là nó vẫn có thể nhận được dữ liệu bạn gửi nếu nó được lập trình để làm như vậy, nhưng không thể gửi thêm bất kỳ thông tin nào trong bất kỳ trường hợp nào. Thông thường khi điều này xảy ra, bạn cũng sẽ đóng kết thúc của bạn kết nối do đó hoàn thành một trật tự tắt máy, nhưng đó không phải là bắt buộc.

Nếu EndReceive ném, đã có kết thúc bất thường của kết nối (quá trình bị giết, cắt cáp mạng, mất điện, v.v.).

Một vài điểm bạn cần phải chú ý đến:

  1. EndReceive không bao giờ có thể trở lại nhỏ hơn không (kiểm tra trong mã của bạn được gây hiểu lầm).
  2. Nếu nó ném nó có thể ném các loại ngoại lệ khác ngoài SocketException.
  3. Nếu trả về 0, bạn phải cẩn thận để ngừng gọi BeginReceive; nếu không, bạn sẽ bắt đầu một trò chơi ping-pong vô hạn và vô nghĩa giữa BeginReceiveEndReceive (nó sẽ hiển thị trong việc sử dụng CPU của bạn). Mã của bạn đã làm điều này, vì vậy không cần phải thay đổi bất cứ điều gì.
+0

+1 đặc biệt vì tôi thích cách bạn đặt "nếu nó được lập trình để làm như vậy". –

+2

+1 Tôi cũng muốn chỉ ra rằng bạn không bao giờ nên có một tuyên bố bắt mà bắt tất cả mọi thứ trừ khi nó lại ném nó. –

+1

@ Alex Tôi không đồng ý với việc cấm bắt tất cả các trường hợp ngoại lệ trừ khi bạn thực hiện lại chúng. Tôi có một lớp máy chủ TCP, hoạt động rất giống với lớp ở đây và tôi không muốn có một số ngoại lệ ngẫu nhiên để chấm dứt toàn bộ ứng dụng máy chủ. Đó là lý do tại sao tôi bắt tất cả Ngoại lệ và chuyển chúng sang Trình xử lý sự kiện OnExceptionCaught, cần được kết nối với một số chức năng ghi nhật ký, v.v. – Algoman

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