소켓 라이브러리에서 recv를 호출 할 때 recv 버퍼의 크기는 얼마입니까?
C의 소켓 라이브러리에 대한 몇 가지 질문이 있습니다. 다음은 내 질문에서 참조 할 코드 스 니펫입니다.
char recv_buffer[3000];
recv(socket, recv_buffer, 3000, 0);
- recv_buffer를 얼마나 크게 만들 수 있습니까? 3000을 사용하고 있지만 임의적입니다.
recv()
버퍼보다 큰 패킷을 받으면 어떻게됩니까 ?- recv를 다시 호출하지 않고 전체 메시지를 받았는지, 수신 할 것이 없을 때 영원히 기다리도록하려면 어떻게해야합니까?
- 공간이 부족할 염려없이 버퍼에 계속 추가 할 수 있도록 고정 된 양의 공간이없는 버퍼를 만들 수있는 방법이 있습니까? 아마도 버퍼에
strcat
대한 최신recv()
응답 을 연결하는 데 사용 합니까?
한 번에 많은 질문이 있다는 것을 알고 있지만 모든 답변에 크게 감사드립니다.
이러한 질문에 대한 답변은 TCP / IP 내 에서 스트림 소켓 ( SOCK_STREAM
) 또는 데이터 그램 소켓 ( SOCK_DGRAM
)을 사용하는지에 따라 달라지며 , 전자는 TCP에 해당하고 후자는 UDP에 해당합니다.
버퍼가 얼마나 크게 전달되는지 어떻게 알 수 recv()
있습니까?
SOCK_STREAM
: 너무 중요하지 않습니다. 당신의 프로토콜이 트랜잭션 / 대화 형 프로토콜이라면, 당신이 기대할 수있는 가장 큰 개별 메시지 / 명령을 담을 수있는 크기를 선택하십시오 (3000은 괜찮을 것입니다). 프로토콜이 대량 데이터를 전송하는 경우 더 큰 버퍼가 더 효율적일 수 있습니다. 일반적으로 소켓의 커널 수신 버퍼 크기와 비슷합니다 (종종 256kB 정도).SOCK_DGRAM
: 응용 프로그램 레벨 프로토콜이 전송하는 가장 큰 패킷을 보유 할 수있을만큼 큰 버퍼를 사용하십시오. UDP를 사용하는 경우 일반적으로 응용 프로그램 수준 프로토콜은 약 1400 바이트보다 큰 패킷을 보내지 않아야합니다. 패킷은 반드시 조각화하고 다시 어셈블해야하기 때문입니다.
recv
버퍼보다 큰 패킷을 가져 오면 어떻게됩니까 ?
SOCK_STREAM
: 스트림 소켓에는 패킷 개념이 없으므로 연속 바이트 스트림이기 때문에 질문은 실제로 의미가 없습니다. 버퍼에 여유 공간이있는 것보다 읽을 수있는 바이트가 더 많으면 OS에 의해 큐에 대기하고 다음에 호출 할 수recv
있습니다.SOCK_DGRAM
: 초과 바이트가 삭제됩니다.
전체 메시지를 받았는지 어떻게 알 수 있습니까?
SOCK_STREAM
: 애플리케이션 레벨 프로토콜에 메시지 끝을 판별하는 방법을 빌드해야합니다. 일반적으로 길이 접두사 (메시지 길이로 각 메시지를 시작) 또는 메시지 끝 구분 기호 (예 : 텍스트 기반 프로토콜의 줄 바꿈) 일 수 있습니다. 덜 사용되는 세 번째 옵션은 각 메시지에 대해 고정 된 크기를 요구하는 것입니다. 이러한 옵션의 조합도 가능합니다 (예 : 길이 값을 포함하는 고정 크기 헤더).SOCK_DGRAM
: 단일recv
호출은 항상 단일 데이터 그램을 반환합니다.
고정 된 공간을 가지지 않고 버퍼를 만들 수있는 방법이 있습니까? 그래서 공간이 부족할 염려없이 계속 추가 할 수 있습니까?
그러나 버퍼를 사용하여 버퍼 크기를 조정할 수 있습니다 realloc()
(원래 malloc()
또는로 할당 된 경우 calloc()
).
TCP와 같은 스트리밍 프로토콜의 경우 거의 모든 크기로 버퍼를 설정할 수 있습니다. 즉, 4096 또는 8192와 같이 2의 거듭 제곱 인 공통 값이 권장됩니다.
더 많은 데이터가 있다면 버퍼가 무엇인지, 다음에 호출 할 때 커널에 저장됩니다 recv
.
예, 버퍼를 계속 키울 수 있습니다. offset idx
에서 시작하여 버퍼 중간에 recv를 수행 할 수 있습니다 .
recv(socket, recv_buffer + idx, recv_buffer_size - idx, 0);
SOCK_STREAM
소켓 이 있으면 recv
스트림에서 "처음 3000 바이트까지"를 가져옵니다. 얼마나 큰 버퍼를 만드는지에 대한 명확한 지침은 없습니다.
당신이있는 경우 SOCK_DGRAM
소켓을, 그리고 데이터 그램 버퍼보다 큰 경우, recv
데이터 그램의 첫 부분, -1을 반환로 버퍼를 채우고 세트 EMSGSIZE에 errno를. 불행히도, 프로토콜이 UDP 인 경우, 이는 UDP가 신뢰할 수없는 프로토콜 이라고 불리는 이유 중 일부인 데이터 그램이 손실됨을 의미합니다. 후자를 잘 알고 있음에도 불구하고 TCP / IP 제품군에서 이름을 하나 ;-).
버퍼를 동적으로 늘리려면 처음에 버퍼를 할당하고 필요에 따라 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 ~ 65515 바이트 범위 일 수 있습니다. 따라서 수신 버퍼의 내결함성 크기는 65507 바이트 (~ 64KB)입니다.
그러나 네트워크 장치가 모든 대형 패킷을 올바르게 라우팅 할 수있는 것은 아닙니다. 자세한 내용은 기존 설명을 참조하십시오.
최대 처리량을위한 최적의 UDP 패킷 크기는 얼마입니까?
인터넷에서 가장 큰 안전한 UDP 패킷 크기는 무엇입니까
16kb는 옳습니다. 기가비트 이더넷을 사용하는 경우 각 패킷의 크기는 9kb 일 수 있습니다.
'Programing' 카테고리의 다른 글
'eval'을 사용하는 것은 왜 나쁜 습관입니까? (0) | 2020.07.07 |
---|---|
약속 체인을 끊고 체인이 끊어진 (거부 된) 단계에 따라 함수를 호출하십시오. (0) | 2020.07.07 |
Json Array를 일반 Java 목록으로 변환 (0) | 2020.07.07 |
각도 2에서 돔 요소를 얻는 방법 (0) | 2020.07.07 |
Android Studio에서 클래스 다이어그램 (UML)을 생성하는 방법 (IntelliJ Idea) (0) | 2020.07.07 |