네트워크 바이트 순서와 기계 순서의 차이점은 무엇입니까?
네트워크 바이트 순서 NBO (네트워크 바이트 순서):
높은 순서에서 낮은 순서로 네트워크에 균일한 네트워크 바이트 순서를 사용하면 호환성 문제를 방지할 수 있습니다.
호스트 바이트 순서 (HBO):
기계마다 HBO 가 다르며 CPU 디자인과 관련이 있습니다.
컴퓨터 데이터 저장소에는 높은 바이트 우선 순위와 낮은 바이트 우선 순위라는 두 가지 바이트 우선 순위가 있습니다. 인터넷의 데이터는 높은 바이트 우선 순위에 따라 네트워크를 통해 전송되므로 내부적으로 낮은 바이트 우선 순위로 데이터를 저장하는 시스템의 경우 인터넷을 통해 데이터를 전송할 때 변환이 필요합니다.
논의 할 첫 번째 구조 유형은 소켓 정보를 저장하는 struct sockaddr 입니다.
구조 sockaddr {
부호 없는 짧은 sa _ family/* 주소 패밀리, AF_xxx */
Charsa _ data [14]; /* 14 바이트 프로토콜 주소 */};
Sa_family 는 일반적으로 AF _ INET;; Sa_data 에는 소켓의 IP 주소와 포트 번호가 포함되어 있습니다.
또 다른 구조 유형이 있습니다.
Struct sockaddr_in {
Short int sin _ family/* 주소 시리즈 */
부호 없는 짧은 정수 sin _ port/* 포트 번호 */
구조 in _ addr sin _ addr/* IP 주소 */
부호 없는 문자 sin _ zero [8]; /* 0 을 채워 struct sockaddr 과 같은 크기를 유지합니다 */
}
이런 구조는 사용하기에 더 편리하다. Sin_zero (struct sockaddr 와 동일한 길이로 sockaddr_in 구조를 채우는 데 사용됨) 는 bjero () 또는 memset () 함수를 사용하여 0 으로 설정해야 합니다. Sockaddr_in 에 대한 포인터와 sockaddr 에 대한 포인터는 서로 변환할 수 있습니다. 즉, 함수에 필요한 매개 변수 유형이 sockaddr 인 경우 함수를 호출할 때 sockaddr_in 에 대한 포인터를 sockaddr 에 대한 포인터로 변환할 수 있습니다. 반대의 경우도 마찬가지입니다. Sin_family 에는 일반적으로 AF _ INET;; Sin_port 및 sin_addr 은 네트워크 바이트 우선 순위로 변환됩니다. Sin_addr 은 변환이 필요하지 않습니다.
몇 바이트 순서 변환 함수에 대해 살펴보겠습니다.
Htons()-"호스트 대 네트워크 짧은"; Htonl()-"호스트 대 네트워크 길이"
Ntohs()-"네트워크 대 호스트 짧은"; Ntohl()-"네트워크 대 호스트 길이"
여기서 H 는' 호스트', N 은' 네트워크', S 는' 짧음', L 은' 길음' 이다.
소켓 설명자를 열고 바인딩을 설정하고 연결을 설정합니다.
소켓 함수의 프로토타입은 다음과 같습니다.
Int 소켓 (int 도메인, int 유형, int 프로토콜);
Domain 매개변수는 소켓 유형 (SOCK_STREAM 또는 SOCK _ DGRAM;) 을 지정합니다. 계약은 일반적으로 값 "0" 을 할당합니다. Socket () 에 대한 호출은 후속 호출에서 사용할 수 있는 정수 소켓 설명자를 반환합니다.
소켓 호출을 통해 소켓 설명자가 반환되면 소켓을 컴퓨터의 한 포트에 연결해야 합니다 (서버측 프로그램을 디자인할 때 자주 호출됨). 그런 다음 포트 모니터에서 요청을 서비스할 수 있습니다. 클라이언트는 일반적으로 이 함수를 호출할 필요가 없습니다.) 바인딩 함수의 프로토타입은 다음과 같습니다.
Int bind(int sockfd, struct sockaddr *my_addr, int addrlen);
Sockfd 는 소켓 설명자이고 my_addr 은 로컬 IP 주소, 포트 번호 등의 정보를 포함하는 sockaddr 유형에 대한 포인터입니다. Addrlen 은 일반적으로 sizeof(struct sockaddr) 로 설정됩니다.
마지막으로 bind 함수에 대해 주의해야 할 점은 로컬 IP 주소를 자동으로 가져오고 다음 할당을 통해 사용되지 않는 포트 번호를 무작위로 얻을 수 있다는 것입니다.
My _ addr.sin _ port = 0; /* 사용되지 않은 포트 번호를 임의로 선택합니다. */
My _ addr.sin _ addr.s _ addr = inaddr _ any; /* 기본 IP 주소 입력 */
My_addr.sin_port 를 0 으로 설정하면 함수가 자동으로 사용되지 않는 포트를 선택합니다. 마찬가지로 my_addr.sin_addr.s_addr 을 INADDR_ANY 로 설정하면 로컬 IP 주소가 자동으로 채워집니다. Bind () 함수가 성공적으로 호출되면 0 을 반환합니다. 오류가 발생하면 "-1" 을 반환하고 errno 를 적절한 오류 번호로 설정합니다. 또한 함수를 호출할 때 일반적으로 포트 번호를 1024 보다 작은 값으로 설정하지 마십시오. 1~ 1024 는 예약된 포트 번호이므로/kloc-보다 큰 값을 사용할 수 있습니다
Connect () 함수는 원격 서버에 대한 TCP 연결을 설정하는 데 사용되며 함수 프로토타입은 다음과 같습니다.
Int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
소켓은 대상 서버의 소켓 설명자입니다. Serv_addr 은 대상 시스템의 IP 주소와 포트 번호를 포함하는 포인터입니다. 오류가 발생하면-1 이 반환되고 errno 에 해당 오류 코드가 포함됩니다. 클라이언트 프로그래밍은 bind () 를 호출할 필요가 없습니다. 이 경우 대상 시스템의 IP 주소만 알면 되고 클라이언트가 서버에 연결하는 포트는 중요하지 않기 때문입니다. 커널은 클라이언트가 사용할 사용하지 않는 포트를 자동으로 선택합니다.
Listen()- 서비스 요청을 수신합니다.
서버측 프로그램에서 소켓이 포트에 바인딩되면 도착한 서비스 요청을 처리하기 위해 해당 포트를 수신해야 합니다.
Int listen(int sockfd, intbacklog);
소켓은 소켓 시스템 호출에서 반환되는 소켓 설명자입니다. Backlog 는 수신 접속 요청이 대기 중인 요청 대기열에 허용되는 최대 요청 수를 지정합니다 (아래 참조). Backlog 는 대기열에서 서비스를 기다리는 요청 수를 제한합니다. 대부분의 시스템의 기본값은 20 입니다. Listen 에 오류가 발생하면-1 을 반환하고 errno 는 적절한 오류 코드로 설정됩니다.
따라서 서버측 프로그램은 일반적으로 다음 순서로 함수 호출을 수행합니다.
소켓 (); Bind (); 듣기 (); /* accept () 는 여기 */
Accept()- 연결 포트에 대한 서비스 요청입니다.
클라이언트가 서버가 수신 중인 포트에 접속을 시도할 때 접속 요청은 서버가 받아들일 때까지 대기합니다 (). Accept () 함수를 호출하여 연결을 설정하면 accept () 함수는 새 연결에 대한 새 소켓 설명자를 반환합니다. 서버는 이전 소켓을 계속 수신할 수 있으며 새 소켓 설명자에 대해 데이터 send () (전송) 및 recv () (수신) 작업을 수행할 수 있습니다.
Int accept(int sockfd, void *addr, int * addrlen);
Sockfd 는 모니터링되는 소켓 설명자이며, addr 은 일반적으로 서비스 접속을 요청한 호스트에 대한 정보를 저장하는 sockaddr_in 변수에 대한 포인터입니다 (한 호스트가 한 포트에서 요청을 전송함). Addrten 은 일반적으로 sizeof(struct sockaddr_in) 값을 갖는 정수 포인터 변수입니다. 오류가 발생하면-1 이 반환되고 해당 errno 값이 설정됩니다.
Send () 및 recv()- 데이터 전송
이 두 함수는 연결 지향 소켓에서 데이터 전송에 사용됩니다.
Send () 함수의 프로토타입은 다음과 같습니다.
Int send(int sockfd, const void *msg, int len, intflags);
Sockfd 는 데이터 전송에 사용할 소켓 설명자이고 msg 는 전송할 데이터에 대한 포인터입니다.
Len 은 데이터 길이 (바이트) 입니다. Flags 는 일반적으로 0 으로 설정됩니다. 이 매개변수 사용에 대해서는 설명서를 참조하십시오.
Char *msg = "Beej 여기 있습니다! 클릭합니다 을 눌러 섹션을 인쇄할 수도 있습니다 Int len, bytes _ sent .....
Len = strlen (msg); Bytes_sent = send(sockfd, msg, len, 0); .....
Send () 함수는 실제로 전송된 바이트 수를 반환합니다. 이는 전송할 데이터보다 적을 수 있습니다. 따라서 send () 의 반환 값을 측정해야 합니다. Send () 의 반환 값이 len 과 일치하지 않을 때 이 상황을 처리해야 합니다.
Recv () 함수의 프로토타입은 다음과 같습니다.
Int recv(int sockfd, void *buf, int len, unsigned int flags);
Sockfd 는 데이터를 수락하는 소켓 설명자입니다. Buf 는 데이터를 수신하는 버퍼입니다. Len 은 버퍼의 길이입니다. Flags 도 0 으로 설정됩니다. Recv () 는 실제로 수신된 바이트 수 또는 오류 발생 시-1 및 해당 errno 값을 반환합니다.
Sendto () 및 Recvfrom()- 데이터그램을 통한 데이터 전송.
연결되지 않은 데이터그램 소켓 모드에서는 로컬 소켓이 원격 시스템에 연결되지 않았기 때문에 데이터를 보낼 때 대상 주소를 지정해야 합니다. Sendto () 함수의 프로토타입은 다음과 같습니다.
Int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, inttolen)
이 함수는 일반적으로 sizeof (struct sockaddr) 로 지정되는 대상 시스템의 IP 주소 및 포트 번호 정보를 나타내는 tolen () 함수보다 두 개 더 많은 매개 변수를 가지고 있습니다. Sendto 함수는 실제로 전송된 데이터 바이트 길이 또는-1 전송 오류 방지도 반환합니다.
Recvfrom () 함수의 프로토타입은 다음과 같습니다.
Int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int * from len)
From 은 소스 시스템의 IP 주소와 포트 번호를 저장하는 struct sockaddr 유형의 변수입니다. Fromlen 은 보통 sizeof (struct sockaddr) 로 설정됩니다. Recvfrom () 이 반환되면 fromlen 에는 from 에 실제로 저장된 데이터 바이트 수가 포함됩니다. Recvfrom () 함수는 수신된 바이트 수 또는 오류 시-1 을 반환하고 적절한 errno 를 설정합니다.
데이터그램 소켓에 대해 connect () 함수를 호출할 때 send () 및 recv () 를 사용하여 데이터를 전송할 수도 있지만 소켓은 여전히 데이터그램 소켓이며 전송 계층의 UDP 서비스를 사용한다는 점에 유의해야 합니다. 그러나 데이터를 보내거나 받을 때 커널은 대상 및 소스 주소 정보를 자동으로 추가합니다.
Close () 및 shut down()- 데이터 전송을 종료합니다.
모든 데이터 작업이 완료되면 close () 함수를 호출하여 소켓을 해제하여 소켓에서 모든 데이터 작업을 중지할 수 있습니다. close (sockfd);
Shutdown () 함수를 호출하여 소켓을 닫을 수도 있습니다. 이 기능을 사용하면 한 방향으로만 데이터 전송을 중지하고 한 방향으로만 데이터 전송을 계속할 수 있습니다. 예를 들어 소켓 쓰기를 끄고 모든 데이터를 읽을 때까지 소켓의 데이터를 계속 받아들일 수 있습니다.
Int shutdown(int sockfd, inthow);
Sockfd 의 의미는 분명합니다. 매개변수 how 는 다음 값으로 설정할 수 있습니다.
0- 추가 데이터 수신이 허용되지 않습니다.
1- 데이터 전송을 허용하지 않습니다.
2- 데이터 송수신을 계속할 수 없습니다. 둘 다 허용되는 경우 close () 를 호출합니다.
작업이 성공하면 Shutdown 은 0 을 반환하고 오류가 발생하면-1 (해당 errno 와 함께) 을 반환합니다.
DNS- 도메인 이름 서비스 관련 기능
IP 주소는 기억과 읽기가 어렵기 때문에 읽기 및 쓰기를 용이하게 하기 위해 도메인 이름으로 호스트를 표현하는 경우가 많기 때문에 도메인 이름과 IP 주소의 변환이 필요합니다. 함수 gethostbyname () 은 이 변환을 완료합니다. 이 함수의 프로토타입은 다음과 같습니다.
Structhostent * gethostbyname (constchar * name);
이 함수는 다음과 같이 정의된 hosten 이라는 구조 유형을 반환합니다.
Fabric 호스트 {
Char * h _ name/* 호스트의 공식 도메인 이름 */
Char * * h _ aliases/* NULL 로 끝나는 호스트 별칭 배열 */
Int h _ addrtype/* 이 반환하는 주소 유형은 AF-INET */
Int h _ 길이; /* 주소의 바이트 길이 */
Char * * h _ addr _ list/* 호스트의 모든 주소를 포함하는 0 으로 끝나는 배열 */
}
# define h _ addr h _ addr _ list [0]/* h-addr-list 의 첫 번째 주소 */
2. 호스트의 부호없는 긴 값을 네트워크 바이트 순서 (32 비트) 로 변환: 왜 그럴까요? 컴퓨터마다 서로 다른 바이트 순서를 사용하여 데이터를 저장하기 때문입니다. 따라서 Winsock 함수의 IP 주소와 포트 번호에 대한 모든 참조와 Winsock 함수로 전송되는 IP 주소와 포트 번호는 네트워크 순서로 구성됩니다.
& amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; 유룡 & amp& lt60; Htonl (u _ long hostlong);
& amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; 예: htonl(0)=0
& amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; Htonl (80) =1342177280
3. 부호없는 긴 숫자를 네트워크 바이트 순서에서 비트 호스트 바이트 순서로 변환하는 것은 위 함수의 역함수입니다. & amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; 유룡 & amp& lt60; Nto HL (u _ long netlong);
& amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; 예: ntohl(0)=0
& amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; Ntohl (1342177280) = 80
1342177280 = 80 * 256 * 256 * 256
4. 호스트의 부호없는 짧은 값을 네트워크 바이트 순서 (16 비트) 로 변환합니다. 그 이유는 2:&; & lt60; & amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; U _ short & amp& lt60; Htons (u _ shorthostshort);
& amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; 예: htonl(0)=0
& amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; Htonl(80)= 20480
5. 부호 없는 단수를 네트워크 바이트 순서에서 호스트 바이트 순서로 변환하는 것은 위 함수의 역함수입니다. & amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; U _ short & amp& lt60; Ntohs (u _ shortnetshort);
& amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; 예: ntohs(0)=0
& amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; & amp& lt60; Ntohsl(20480)= 80
20480 = 8-*256 (크기 주소 변환)
* * * *
CPU 마다 바이트 순서 유형이 다릅니다. 이러한 바이트 순서는 정수가 메모리에 저장되는 순서를 나타냅니다. 이것이 바로 이른바 호스트 순서다.
가장 일반적인 두 가지 유형이 있습니다.
1.Little endian: 시작 주소에 하위 바이트를 저장합니다.
2.Big Endian: 시작 주소에 상위 바이트를 저장합니다.
소단 (을) 치다
인간의 사고에 가장 잘 맞는 바이트 순서.
주소의 낮은 저장 값의 낮은 위치
주소 상위 저장된 값의 상위 수준.
아무리 말해도 사람의 생각에 가장 잘 맞는 바이트 순서다. 사람의 첫인상으로 볼 때.
하위 값이 작으면 메모리 주소가 작은 곳, 즉 하위 메모리 주소에 배치해야 합니다.
반대로 높은 값은 메모리 주소가 큰 위치, 즉 높은 메모리 주소에 배치해야 합니다.
큰 끝을 유지하다
가장 직관적인 바이트 순서
주소 하한 저장된 값의 상한.
상위 주소 저장된 값의 하위 수준입니다.
왜 직관적이고 대응을 고려하지 않는가?
낮은 순서에서 높은 순서로 왼쪽에서 오른쪽으로 메모리 주소를 쓰면 됩니다.
일반적으로 높은 순서에서 낮은 순서로 이러한 값을 기록합니다.
두 가지를 비교하고 바이트별로 채웁니다.