티스토리 뷰

안녕하세요.

신랑 각시의 신랑입니다.


일하면서, IPv4 와 IPv6 Client 를 연결 요청을 모두 받아야 하는 Server 가 필요했는데요, IPv6 용 Server 를 만들어 두면 모두 수용 가능합니다.


배경 적인 내용은 검색하시거나 책을 찾아보시면 좋을 것 같구요.

제 블로그에서는 IPv6 용 Server 소스만 적어볼까 합니다.


아래는 소스 전체와 컴파일 Line 입니다.

#include

#include #include #include #include #include #include std::string GetPeerInfo(struct sockaddr * _addr, socklen_t _addrlen) { char hostname[256]; char svcname[64]; if(getnameinfo(_addr, _addrlen, hostname, sizeof(hostname), svcname, sizeof(svcname), NI_NUMERICHOST | NI_NUMERICSERV) != 0) { char buf[128]; std::cout << "getnameinfo() - fail " << errno << ":" << strerror_r(errno, buf, sizeof(buf)); std::cout << std::endl; return ""; } return std::string(hostname) + ":" + svcname; } void doServer(int _sock) { if(listen(_sock, 5) < 0) { std::cout << "[SERVER] listen() fail : " << strerror(errno) << std::endl; return ; } struct sockaddr clientaddr; socklen_t addrlen; while(true) { std::cout << "[SERVER] accept() wait" << std::endl; int conn = accept(_sock, &clientaddr, &addrlen); if(conn < 0) { std::cout << "[SERVER] accept() fail : " << strerror(errno) << std::endl; continue; } else { std::cout << "[SERVER] connected from : " << GetPeerInfo(&clientaddr, addrlen) << std::endl; } char cBuf; while(true) { if(recv(conn, &cBuf, 1, 0) <= 0) break; std::cout << cBuf; if(send(conn, &cBuf, 1, 0) <= 0) break; } std::cout << std::endl; close(conn); } close(_sock); std::cout << "[SERVER] Bye" << std::endl; } void serverIPv6(char * _port) { std::cout << "[SERVER] IPv6 Only Mode" << std::endl; int sfd = socket(AF_INET6, SOCK_STREAM, 0); if(sfd < 0) { std::cout << "socket() fail : " << strerror(errno) << std::endl; return ; } int on = 1; setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)); struct sockaddr_in6 addr; addr.sin6_family = AF_INET6; addr.sin6_port = htons(std::stoi(_port)); addr.sin6_addr = in6addr_any; if(bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { std::cout << "bind() fail : " << strerror(errno) << std::endl; close(sfd); return ; } doServer(sfd); close(sfd); } int main(int argc, char * argv[]) { if(argc != 2) { std::cout << "invalid argument" << std::endl; std::cout << "ex) server6 [port]" << std::endl; return 0; } serverIPv6(argv[1]); return 0; }


몇 가지 설명을 하자면,


1) Peer 주소를 알기 위하여 IPv4 와 IPv6 를 모두 표현할 수 있는 getnameinfo() 함수를 사용했습니다.


2) doServer() 함수에서 listen() 과 accept() 를 호출하고, 끊어질 때까지 echo 서버로 동작합니다.


3) serverIPv6() 함수에서 socket() 과 bind() 를 호출한 뒤에, doServer() 를 호출합니다. 


위의 코드를 server6.cpp 파일에 넣고, 아래와 같이 컴파일 했습니다.


g++ -o server6 -std=c++11 

테스트 결과는 클라이언트 소스를 쓰고 난 뒤에 포스팅 하도록 하겠습니다.




댓글