Các cuộc gọi song song để gửi / recv trên cùng một ổ cắm có hợp lệ không?


126
  1. Chúng ta có thể gọi gửi từ một chủ đề và recv từ một chủ đề khác trên cùng một ổ cắm không?
  2. Chúng ta có thể gọi nhiều lần gửi song song từ các luồng khác nhau trên cùng một ổ cắm không?

Tôi biết rằng một thiết kế tốt nên tránh điều này, nhưng tôi không rõ các API hệ thống này sẽ hoạt động như thế nào. Tôi không thể tìm thấy một tài liệu tốt cho cùng.

Bất kỳ con trỏ theo hướng sẽ hữu ích.


2
Tại sao bạn cho rằng làm như vậy là một thực hành xấu?. Nó có vẻ tốt với tôi bởi vì bạn lắng nghe và nhận được từ các chủ đề khác nhau.
TheMathNoob

Câu trả lời:


92

POSIX định nghĩa gửi / recv là các hoạt động nguyên tử, vì vậy giả sử bạn đang nói về POSIX send / recv thì có, bạn có thể gọi chúng đồng thời từ nhiều luồng và mọi thứ sẽ hoạt động.

Điều này không nhất thiết có nghĩa là chúng sẽ được thực thi song song - trong trường hợp nhiều lần gửi, lần thứ hai sẽ có khả năng chặn cho đến khi lần đầu tiên hoàn thành. Bạn có thể sẽ không nhận thấy điều này nhiều, vì việc gửi hoàn tất sau khi đưa dữ liệu của nó vào bộ đệm ổ cắm.

Nếu bạn đang sử dụng ổ cắm SOCK_STREAM, cố gắng thực hiện mọi thứ song song sẽ ít hữu ích hơn vì send / recv có thể gửi hoặc chỉ nhận một phần của tin nhắn, điều đó có nghĩa là mọi thứ có thể bị chia tách.

Chặn gửi / recv trên các ổ cắm SOCK_STREAM chỉ chặn cho đến khi chúng gửi hoặc recv ít nhất 1 byte, do đó, sự khác biệt giữa chặn và không chặn là không hữu ích.


1
@Joao: Ổ cắm SOCK_DGRAM được ghi lại là "giữ ranh giới tin nhắn", điều này không rõ ràng. Từ việc xem xét các nguồn nhân linux, ít nhất bạn có thể thấy rằng mỗi lần gửi và recv đều xử lý một gói duy nhất về nguyên tử (ít nhất là đối với udp).
Chris Dodd

2
@Kedar: không chắc ý của bạn là gì. Trả sendvề ngay khi dữ liệu được đặt vào bộ đệm gửi và dữ liệu được gửi qua ngăn xếp netowrk và ra ngoài mạng không đồng bộ. Vì vậy, nếu bạn có một luồng gửi và một luồng nhận, thì hoàn toàn có thể (thậm chí có khả năng) để luồng gửi gửi nhiều gói trước khi luồng nhận được gói đầu tiên. Nó hoàn toàn không đồng bộ và không đồng thời.
Chris Dodd

6
@ChrisDodd, bạn có thể cung cấp một liên kết cho "POSIX định nghĩa gửi / recv là hoạt động nguyên tử" không?
suitianshi

2
@suitianshi: Tài liệu chuẩn POSIX 1003.1c liệt kê tất cả các chức năng trong 1003.1 được reentrant (an toàn để gọi từ các luồng) và không. Thật không may, tôi không biết về một bản sao trực tuyến miễn phí có sẵn ở bất cứ đâu.
Chris Dodd

2
@ChrisDodd Tôi đã tìm thấy bản sao trên unix-systems.org/version4 và tôi có thể xem danh sách Bảng giao diện hệ thống ở chương 7.1 nhưng không thấy nơi nó liệt kê các chức năng là hoạt động nguyên tử. Không nghi ngờ bạn, nhưng bạn có thể vui lòng chia sẻ / chỉnh sửa câu trả lời của bạn để chứng minh quan điểm của bạn trong tài liệu không?
dùng153882

17

Bộ mô tả ổ cắm thuộc về quy trình, không thuộc về một chủ đề cụ thể. Do đó, có thể gửi / nhận đến / từ cùng một ổ cắm trong các luồng khác nhau, HĐH sẽ xử lý đồng bộ hóa.

Tuy nhiên, nếu thứ tự gửi / nhận có ý nghĩa về mặt ngữ nghĩa, thì chính bạn (tương ứng mã của bạn) phải đảm bảo sắp xếp hợp lý giữa các hoạt động trong các luồng khác nhau - như mọi trường hợp với các luồng.


4

Tôi không thấy cách nhận song song có thể hoàn thành bất cứ điều gì. Nếu bạn có thông báo 3 byte, 1 luồng có thể nhận được 2 byte đầu tiên và một byte khác cuối cùng, nhưng bạn không có cách nào để biết đó là byte nào. Trừ khi tin nhắn của bạn chỉ dài một byte, không có cách nào đáng tin cậy để bạn có thể làm bất cứ điều gì hoạt động với nhiều luồng nhận được.

Nhiều lần gửi có thể hoạt động, nếu bạn đã gửi toàn bộ tin nhắn trong một cuộc gọi, nhưng tôi không chắc chắn. Có khả năng người ta có thể ghi đè lên người khác. Chắc chắn sẽ không có bất kỳ lợi ích hiệu suất để làm như vậy.

Nếu nhiều luồng cần gửi, bạn nên thực hiện hàng đợi tin nhắn được đồng bộ hóa. Có một luồng thực hiện gửi thực tế đọc tin nhắn từ hàng đợi và có các luồng khác liệt kê toàn bộ tin nhắn. Điều tương tự sẽ hoạt động để nhận, nhưng luồng nhận sẽ phải biết định dạng của các tin nhắn để nó có thể giải nén chúng đúng cách.


9
Nếu bạn đang sử dụng ổ cắm SOCK_DGRAM, mỗi recv sẽ nhận được một datagram duy nhất; nó sẽ không bao giờ được phân chia giữa các recvs
Chris Dodd

2
@noah, tôi đồng ý recvs song song không thể hoàn thành bất cứ điều gì. Đó là lý do tại sao tôi không hỏi nó. Câu hỏi của tôi là gửi / recv song song và sau đó nhiều lần gửi song song. Câu trả lời của bạn không cung cấp một cái nhìn sâu sắc vào gửi song song. Cảm ơn vì cùng.
Jay

1
@Chris điểm tốt. Tôi đã giả sử TCP. @Jay Bạn có thể làm rõ câu hỏi "Chúng tôi có thể gọi gửi / recv song song" nghe giống như bạn muốn nhận song song không.
noah
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.