Tôi có một chương trình máy chủ mạng hướng sự kiện. Chương trình này chấp nhận các kết nối từ các quá trình khác trên các máy chủ khác. Có thể có nhiều kết nối ngắn ngủi từ các cổng khác nhau trên cùng một IP từ xa.Sử dụng accept() và chọn() cùng một lúc?
Hiện tại, tôi có một vòng lặp while(1)
gọi accept()
và sau đó sinh ra một luồng để xử lý kết nối mới. Mỗi kết nối được đóng lại sau khi tin nhắn được đọc. Ở đầu từ xa, kết nối sẽ bị đóng sau khi tin nhắn được gửi đi.
Tôi muốn loại bỏ chi phí của việc thiết lập và xé các kết nối bằng cách lưu bộ nhớ đệm các ổ cắm FD mở. Về phía người gửi, điều này rất dễ dàng - tôi chỉ không đóng các kết nối và giữ chúng xung quanh.
Ở phía người nhận, khó hơn một chút. Tôi biết tôi có thể lưu trữ FD trả về accept()
trong cấu trúc và nghe tin nhắn trên tất cả các ổ cắm như vậy bằng cách sử dụng poll()
hoặc select()
, nhưng tôi muốn đồng thời cả hai đều nghe kết nối mới qua số accept()
và nghe trên tất cả các kết nối được lưu trong bộ nhớ cache.
Nếu tôi sử dụng hai luồng, một trên poll()
và một trên accept()
, sau đó khi trả về cuộc gọi accept()
(kết nối mới), tôi phải đánh thức luồng khác đang chờ kết nối cũ. Tôi biết tôi có thể làm điều này với một tín hiệu và pselect()
, nhưng toàn bộ mớ hỗn độn này có vẻ như cách quá nhiều công việc cho một cái gì đó rất đơn giản.
Có cuộc gọi hoặc phương pháp vượt trội nào sẽ cho phép tôi xử lý đồng thời các kết nối mới đang được mở và dữ liệu được gửi trên các kết nối cũ không?
Hmm, đó là một điều kiện chủng tộc nổi tiếng - 'accept (2)' sẽ chặn nếu khách hàng giảm nỗ lực kết nối giữa hai syscalls. Bạn * cần * ổ cắm nghe không bị chặn. –
Điều này là đúng - bạn có thể thêm bộ mô tả tập tin nghe của bạn vào 'readfds' trong lệnh' select() ', và' select() 'sẽ cho bạn biết bộ mô tả tập tin là" có thể đọc được "nếu nó có kết nối sẵn sàng để' accept() '. @Nikolai cũng chính xác - ổ cắm nghe không được chặn và lệnh 'accept()' được chuẩn bị để xử lý 'EAGAIN'. – caf