2010-02-10 24 views
8

Trong mã khách hàng của tôi, tôi đang làm theo các bước sau để kết nối với một ổ cắm:Tái sử dụng mô tả ổ cắm trên kết nối thất bại

  1. Tạo cổng

    sockDesc = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) 
    
  2. Connecting nó (thử lại cho 'x 'thời gian trong trường hợp thất bại)

    connect(sockDesc, (sockaddr *) &destAddr, sizeof(destAddr)) 
    

    (Sau khi điền destAddr trường)

  3. Sử dụng ổ cắm cho send()/recv() hoạt động:

    send(sockDesc, buffer, bufferLen, 0) 
    recv(sockDesc, buffer, bufferLen, 0) 
    
  4. close() mô tả ổ cắm và thoát

    close(sockDesc) 
    

Nếu trong quá trình send()/recv() ngắt kết nối, tôi thấy rằng Tôi có thể kết nối bằng cách quay lại bước 2.

Giải pháp này có được không? Tôi có nên đóng bộ mô tả socket và quay lại bước 1 không?

Một quan sát thú vị khác mà tôi không thể hiểu là khi Tôi dừng máy chủ echo và khởi động máy khách. Tôi tạo ra một Socket (bước 1) và gọi connect() mà không thành công (như mong đợi) nhưng sau đó tôi tiếp tục gọi connect(), cho phép nói, 10 lần. Sau 5 lần thử lại, tôi khởi động máy chủ và connect() thành công. Nhưng trong khi gọi send() cuộc gọi sẽ nhận được lỗi SIGPIPE. Tôi muốn biết:

1) Tôi có cần tạo ổ cắm mới mỗi lần connect() không thành công? Theo sự hiểu biết của tôi miễn là tôi chưa thực hiện bất kỳ send()/recv() nào trên ổ cắm, nó cũng tốt như mới và tôi có thể sử dụng lại cùng một số fd cho cuộc gọi connect().

2) Tôi không hiểu tại sao SIGPIPE được nhận khi máy chủ kết thúc và connect() thành công.

+0

Sau khi thay đổi mã như đề xuất đóng bộ mô tả scoket và tạo ổ cắm mới và kết nối nó, vấn đề SIGPIPE không còn xảy ra nữa. – Adil

+1

Tôi thấy liên kết này hữu ích và có liên quan đến câu hỏi của bạn khi bạn sử dụng gửi thay vì viết: http://stackoverflow.com/questions/9048959/write-and-send-solving-errors-difference –

Trả lời

5

Có, bạn nên đóng và quay lại bước 1:

close() đóng một bộ mô tả tập tin, để nó không còn đề cập đến bất kỳ tập tin và có thể được tái sử dụng.

Từ here.

+0

Bất kỳ lý do cụ thể nào? Khi tôi đang sử dụng cùng một fd trong cuộc gọi kết nối để kết nối lại với máy chủ và không tạo bất kỳ ổ cắm mới nào, nó sẽ không gây hại? hoặc trong trường hợp này socket đi vào trạng thái chờ đợi hoặc một cái gì đó? – Adil

+0

Các thông số kỹ thuật cũng gợi ý rằng "tệp" không còn đề cập đến bất cứ điều gì. Với tôi điều này chỉ ra rằng xử lý vẫn còn hợp lệ tuy nhiên nó cần phải được tái khởi tạo. –

4

Ổ cắm tương ứng với kết nối bị hỏng ở trạng thái không ổn định. thông thường bạn sẽ không được phép kết nối lại trừ khi hệ điều hành nhả ổ cắm.

Tôi nghĩ sẽ tốt hơn nếu đóng() và kết nối lại .. bạn không phải tạo ổ cắm khác.

Dù sao, hãy đảm bảo đặt LINGER của ổ cắm của bạn để đảm bảo rằng không có dữ liệu nào bị mất trong quá trình truyền.

Xem http://www.gnu.org/s/libc/manual/html_node/Socket_002dLevel-Options.html#Socket_002dLevel-Options

+0

Nếu tôi đóng bộ mô tả, tôi nghĩ rằng tôi cần phải tạo lại socket vì việc đóng bộ mô tả có nghĩa là phá hủy socket, phải không? – Adil

+0

Sau khi một ổ cắm đã được 'close()' d bạn sẽ không sử dụng bộ mô tả socket nữa. Nó là không hợp lệ sau đó. Sử dụng 'socket()' để thu hút một bộ mô tả socket mới. – alk

2

Nếu kết nối bị hỏng và bạn cố gắng viết trên mô tả tập tin bạn sẽ nhận được những tấm lỗi ống/tín hiệu. Tất cả điều này là nói rằng các mô tả tập tin bạn đã cố gắng viết để không còn có bất cứ ai ở phía bên kia để đọc những gì bạn đang gửi.

Những gì bạn có thể làm là bắt tín hiệu SIGPIPE và sau đó xử lý kết nối lại bằng cách đóng FD và quay lại bước của bạn 1. Bây giờ bạn sẽ có FD mới, bạn có thể đọc và ghi từ kết nối.

2

Nếu đặc tả UNIX đơn không nói rằng nó PHẢI làm việc để quay lại bướC# 2 thay vì bướC# 1, thì thực tế là nó hoạt động trên Linux chỉ là chi tiết triển khai, và bạn sẽ tốt hơn nhiều và di động hơn nếu bạn quay trở lại bướC# 1. Theo như tôi biết, đặc điểm kỹ thuật không đảm bảo rằng bạn có thể quay lại bướC# 2 và vì vậy, tôi khuyên bạn nên quay lại bướC# 1.

4

Tôi nghĩ việc đóng ổ cắm là điều đúng đắn để làm, mặc dù thực tế là nó có thể hoạt động nếu bạn không làm.

Ổ cắm không kết nối có thể không ở trạng thái tương tự như trạng thái hoàn toàn mới - điều này có thể gây ra sự cố sau này. Tôi muốn tránh khả năng và chỉ cần tạo ra một cái mới. Nó sạch hơn.

Ổ cắm TCP chứa rất nhiều trạng thái, một số trong đó là trạng thái triển khai cụ thể và được thực hiện từ mạng.

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