- Czy możemy wywołać send z jednego wątku i recv z innego na tym samym gnieździe?
- Czy możemy wywołać wiele wysyłek równolegle z różnych wątków w tym samym gnieździe?
Wiem, że dobry projekt powinien tego unikać, ale nie jestem pewien, jak zachowają się te systemowe API. Nie mogę znaleźć dobrej dokumentacji również do tego samego.
Pomocne będą wszelkie wskazówki dotyczące kierunku.
c
networking
sockets
Sójka
źródło
źródło
Odpowiedzi:
POSIX definiuje send / recv jako operacje atomowe, więc zakładając, że mówisz o POSIX send / recv, to tak, możesz wywoływać je jednocześnie z wielu wątków i wszystko będzie działać.
Nie musi to koniecznie oznaczać, że będą wykonywane równolegle - w przypadku wielu wysyłek druga prawdopodobnie będzie blokowana do zakończenia pierwszej. Prawdopodobnie nie zauważysz tak bardzo, ponieważ wysyłanie kończy się, gdy umieści swoje dane w buforze gniazda.
Jeśli używasz gniazd SOCK_STREAM, próba wykonania czynności równoległych jest mniej przydatna, ponieważ send / recv może wysłać lub odebrać tylko część wiadomości, co oznacza, że rzeczy mogą się rozdzielić.
Blokowanie wysyłania / odbierania na gniazdach SOCK_STREAM blokuje tylko do momentu wysłania lub odebrania co najmniej 1 bajtu, więc różnica między blokowaniem a nieblokowaniem nie jest użyteczna.
źródło
send
powraca, gdy tylko dane zostaną umieszczone w buforze wysyłania, a dane są przesyłane przez stos sieciowy i asynchronicznie do sieci. Więc jeśli masz jeden wątek wysyłający i jeden odbierający, jest całkowicie możliwe (nawet prawdopodobne) wysłanie przez wątek wysyłający wielu pakietów, zanim wątek odbierający otrzyma pierwszy pakiet. Jest całkowicie asynchroniczny i nie symultaniczny.Deskryptor gniazda należy do procesu, a nie do określonego wątku. W związku z tym możliwe jest wysyłanie / odbieranie do / z tego samego gniazda w różnych wątkach, system operacyjny zajmie się synchronizacją.
Jeśli jednak kolejność wysyłania / odbierania jest znacząca semantycznie, Ty sam (odpowiednio Twój kod) musisz zapewnić odpowiednią sekwencję między operacjami w różnych wątkach - jak zawsze w przypadku wątków.
źródło
Nie widzę, jak równoległe odbieranie mogłoby cokolwiek osiągnąć. Jeśli masz wiadomość 3-bajtową, jeden wątek może otrzymać pierwsze 2 bajty, a drugi ostatni bajt, ale nie możesz stwierdzić, który jest który. Jeśli twoje wiadomości nie mają długości tylko bajtu, nie ma możliwości, aby cokolwiek działało niezawodnie przy odbieraniu wielu wątków.
Wiele wysyłek może zadziałać, jeśli wysłałeś całą wiadomość w jednym połączeniu, ale nie jestem pewien. Możliwe, że jeden mógłby nadpisać inny. Z pewnością nie przyniosłoby to żadnych korzyści w zakresie wydajności.
Jeśli trzeba wysłać wiele wątków, należy zaimplementować zsynchronizowaną kolejkę wiadomości. Miej jeden wątek, który wykonuje faktyczne wysyłanie, który czyta wiadomości z kolejki, a pozostałe wątki kolejkują całe wiadomości. To samo działałoby w przypadku odbierania, ale wątek odbioru musiałby znać format wiadomości, aby mógł je prawidłowo deserializować.
źródło