POSIX 소켓을 플러시하는 방법이 있습니까?
POSIX 소켓의 송신측을 리모트엔드까지 플러시하는 표준 콜이 있습니까?아니면 사용자 레벨 프로토콜의 일부로 구현해야 합니까?늘 쓰던 머리글자를 둘러봤지만 아무것도 찾을 수가 없었어요.
TCP_NODELAY 를 설정하고, 리셋 하는 것보다 리셋 하는 것은 어떻습니까?아마 중요한 데이터를 보내기 직전이나 메시지 발송이 끝나면 할 수 있을 것입니다.
send(sock, "notimportant", ...);
send(sock, "notimportant", ...);
send(sock, "notimportant", ...);
int flag = 1;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
send(sock, "important data or end of the current message", ...);
flag = 0;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
Linux man 페이지에 기재되어 있듯이
TCP_NODELAY... 이 옵션을 설정하면 보류 중인 출력의 명시적 플러시가 강제됩니다.
따라서 메시지 뒤에 설정하는 것이 좋을 것 같습니다만, 다른 시스템에서는 어떻게 동작하는지는 잘 모르겠습니다.
Unix-domain 소켓의 경우fflush()
네트워크 소켓을 말하는 것 같습니다.그것들을 플러싱하는 개념이 실제로 없다.가장 가까운 것은 다음과 같습니다.
세션 종료 시 콜
shutdown(sock, SHUT_WR)
소켓의 쓰기를 종료합니다.TCP 소켓에서 sockopt를 사용한 Nagle 알고리즘 비활성화
TCP_NODELAY
초동 조사에서는 처리되는 것처럼 보여도 안심하고 할 수 없는 것이 일반적입니다.
사용자 프로토콜 수준에서 'flush'를 요구하는 문제를 처리하는 것이 올바른 일일 수 있습니다.
RFC 1122 에서는, 찾고 있는 제품의 이름은 「PUSH」입니다.다만, 「PUSH」를 실장하는 관련 TCP API 실장은 없는 것 같습니다.아아, 운이 없군.
일부 응답 및 댓글은 Nagle 알고리즘을 다루고 있습니다.대부분의 경우 Nagle 알고리즘이 매번 전송을 지연시킨다고 가정합니다.이 가정은 틀렸다.Nagle은 이전 패킷 중 적어도1개가 아직 확인 응답되지 않은 경우에만 송신을 지연합니다(http://www.unixguide.net/network/socketfaq/2.11.shtml)).
바꿔 말하면, TCP 는 (패킷 행의) 첫 번째 패킷을 즉시 송신합니다.접속이 느리고 컴퓨터가 적시에 확인을 받지 못하는 경우에만 Nagle은 다음 데이터 전송이 지연됩니다(어느 쪽이든 먼저 발생하는 경우).
- 타임아웃에 도달하거나
- 확인 응답되지 않은 마지막 패킷이 확인 응답된 경우
- 송신 버퍼가 꽉 찼습니다.
- Nagle을 비활성화하거나
- 접속의 송신 방향을 셧다운 했다.
적절한 완화 방법은 후속 데이터의 비즈니스를 가능한 한 피하는 것입니다.이것은 다음을 의미합니다.응용 프로그램이 호출하는 경우send()
1 개의 복합 요구를 송신하는 경우는, 애플리케이션의 재작성을 시도합니다.복합요구를 사용자 공간에서 조립한 후 콜합니다.send()
1회. 콘텍스트스위치에서도 절약됩니다(대부분의 사용자 공간 조작보다 훨씬 비쌉니다).
또, 송신 버퍼에 네트워크 패킷의 최대 사이즈를 채울 수 있는 충분한 데이터가 포함되어 있는 경우, Nagle도 지연하지 않습니다.이것은 다음을 의미합니다.송신한 마지막 패킷이 송신 버퍼에 가득 찰 정도로 큰 경우, TCP 는 어떠한 경우에도 가능한 한 빨리 데이터를 송신합니다.
요약하면 Nagle은 패킷플래그먼테이션을 줄이기 위한 무차별적인 접근법이 아닙니다.반대로:사용자 데이터와 헤더 데이터 간의 응답 시간과 비율을 모두 양호하게 유지하는 것은 유용하고 역동적이며 효과적인 접근 방식이라고 생각합니다.말하자면, 당신은 그것을 효율적으로 다룰 줄 알아야 합니다.
표준 TCP/IP 소켓인터페이스에서는, 데이터를 「리모트 엔드까지」플래시 해, 실제로 확인 응답을 얻을 수 있는 방법은 없습니다.
일반적으로 프로토콜에 "실시간" 데이터 전송이 필요한 경우 일반적으로 가장 좋은 방법은 다음을 설정하는 것입니다.setsockopt()
의TCP_NODELAY
이것에 의해, 보다 많은 바이트가 사용 가능하게 될 때까지 대기해, 모든 TCP 레벨 타이머를 사용해 송신 타이밍을 결정하는 대신에, 보다 직접적으로 네트워크에 송신하기 위해서, 프로토콜 스택내의 Nagle 알고리즘이 디세블이 되어, 소켓상의 write() 또는 send()가 맵 됩니다.메모: Nagle을 해제해도 TCP 슬라이딩 창은 비활성화되지 않으므로 항상 안전합니다.다만, 「실시간」속성이 필요 없는 경우는, 패킷의 오버헤드가 큰폭으로 상승할 가능성이 있습니다.
게다가 통상의 TCP 소켓메커니즘이 어플리케이션에 맞지 않는 경우는, 일반적으로 UDP 를 사용해 UDP 의 기본적인 송수신 속성을 기초로 독자적인 프로토콜 기능을 구축하는 것이 필요합니다.이것은, 프로토콜이 특별한 요구를 가지고 있는 경우, 매우 일반적인 일이지만, 이것을 적절히 실시해, 모든 것을 취득하는 것의 복잡성을 과소평가하지 말아 주세요.비교적 단순한 어플리케이션을 제외한 모든 어플리케이션에서 ble 및 기능적으로 정확합니다.우선 TCP의 설계 기능에 대한 철저한 연구는 고려해야 할 많은 문제를 밝혀낼 것입니다.
I think it would be extremely difficult, if not impossible to implement correctly. What is the meaning of "flush" in this context? Bytes transmitted to network? Bytes acknowledged by receiver's TCP stack? Bytes passed on to receiver's user-mode app? Bytes completely processed by user-mode app?
Looks like you need to do it at the app level...
TCP gives only best-effort delivery, so the act of having all the bytes leave Machine A is asynchronous with their all having been received at Machine B. The TCP/IP protocol stack knows, of course, but I don't know of any way to interrogate the TCP stack to find out if everything sent has been acknowledged.
By far the easiest way to handle the question is at the application level. Open a second TCP socket to act as a back channel and have the remote partner send you an acknowledgement that it has received the info you want. It will cost double but will be completely portable and will save you hours of programming time.
You could set the tcp option SO_LINGER to set a certain timeout and then close the socket in order to make sure all data has been sent (or detect failure to do so) upon the closeing of a connection. Other than that, TCP is a "best effort" protocol, and it doesn't provide any real guarantees that data will ever actually reach the destination (in contrast to what some seems to believe), it just tries it best to get it delivered in correct order and as soon as possible.
There is a linux-specific way to do this on TCP sockets:
You don't force the tcp stack to "send out data immediately", but remember that you and kernel are sending data as fast as you can. You can slightly reduce the delay between send
and actual delivery with TCP_NODELAY
.
But basically, by doing send
you've done your part and you just have to wait for tcp to do its part.
You can Use ioctl
on the socket with SIOCOUTQ
or TIOCOUTQ
to query the status of delivery and just wait until it's finished. This should be be enough. Especially for use-cases like sending an application-level packet fragments.
Use fsync():
sock_descript는 소켓(...) 호출의 정수 파일 기술자입니다.
fsync(filename_filename);
언급URL : https://stackoverflow.com/questions/855544/is-there-a-way-to-flush-a-posix-socket
'source' 카테고리의 다른 글
다른 스레드의 주 스레드에서 실행 중인 코드 (0) | 2022.08.03 |
---|---|
vuex를 사용하여 항목을 삭제하는 방법 (0) | 2022.08.03 |
'안드로이드'를 어떻게 고치죠?Network On Main Thread Exception'? (0) | 2022.08.03 |
롬복은 어떻게 작동하나요? (0) | 2022.08.01 |
문자열이 null과 동일한지 확인하는 방법 (0) | 2022.08.01 |