소켓 라이브러리에서 recv를 호출할 때 사용하는 recv 버퍼 크기
C 소켓 라이브러리에 대해 몇 가지 질문이 있습니다.다음은 질문에서 참조할 코드 조각입니다.
char recv_buffer[3000];
recv(socket, recv_buffer, 3000, 0);
- recv_buffer 크기를 결정하려면 어떻게 해야 하나요?3000을 사용하고 있지만 임의입니다.
- 만약의 경우
recv()
내 버퍼보다 큰 패킷을 수신할 수 있습니까? - recv에 다시 전화하지 않고 전체 메시지를 받았는지 확인하고 수신할 것이 없을 때 메시지를 영원히 기다려야 하는지 어떻게 알 수 있습니까?
- 버퍼에 일정한 공간을 갖지 않고 공간이 부족해질 염려 없이 버퍼를 계속 추가할 수 있는 방법이 있을까요?
strcat
최신 정보를 연결하다recv()
버퍼에 대한 반응?
많은 질문들이 한꺼번에 쏟아지는 건 알지만 어떤 답변이라도 답변해주시면 감사하겠습니다.
이러한 질문에 대한 답변은 스트림소켓 사용 여부에 따라 달라집니다.SOCK_STREAM
또는 데이터그램 소켓(SOCK_DGRAM
): TCP/IP 에서는, 전자는 TCP 에 대응해, 후자는 UDP 에 대응합니다.
버퍼 크기를 어떻게 알 수 있습니까?recv()
?
SOCK_STREAM
별로 중요하지 않아요.프로토콜이 트랜잭션/인터랙티브 프로토콜인 경우, 합리적으로 예상할 수 있는 가장 큰 개별 메시지/명령어를 저장할 수 있는 크기를 선택하십시오(3000개면 충분합니다).프로토콜이 대량 데이터를 전송하는 경우 더 큰 버퍼가 더 효율적일 수 있습니다. 좋은 경험적 규칙은 소켓의 커널 수신 버퍼 크기(대개 약 256kB)와 비슷합니다.SOCK_DGRAM
: 어플리케이션레벨의 프로토콜이 송신한 패킷 중 가장 큰 패킷을 저장할 수 있는 버퍼를 사용합니다.UDP를 사용하는 경우 일반적으로 애플리케이션 수준 프로토콜이 약 1400바이트보다 큰 패킷을 전송해서는 안 됩니다. 이러한 패킷은 조각화하고 재구성해야 하기 때문입니다.
만약의 경우recv
버퍼보다 큰 패킷을 얻을 수 있을까요?
SOCK_STREAM
: 스트림 소켓에는 패킷의 개념이 없기 때문에 이 질문은 사실 이치에 맞지 않습니다.그것은 바이트의 연속적인 스트림일 뿐입니다.읽기 가능한 바이트 수가 버퍼 용량보다 많을 경우 해당 바이트는 OS에 의해 큐잉되어 다음 호출에 사용할 수 있습니다.recv
.SOCK_DGRAM
: 초과 바이트는 폐기됩니다.
메시지를 다 받았는지 어떻게 알 수 있나요?
SOCK_STREAM
: 응용 프로그램 수준 프로토콜에 메시지 종료를 결정하는 방법을 구축해야 합니다.일반적으로 이것은 길이 접두사(메시지 길이로 각 메시지를 시작) 또는 메시지 끝 구분자(텍스트 기반 프로토콜의 줄 바꿈일 수 있음) 중 하나입니다.세 번째, 덜 사용되는 옵션은 각 메시지에 고정 크기를 지정하는 것입니다.이러한 옵션의 조합도 가능합니다(예: 길이 값이 포함된 고정 크기 헤더).SOCK_DGRAM
: 싱글recv
call은 항상 단일 데이터그램을 반환합니다.
버퍼에 일정한 공간을 확보하지 않고 공간이 부족할 염려 없이 계속 추가할 수 있는 방법이 있습니까?
아니요. 하지만 버퍼 크기를 조정할 수 있습니다.realloc()
(처음 할당한 경우)malloc()
또는calloc()
(즉,)
TCP와 같은 스트리밍 프로토콜의 경우 버퍼를 거의 모든 크기로 설정할 수 있습니다.즉, 4096이나 8192와 같이 2의 거듭제곱인 공통값을 권장합니다.
어떤 버퍼보다 더 많은 데이터가 있는 경우 다음 호출을 위해 커널에 저장됩니다.recv
.
네, 버퍼를 계속 키울 수 있습니다.오프셋부터 버퍼 중앙으로 recv를 실행할 수 있습니다.idx
다음과 같은 작업을 수행합니다.
recv(socket, recv_buffer + idx, recv_buffer_size - idx, 0);
를 가지고 있는 경우SOCK_STREAM
소켓,recv
는 스트림에서 "최초 3000바이트까지"를 가져옵니다.버퍼의 크기에 대한 명확한 지침은 없습니다. 스트림이 얼마나 큰지 아는 것은 스트림이 모두 완료된 시점뿐입니다.-)
를 가지고 있는 경우SOCK_DGRAM
소켓, 데이터그램이 버퍼보다 큽니다.recv
버퍼에 데이터그램의 첫 번째 부분을 채우고 -1을 반환하고 EMSGSIZE로 errno를 설정합니다.불행하게도 프로토콜이 UDP이면 나머지 데이터그램이 손실된다는 것을 의미합니다.UDP가 신뢰할 수 없는 프로토콜이라고 불리는 이유의 일부입니다(신뢰할 수 있는 데이터그램 프로토콜이 있지만 그다지 인기가 없습니다.TCP/FAMIP에는 이름을 붙일 수 없습니다.후자를 꽤 잘 알면서도 말이다;-)
버퍼를 동적으로 확장하려면 처음에 버퍼를malloc
및 사용realloc
필요에 따라서,하지만 그것은 너에게 도움이 되지 않을 거예요recv
아아, UDP 소스로부터.
위해서SOCK_STREAM
소켓에서는 버퍼 사이즈는 중요하지 않습니다.대기 바이트의 일부를 풀하고 있기 때문에 다음 콜에서 더 많은 바이트를 취득할 수 있기 때문입니다.적당한 크기의 버퍼를 고르세요.
위해서SOCK_DGRAM
소켓, 당신은 대기 메시지의 적합한 부분을 얻을 것이고 나머지는 폐기될 것입니다.다음 ioctl을 사용하여 대기 데이터그램 크기를 얻을 수 있습니다.
#include <sys/ioctl.h>
int size;
ioctl(sockfd, FIONREAD, &size);
또는 다음 중 하나를 사용할 수 있습니다.MSG_PEEK
그리고.MSG_TRUNC
의 깃발recv()
콜을 실행하여 대기 데이터그램 크기를 가져옵니다.
ssize_t size = recv(sockfd, buf, len, MSG_PEEK | MSG_TRUNC);
당신은 필요하다MSG_PEEK
대기 중인 메시지를 엿보기(수신하지 않음) - recv는 잘라낸 크기가 아닌 실제 크기를 반환합니다.MSG_TRUNC
현재 버퍼를 오버플로하지 않도록 합니다.
그럼 그냥...malloc(size)
진짜 완충장치와recv()
데이터그램
테크놀로지는 항상 구현에 따라 달라지기 때문에 질문에 대한 확실한 답변은 없습니다.버퍼 사이즈가 입력되어도 TCP 통신에 문제가 되지 않기 때문에, UDP로 통신하고 있다고 생각합니다.
RFC 768에 따르면 UDP 패킷사이즈(헤더 포함)의 범위는 8 ~65,515 바이트입니다따라서 수신 버퍼의 장애 방지 크기는 65507바이트(~64KB)입니다.
다만, 모든 큰 패킷이 네트워크 디바이스에 의해서 적절히 라우팅 되는 것은 아닙니다.자세한 것에 대하여는, 기존의 설명을 참조해 주세요.
최대 스루풋을 실현하기 위한 UDP 패킷의 최적 사이즈는 무엇입니까?
인터넷상의 최대 안전 UDP 패킷사이즈
16kb가 적당합니다.기가비트 이더넷을 사용하는 경우 각 패킷의 크기는 9kb가 될 수 있습니다.
언급URL : https://stackoverflow.com/questions/2862071/how-large-should-my-recv-buffer-be-when-calling-recv-in-the-socket-library
'programing' 카테고리의 다른 글
java.util 입니다.정말 그렇게 무작위로요?52! (팩토리얼) 가능한 시퀀스를 생성하려면 어떻게 해야 합니까? (0) | 2022.08.11 |
---|---|
npm 빌드 실행 후 vuejs 빈 페이지 (0) | 2022.08.11 |
Vue.js에 중첩된 구성 요소: 구성 요소를 마운트하지 못했습니다. 템플릿 또는 렌더 함수가 정의되지 않았습니다. (0) | 2022.08.11 |
Vuex 중첩 루프, 선택/옵션에서 v-model을 처리하는 방법 (0) | 2022.08.11 |
Java에서 int[]를 Integer[]로 변환하려면 어떻게 해야 합니까? (0) | 2022.08.11 |