UDP 네트워크 프로그래밍 - 2

2019. 7. 21. 17:31드론

만일 UDP 네트워크 domain을 인터넷 통신 방식으로 설정하게 된다면 bind에서 주소 체계를 설정할 때

 

struct sockaddr_in {
    __uint8_t sin_len;
    sa_family_t sin_family;
    in_port_t sin_port;
    struct in_addr sin_addr;
    char sin_zero[8];

};

의 구조체를 사용해서 IP주소를 넣어줘야만 한다

 

하지만 CPU 상황에 따라 바이트 순서가 다르므로 반드시 바이트 순서 변환 함수를 사용해서 넣어줘야만 한다. 자세히 살펴보면, RISC CPU와 x86 CPU에서 메모리에 데이터를 저장하는 방식이 다르다. x86은 리틀 엔디안 방식으로 하위 비트의 값을 먼저 저장하게 된다. 예를 들어, "1A2B3C4D"를 메모리에 "4D3C2B1A"라고 저장한다

 

우리가 익숙한 메모리 저장 방식은 RISC에서 사용하는 빅 엔디안 방식이다. 왼쪽에서 오른쪽으로 읽는 언어를 사용하는 사람들에게는 이 방식이 가장 자연스러운 방식이다. 네트워크 상에서도 순차적으로 데이터가 전송되는데 이러한 이유로 빅 엔디안이 보다 더 적합하다. 이를 네트워크 바이트 순서라고 하는데, 송/수신 데이터 모두 빅 엔디안으로 간주해서 처리해야 한다

 

https://genesis8.tistory.com/37

 

일반적으로 PC에서 사용하고 있는 CPU는 인텔 계열의 CPU이기 때문에, 엔디안 변환이 필요하게 된다. 따라서 유닉스에서는 바이트 순선 변환 함수를 제공하고 있다. RISC CPU에서도 동작을 할 수 있지만 소스코드 호환성을 위해 사용하는 것이 좋다

 

htons() : (Host to network short)  

             Host 시스템에서 Network로 short 형 데이터를 보낼 때  바이트 오더를 바꾸어주는 함수 (주로 포트번호)

htonl() : (Host to network long )

            long 형 데이터의 바이트 오더를 바꾸어주는 함수

ntohs() : (Network to host short)

            Network에서 Host로 short형 데이터의 바이트 오더를 바꾸어주는 함수

ntohl()  : (Network to host long)

            long 형 데이터의 바이트 오더를 바꾸어주는 함수

 

[출처: https://fattarzan.tistory.com/entry/htonl-htons-ntohl-ntohs [뚱보타잔]]

 

그리고 네트워크 주소 IP를 입력할 때, 문자열을 사용하게 되는데 실제로는 16진수의 정수값이므로 이를 변환해야 한다. 유닉스에서는 네트워크 주소 변환 함수를 지원하는데, 주로 사용하는 것이 inet_aton()이다. 이는 문자열 형태의 IP 주소를 16진수의 32비트 IP 주소로 변환하게 된다

 

이렇게 서버와 클라이언트가 연결된 이후에는 데이터를 송수신하는 일만 남았다. TCP의 경우에는 서버가 연결되어 있기 때문에 read나 write 같은 파일 디스크립터를 조작하는 함수를 통해서 데이터를 송수신할 수 있지만, UDP의 경우에는 서버와 연결되어 있지 않으므로 다른 함수를 사용해야 한다. 따라서 통신을 위해서 sendto, recvfrom 함수를 사용한다

 

소켓을 이용해서 UDP로 서로 통신하는 코드를 작성해보려고 한다. 서버는 클라이언트로부터 데이터를 받아서 그대로 다시 되돌려주는 에코(echo) 서버다. 클라이언트는 현재 시스템과 연결 가능한 루프백 주소를 입력해서 통신을 하게 된다

 

 

[실행화면]

 

[출처] 사물인터넷을 위한 리눅스 프로그래밍 with 라즈베리파이