Programming

[C/C++]Linux 시스템콜을 이용한 TCP/IP 프로그래밍 기초

라우드니스 2010. 8. 28. 19:40

= TCP/IP 소켓 관련 시스템콜 =
struct sockaddr_in {
    short int          sin_family;  /* Address family               */
    unsigned short int sin_port;    /* Port number                  */
    struct in_addr     sin_addr;    /* Internet address             */
    unsigned char      sin_zero[8]; /* Same size as struct sockaddr */
};

-> 실제로 사용하게 되는 구조체. 꼭 기억하자!

 
// htons()--"Host to Network Short"
// htonl()--"Host to Network Long"
// ntohs()--"Network to Host Short"
// ntohl()--"Network to Host Long"

-> 소켓을 사용해 데이터를 보내거나 받을때 CPU가 읽는 방식이 몇가지가 있기 때문에 호환성을 위해서 데이터를 변환해 주어야 하는데 이를 해주는 함수.

#include 
#include 

-> 밑의 함수들이 존재하는 헤더파일

int socket(int domain, int type, int protocol);

int bind(int sockfd, struct sockaddr *my_addr, int addrlen);

int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);

int listen(int sockfd, int backlog); //backlog는 접속대기 큐의 최대 연결 가능 숫자. 대게 5~10 사이의 숫자를 쓴다.

int accept(int sockfd, void *addr, int *addrlen);

int send(int sockfd, const void *msg, int len, int flags); //msg는 보낼 내용을 가리키는 포인터, len은 msg의 크기, flags 는 항상 0

int recv(int sockfd, void *buf, int len, unsigned int flags); //buf는 받은 내용을 받을 포인터, len은 buf의 크기, flags 는 항상 0

int sendto(int sockfd, const void *msg, int len, unsigned int flags,
               const struct sockaddr *to, int tolen);

int recvfrom(int sockfd, void *buf, int len, unsigned int flags
                struct sockaddr *from, int *fromlen);
//sendto 의 sockaddr은 보낼 주소가 담긴 sockaddr_in 포인터, recvfrom 는 받을 주소가 담긴 sockaddr_in. len은 sockaddr_in 구조체의 크기

close(sockfd); // 유닉스호환시스템에서는 socket도 파일이므로 close로 닫아버린다.

int shutdown(int sockfd, int how); // how : 0 - 더이상의 수신 금지 1 - 더이상의 송신 금지 2 - 더이상의 송수신 금지(close()와 같은 경우) 

int getpeername(int sockfd, struct sockaddr *addr, int *addrlen); // 넘겨준 addr포인터에 peer에 관한 정보가 저장된다.

int gethostname(char *hostname, size_t size); // 넘겨준 hostname에 리턴된다. size는 hostname의 크기

#include 

-> DNS로 부터 읽어오는 함수들을 가지고 있는 헤더파일.

struct hostent *gethostbyname(const char *name); //DNS로 부터 내용을 가지고 온다.

struct hostent {
    char    *h_name;
    char    **h_aliases;
    int     h_addrtype;
    int     h_length;
    char    **h_addr_list;
};
#define h_addr h_addr_list[0]
// h_name - 호스트의 공식적인 이름
// h_aliases - 호스트의 별명으로서 NULL 로 끝맺음된다.
// h_addrtype - 주소의 종류, 보통 AF_INET
// h_length - 주소의 바이트 수
// h_addr_list - 0으로 끝나는 네트워크 주소들, NBO로 되어 있다.
// h_addr - h_addr_list속의 첫번째 주소 

관련 코드 :

// ...간단한 에러설정 
        if ((h=gethostbyname(argv[1])) == NULL) {  /* get the host info */
            herror("gethostbyname");
            exit(1);
        }

        printf("Host name  : %s\n", h->h_name);
        printf("IP Address : %s\n",inet_ntoa(*((struct in_addr *)h->h_addr)));
// 나머지 설정


= 서버프로그램의 주된 흐름 : =


//... 변수설정
        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
            perror("socket");
            exit(1);
        }

// sockaddr_in 설정.
        if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
            perror("bind");
            exit(1);
        }
        if (listen(sockfd, BACKLOG) == -1) {
            perror("listen");
            exit(1);
        }

//accept 설정 시작. 대게 서버가 그냥 종료되는 일이 없으므로 무한루프안에 집어넣는다.
        if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr,&sin_size)) == -1) {
            perror("accept");
            continue;
        }


= 클라이언트 프로그램의 주된 흐름 : =

#define PORT 3490 // the port client will be connecting to 

#define MAXDATASIZE 100 // max number of bytes we can get at once 

//... 변수설정. 해당 클라이언트 프로그램은 DNS서버로 부터 IP주소를 가지고 온다.
        if ((he=gethostbyname(argv[1])) == NULL) {  // get the host info 
            perror("gethostbyname");
            exit(1);
        }

        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
            perror("socket");
            exit(1);
        }
//호스트 sockaddr_in 설정
        their_addr.sin_family = AF_INET;    // host byte order 
        their_addr.sin_port = htons(PORT);  // short, network byte order 
        their_addr.sin_addr = *((struct in_addr *)he->h_addr);
        memset(&(their_addr.sin_zero), '\0', 8);  // zero the rest of the struct 

//connect를 이용해 host에 접속.
        if (connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == -1) {
            perror("connect");
            exit(1);
        }
        if ((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) {
            perror("recv");
            exit(1);
        }
        buf[numbytes] = '\0';
        printf("Received: %s",buf);
        close(sockfd);
참조 사이트 :


반응형