소켓 대 종료?
C에서 소켓을 닫으면 소켓이 파괴되어 나중에 재사용 할 수 있음을 이해했습니다.
셧다운은 어때? 설명에 따르면 해당 소켓에 대한 이중 연결의 절반이 닫힙니다. 그러나 소켓이 close
시스템 호출 처럼 파괴 됩니까?
이것은 Beej의 네트워킹 안내서에 설명 되어 있습니다. shutdown
한 방향 또는 두 방향으로 통신을 차단하는 유연한 방법입니다. 두 번째 매개 변수가 SHUT_RDWR
인 경우 (와 같은 close
) 전송 및 수신을 모두 차단합니다 . 그러나 close
실제로 소켓을 파괴하는 방법입니다.
를 사용 shutdown
하면 피어가 이미 보낸 보류중인 데이터를 계속받을 수 있습니다 (이 점에 대해 Joey Adams에게 감사드립니다).
기존 답변 중 어떤 것도 사람들에게 TCP 프로토콜 수준에서 방법 shutdown
과 close
작동 방식을 알려주지 않으므로 추가해야합니다.
표준 TCP 연결은 4 방향 종료에 의해 종료됩니다.
- 참가자가 더 이상 전송할 데이터가 없으면 FIN 패킷을 상대방에게 보냅니다.
- 상대방이 FIN에 대한 ACK를 반환합니다.
- 상대방도 데이터 전송을 마치면 다른 FIN 패킷을 보냅니다.
- 초기 참가자는 ACK를 반환하고 전송을 마무리합니다.
그러나 TCP 연결을 닫는 또 다른 "비상"방법이 있습니다.
- 참가자는 RST 패킷을 보내고 연결을 포기합니다
- 다른 쪽은 RST를 수신 한 후 연결을 포기합니다.
Wireshark를 사용한 테스트에서 기본 소켓 옵션 shutdown
을 사용하면 다른 쪽 끝으로 FIN 패킷을 보내지 만 그게 전부입니다. 상대방이 FIN 패킷을 보낼 때까지 데이터를 계속받을 수 있습니다. 이 일이 발생 Receive
하면 0 크기의 결과를 얻습니다. 따라서 "보내기"를 종료 한 첫 번째 사람이라면 데이터 수신을 마치면 소켓을 닫아야합니다.
close
반면, 연결이 여전히 활성 상태 인 동안 (다른 쪽이 여전히 활성 상태이고 시스템 버퍼에 데이터가 전송되지 않은 경우) 호출 하면 다른쪽으로 RST 패킷이 전송됩니다. 이것은 오류에 좋습니다. 예를 들어 상대방이 잘못된 데이터를 제공했거나 데이터 제공을 거부 한 경우 (DOS 공격?) 소켓을 즉시 닫을 수 있습니다.
규칙에 대한 나의 의견은 다음과 같습니다.
- 고려
shutdown
하기 전에close
가능하면 - 종료하기로 결정하기 전에 (0 크기 데이터 수신) 수신을 완료 한 경우 마지막 송신 (있는 경우)이 끝난 후 연결을 닫으십시오.
- 연결을 정상적으로 닫으려면 연결을 종료하고 (SHUT_WR을 사용하고이 시점 이후에 SHUT_RD를 사용하여 데이터 수신에 신경 쓰지 않는 경우) 0 크기의 데이터가 수신 될 때까지 기다렸다가 소켓.
- 어쨌든 다른 오류가 발생한 경우 (예 : 시간 초과) 소켓을 닫으십시오.
SHUT_RD 및 SHUT_WR에 대한 이상적인 구현
다음은 테스트를 거치지 않았으므로 자신의 책임을 신뢰하십시오. 그러나 나는 이것이 합리적이고 실용적인 방법이라고 생각합니다.
TCP 스택이 SHUT_RD만으로 셧다운을 수신하면 더 이상 데이터가 예상되지 않는 것으로이 연결을 표시해야합니다. 그런 다음 보류중인 read
요청 과 후속 요청 (어느 스레드에 관계없이)은 크기가 0 인 결과로 반환됩니다. 그러나 연결은 여전히 활성 상태이며 사용 가능합니다. 예를 들어 여전히 OOB 데이터를 수신 할 수 있습니다. 또한 OS는이 연결에 대해 수신 한 모든 데이터를 삭제합니다. 그러나 그게 전부입니다. 패키지는 다른쪽으로 보내지지 않습니다.
TCP 스택이 SHUT_WR만으로 종료를 수신하면 더 이상 데이터를 전송할 수 없으므로이 연결을 표시해야합니다. 보류중인 모든 쓰기 요청은 완료되지만 후속 쓰기 요청은 실패합니다. 또한 FIN 패킷은 다른쪽에 보내 져서 더 많은 데이터가 없다는 것을 알려줍니다.
대신 close()
사용하면 피할 수있는 몇 가지 제한 사항 이 있습니다 shutdown()
.
close()
TCP 연결에서 양방향을 종료합니다. 때로는 다른 엔드 포인트에 데이터 전송이 완료되었지만 여전히 데이터를 수신하고 싶다고 말하고 싶을 때가 있습니다.
close()
디스크립터 참조 수 (파일 테이블 항목에서 유지 보수되고 현재 파일 / 소켓을 참조하는 열린 디스크립터 수를 계산)를 줄이고 디스크립터가 0이 아닌 경우 소켓 / 파일을 닫지 않습니다. 즉, 포크하는 경우, 정리는 참조 카운트가 0으로 떨어진 후에 만 발생합니다 shutdown()
. 참조 카운트를 무시하고 정상적인 TCP 닫기 시퀀스를 시작할 수 있습니다.
매개 변수는 다음과 같습니다.
int shutdown(int s, int how); // s is socket descriptor
int how
될 수 있습니다 :
SHUT_RD
또는 0
추가 수신이 허용되지 않습니다
SHUT_WR
또는 1
추가 전송이 허용되지 않습니다
SHUT_RDWR
or 2
Further sends and receives are disallowed
This may be platform specific, I somehow doubt it, but anyway, the best explanation I've seen is here on this msdn page where they explain about shutdown, linger options, socket closure and general connection termination sequences.
In summary, use shutdown to send a shutdown sequence at the TCP level and use close to free up the resources used by the socket data structures in your process. If you haven't issued an explicit shutdown sequence by the time you call close then one is initiated for you.
I've also had success under linux using shutdown()
from one pthread to force another pthread currently blocked in connect()
to abort early.
Under other OSes (OSX at least), I found calling close()
was enough to get connect()
fail.
"shutdown() doesn't actually close the file descriptor—it just changes its usability. To free a socket descriptor, you need to use close()."1
Close
When you have finished using a socket, you can simply close its file descriptor with close; If there is still data waiting to be transmitted over the connection, normally close tries to complete this transmission. You can control this behavior using the SO_LINGER socket option to specify a timeout period; see Socket Options.
ShutDown
You can also shut down only reception or transmission on a connection by calling shutdown.
The shutdown function shuts down the connection of socket. Its argument how specifies what action to perform: 0 Stop receiving data for this socket. If further data arrives, reject it. 1 Stop trying to transmit data from this socket. Discard any data waiting to be sent. Stop looking for acknowledgement of data already sent; don’t retransmit it if it is lost. 2 Stop both reception and transmission.
The return value is 0 on success and -1 on failure.
in my test.
close
will send fin packet and destroy fd immediately when socket is not shared with other processes
shutdown
SHUT_RD, process can still recv data from the socket, but recv
will return 0 if TCP buffer is empty.After peer send more data, recv
will return data again.
shutdown
SHUT_WR will send fin packet to indicate the Further sends are disallowed. the peer can recv data but it will recv 0 if its TCP buffer is empty
shutdown
SHUT_RDWR (equal to use both SHUT_RD and SHUT_WR) will send rst packet if peer send more data.
참고URL : https://stackoverflow.com/questions/4160347/close-vs-shutdown-socket
'Programing' 카테고리의 다른 글
파일 또는 어셈블리 'System.Web.Mvc'를로드 할 수 없습니다 (0) | 2020.05.10 |
---|---|
캐시와 지속의 차이점은 무엇입니까? (0) | 2020.05.10 |
텍스트 인코딩을 결정하는 방법은 무엇입니까? (0) | 2020.05.09 |
SQL에서 count (column)과 count (*)의 차이점은 무엇입니까? (0) | 2020.05.09 |
C ++에서 int를 열거 형으로 캐스팅하는 방법은 무엇입니까? (0) | 2020.05.09 |