반응형

리눅스 C : TCP 소켓 프로그램

알게된 배경

 라즈베리 파이를 위한 소캣 프로그램을 만들다 보니 어쩔 수 없이 TCP와 같은 소켓 프로그램을 제작하게 되었다. 소켓 프로그램의 경우 대부분 표준화가 되어 있으며, 구현하는 절차가 거의 정해져 있다. 때문에 이해를 했다 하더라도 외우고 있는건 무리기 때문에 기록을 남긴다.


사전에 염두 해야 할 점

 C와 C++이 일반적으로 빠른 이유는 운영체제와 거의 직접적으로 맞닿아서 작동이 된다는 점이다. 심지어 운영체제가 없는 마이크로프로세서 분야에서도 C가 사용되고 있다. 즉, 하드웨어나 운영체제의 영향을 많이 받기 때문에 당연히 윈도우와 리눅스간 코드는 차이가 있다.

 하나 더 알아야 할 것은 리눅스, OS X, FreeBSD 등 윈도우를 제외하고는 대부분은 유닉스 기반이라 소켓 코드가 거의 같다(게다가 컴파일러도 거의 비슷하다).


소스코드

 일반적으로 에코서버 코드가 기본이지만, 여기서는 스트림을 전송하거나 수신하는 코드는 제외한다.


서버

#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

void errorHandl(char* msg)
{
    puts(msg);
    exit(1);
}

int main(int argc, char* argv[])
{
    int serv_sock;
    int clnt_sock;
    struct sockaddr_in serv_addr;
    struct sockaddr_in clnt_addr;
    socklen_t clnt_addr_sz;

    if(argc != 2)
    {
        printf("Usage : %s <port>\n", argv[0]);
        exit(1);
    }
    // 서버 TCP 소켓 생성
    serv_sock = socket(PF_INET, SOCK_STREAM, 0);
    if(serv_sock == -1)
         errorHandl("socket() error");

    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(atoi(argv[1]));

    if(bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1)
        errorHandl("bind() error");

    // serv_sock 다음 인수는 최대 대기중인 클라이언트 수
    if(listen(serv_sock, 5) == -1)
        errorHandl("listen() error");

    clnt_addr_sz = sizeof(clnt_addr);
    clnt_sock = accept(serv_sock, (struct sockaddr*) &clnt_addr, &clnt_addr_sz);
    if(clnt_sock == -1)
        errorHandl("accept() error");

    // 이제 소켓을 통해서 전송할 작업을 작성하면 된다.
    // 생략

    // 클라이언트/서버 순서대로 스트림을 닫느다.
    close(clnt_sock);
    close(serv_sock);

    return 0;
}


클라이언트

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

void errorHandl(char* msg)
{
    puts(msg);
    exit(1);
}

int main(int argc, char* argv[])
{
    int sock;
    struct sockaddr_in serv_addr;
    if(argc != 3)
    {
        printf("Usage : %s <IP> <port>\n", argv[0]);
        exit(1);
    }
    // TCP 소켓 설정
    sock = socket(PF_INET, SOCK_STREAM, 0);
    if(sock == -1)
         errorHandl("socket() error");

    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
    serv_addr.sin_port = htons(atoi(argv[2]));

    if(connect(sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1)
        errorHandl("connect() error");

    // 여기서 전송이나 수신하는 내용을 작성함
    // 생략

    // 소켓 스트림 닫음
    close(sock);

    return 0;
}



반응형

+ Recent posts