동일한 소켓에서 send / recv에 대한 병렬 호출이 유효합니까?


127
  1. 하나의 스레드에서 send를 호출하고 동일한 소켓의 다른 스레드에서 recv를 호출 할 수 있습니까?
  2. 동일한 소켓의 다른 스레드에서 여러 전송을 병렬로 호출 할 수 있습니까?

좋은 디자인은 이것을 피해야한다는 것을 알고 있지만 이러한 시스템 API의 작동 방식은 확실하지 않습니다. 나는 또한 좋은 문서를 찾을 수 없다.

방향에 대한 포인터가 도움이 될 것입니다.


3
왜 그렇게하는 것이 나쁜 습관이라고 주장합니까? 다른 스레드에서 듣고 수신하기 때문에 괜찮습니다.
TheMathNoob

답변:


92

POSIX는 send / recv를 원자 연산으로 정의하므로 POSIX send / recv에 대해 이야기하고 있다고 가정하면 여러 스레드에서 동시에 호출 할 수 있으며 작동합니다.

이것은 반드시 병렬로 실행될 것이라는 것을 의미하지는 않습니다. 여러 전송의 경우 두 번째는 첫 번째가 완료 될 때까지 차단 될 것입니다. 송신이 일단 데이터를 소켓 버퍼에 넣은 후에는 완료되므로이 점을 많이 알지 못할 것입니다.

SOCK_STREAM 소켓을 사용하는 경우 send / recv가 메시지의 일부만 보내거나받을 수 있으므로 병렬 작업을 시도하는 것이 유용하지 않을 수 있습니다.

SOCK_STREAM 소켓에서 send / recv를 차단하면 최소 1 바이트를 보내거나받을 때까지만 차단되므로 차단과 비 차단의 차이는 유용하지 않습니다.


1
@Joao : SOCK_DGRAM 소켓은 "메시지 경계 유지"로 문서화되어 있지만 명확하지 않습니다. 리눅스 커널 소스를 살펴보면 적어도 각 send 및 recv가 단일 패킷을 원자 적으로 처리한다는 것을 알 수 있습니다 (적어도 udp의 경우).
Chris Dodd

2
@Kedar : 무슨 뜻인지 잘 모르겠습니다. send데이터가 전송 버퍼에 배치 되 자마자 A가 반환되고 데이터가 netowrk 스택을 통해 전송되어 네트워크로 비동기 적으로 전송됩니다. 따라서 하나의 스레드 전송과 하나의 스레드 수신이있는 경우 수신 스레드가 첫 번째 패킷을 수신하기 전에 전송 스레드가 많은 패킷을 전송할 수 있습니다. 완전히 비동기 적이며 동시 적이 지 않습니다.
Chris Dodd

6
@ChrisDodd, "POSIX는 send / recv를 원자 연산으로 정의합니다"에 대한 링크를 줄 수 있습니까?
suitianshi

2
@suitianshi : POSIX 1003.1c 표준 문서는 1003.1에서 재진입 (스레드에서 호출해도 안전) 기능이 아닌 모든 기능을 나열합니다. 안타깝게도 어디에서나 무료 온라인 사본을 사용할 수 없습니다.
Chris Dodd

2
@ChrisDodd unix-systems.org/version4에서 사본을 찾았고 7.1 장에서 시스템 인터페이스 테이블 목록을 볼 수 있지만 기능이 원자 연산으로 나열되는 위치는 볼 수 없습니다. 의심의 여지가 없지만 문서의 요점을 정당화하기 위해 답변을 공유 / 편집 할 수 있습니까?
user153882

17

소켓 디스크립터는 특정 스레드가 아닌 프로세스에 속합니다. 따라서 다른 스레드에서 동일한 소켓으로 송수신 할 수 있으며 OS는 동기화를 처리합니다.

그러나 송신 / 수신 순서가 의미 적으로 중요한 경우, 항상 스레드와 마찬가지로 다른 스레드의 작업간에 적절한 순서를 지정해야합니다.


4

병렬로받는 것이 어떻게 성취 할 수 있는지 보지 못합니다. 3 바이트 메시지가있는 경우 1 스레드는 첫 번째 2 바이트와 다른 바이트를 얻을 수 있지만 어느 것이 어느 것인지 알 수는 없습니다. 메시지 길이가 1 바이트가 아닌 이상 여러 스레드 수신에서 안정적으로 작업 할 수있는 방법이 없습니다.

한 번의 호출로 전체 메시지를 보낸 경우 여러 번의 전송 작동 할 수 있지만 확실하지 않습니다. 하나는 다른 것을 덮어 쓸 수 있습니다. 그렇게하면 성능상의 이점이 없을 것입니다.

여러 스레드를 보내야하는 경우 동기화 된 메시지 큐를 구현해야합니다. 큐에서 메시지를 읽는 실제 전송을 수행하는 스레드 하나와 전체 메시지를 큐에 넣는 스레드가 있습니다. 수신에서도 마찬가지이지만 수신 스레드는 메시지의 형식을 알아야 직렬화를 해제 할 수 있습니다.


9
SOCK_DGRAM 소켓을 사용하는 경우 각 recv는 단일 데이터 그램을 얻습니다. 그것은 recvs 사이에 분할되지 않을 것입니다
크리스 Dodd

2
@noah, 병렬 recvs가 아무것도 달성 할 수 없다는 데 동의합니다. 내가 묻지 않은 이유입니다. 내 질문은 send / recv parallely이고 여러 개의 send parallely입니다. 귀하의 답변은 병렬 전송에 대한 통찰력을 제공합니다. 같은 주셔서 감사합니다.
Jay

1
@Chris 좋은 지적. TCP를 가정하고있었습니다. @Jay 당신은 병렬로 수신하고 싶은 것처럼 "우리는 / send / recv parallely를 호출 할 수 있습니까?"라는 질문을 명확히 할 수 있습니다.
noah
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.