2012-09-13 47 views
14

Tôi có một ứng dụng cần gửi một số dữ liệu đến máy chủ tại một thời điểm nào đó. Cách dễ dàng là đóng kết nối và sau đó mở lại khi tôi muốn gửi một thứ gì đó. Nhưng tôi muốn giữ kết nối mở để khi tôi muốn gửi dữ liệu, trước tiên tôi kiểm tra kết nối bằng chức năng này:Kiểm tra xem ổ cắm có được kết nối hay không

bool is_connected(int sock) 
{ 
    unsigned char buf; 
    int err = recv(sock,&buf,1,MSG_PEEK); 
    return err == -1 ? false : true; 
} 

Phần xấu là điều này không hiệu quả. Nó treo khi không có dữ liệu để nhận. Tôi có thể làm gì? Làm thế nào tôi có thể kiểm tra xem kết nối vẫn mở?

+3

http://stackoverflow.com/questions/4142012/how-to-find-the-socket-connection-state-in-c – BoBTFish

Trả lời

17

Đừng kiểm tra trước và sau đó gửi. Đó là nỗ lực lãng phí và sẽ không làm việc anyway - trạng thái có thể thay đổi giữa khi bạn kiểm tra và khi bạn gửi. Chỉ cần làm những gì bạn muốn làm và xử lý lỗi nếu nó không thành công.

Để kiểm tra trạng thái, sử dụng:

int error_code; 
int error_code_size = sizeof(error_code); 
getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, &error_code, &error_code_size); 
+1

Đúng ... nhưng đôi khi rất hữu ích khi kiểm tra xem ổ cắm có được kết nối hay không. Đặt nó thành non-block, và sau đó đọc với peek_msg là một cách tốt để gợi ra một mã lỗi để kiểm tra xem ổ cắm vẫn được kết nối. –

+2

@RafaelBaptista Tại sao? * Sử dụng * nó sẽ kiểm tra. Thử nghiệm đầu tiên không thể làm việc đáng tin cậy, vì lý do David đưa ra ở trên. – EJP

+0

@EJP: Tôi muốn kiểm tra kết nối máy khách đang hoạt động nên tôi không lãng phí tài nguyên trong trường hợp không. – che

12

Bạn cần bật hành vi không chặn, bằng cách đặt O_NONBLOCK sử dụng fcntl. Một cách dễ dàng nhưng không phải là tiêu chuẩn để làm một non-blocking đọc sẽ được sử dụng:

recv(sock, &buf, 1, MSG_PEEK | MSG_DONTWAIT); 

Sau đó, bạn phải séc errno nếu nó không thành công. Nó có thể thất bại với EAGAIN hoặc nó có thể thất bại với EBADF hoặc ENOTCONN, vv


Rõ ràng, cách đơn giản nhất và sạch nhất để đối phó với điều này sẽ là để tránh "quên" nếu các ổ cắm được kết nối hay không. Bạn sẽ nhận thấy nếu các ổ cắm bị ngắt kết nối khi một recv trả về 0 hoặc một send trả về EPIPE.

+2

này sẽ không phát hiện tất cả các lỗi kết nối. Chỉ một send() mới có thể làm điều đó. – EJP

+0

@EJP Đó là sự thật trong thực tế. Tôi chỉ cải thiện giải pháp của op. Những gì bạn đang đề xuất là giải pháp chống đạn duy nhất, nhưng nó đòi hỏi phải gửi. – cnicutar

2

Mặc định việc sử dụng TCP không cho phép phát hiện kịp thời các ổ cắm chết (ngoài đóng cửa bình thường) nên tôi cho rằng chức năng "is_connected" như thế này phần lớn là vô ích cho mọi mục đích thực tế. Xem xét việc triển khai lớp ứng dụng tiếp tục và theo dõi nếu nó còn sống dựa trên các phản hồi kịp thời (hoặc thiếu nó).

chỉnh sửa: sau khi đăng, tôi thấy liên kết của BoBTFish, có hiệu quả giống nhau.

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