2011-03-04 8 views
3

TCP 소켓 (인터넷 도메인)을 기반으로 클라이언트 서버 프로그램을 설계하고 테스트하고 있습니다. 현재 로컬 컴퓨터에서 테스트 중이며 SIGPIPE에 대한 다음 내용을 이해할 수 없습니다.TCP 클라이언트 - 서버 SIGPIPE

*. SIGPIPE는 무작위로 나타납니다. 그것은 결정 론적 일 수 있습니까?

첫 번째 테스트에는 클라이언트에서 하나의 작은 (25 자) 보내기 작업과 서버에서 해당 수신이 포함됩니다. 동일한 컴퓨터에서 동일한 코드가 성공적으로 실행되거나 (SIGPIPE) 완전히 제어 할 수 없습니다. 실패율은 약 45 % (매우 높음)입니다. 그래서, 나는 이것을 최소화하기 위해 기계를 어떤 식 으로든 조정할 수 있습니까?

**. 두 번째 테스트에서는 클라이언트에서 서버 (총 1MB의 데이터)에 대해 40000 개의 작은 (25 자) 메시지를 보낸 다음 서버가 실제로받은 총 데이터 크기에 응답했습니다. 클라이언트는 긴밀한 루프에서 데이터를 보내고 서버에 단일 수신 호출이 있습니다. 최대 1200 바이트의 전체 데이터를 전송할 때만 작동하며, 비 결정적 SIGPIPE가 약 70 % 나되었습니다 (실제로는 좋지 않습니다).

내 디자인에 약간의 개선이있을 수 있습니까? (아마도 서버에있을 것입니다). 서버에 대한 단일 소켓 연결이 이루어지면 클라이언트는 중간에서 매우 많은 양의 데이터 (각 메시지 당 약 25 자)를 보낼 수 있어야합니다. 하나의 수신에 대한 여러 번의 전송은 항상 손실이 많고 비효율적이라고 생각합니다. 메시지를 결합하고 하나의 send() 작업 만 보내야합니다. 그게 유일한 방법인가요?

답변

7

연결되지 않은 파이프/소켓에 쓰려고하면 SIGPIPE가 전송됩니다. 시그널에 대한 핸들러를 설치하면 send()가 대신 오류를 반환합니다.

signal(SIGPIPE, SIG_IGN); 

또는, 소켓 SIGPIPE를 비활성화 할 수 있습니다

int n = 1; 
setsockopt(thesocket, SOL_SOCKET, SO_NOSIGPIPE, &n, sizeof(n)); 

또한, 데이터는 언급하고 매우 높지 않다 금액. 아마도 어딘가에 당신의 연결이 예기치 않게 닫히는 SIGPIPE를주는 버그가있을 것입니다.

+1

SO_NOSIGPIPE는 이식 할 수 없습니다. 여기를 참조하십시오 : http://stackoverflow.com/questions/108183/how-to-prevent-sigpipes-or-handle-them-properly –

1

닫힌 소켓에 쓰기를 시도하기 때문에 SIGPIPE가 발생합니다. 이것은 가능한 버그를 나타내므로 응용 프로그램이 왜 발생하는지 확인하고 먼저 수정하십시오.

SIGPIPE를 그냥 마스크하려고하는 것은 실제로 신호가 어디서 오는지 알지 못하기 때문에 SIGPIPE의 다른 소스를 가릴 수 있기 때문에 좋은 생각이 아닙니다. 멀티 스레드 환경에서 신호는 끔찍한 해결책입니다.

드문 경우이지만 이것을 피할 수 없으므로 신호를 보낼 때 마스크 할 수 있습니다. send()/sendto()MSG_NOSIGNAL 플래그를 설정하면 SIGPIPE이 발생하지 않습니다. 이 오류를 트리거하면 send()이 -1을 반환하고 errnoEPIPE으로 설정됩니다. 깨끗하고 쉽게. 자세한 내용은 man send을 참조하십시오.