Software/통신 프로토콜

[TCP/IP] 서버 프로그램 만들기

초인로크 2021. 3. 13. 00:00
반응형

시스템을 만들다 보면 무선통신을 해야 될 때가 있는데,

 

제일 기초적인 C언어를 이용한 소켓통신의 샘플을 여기에 올려놓는다.

 

서버를 돌리기 위한 최소한의 부분만을 올려놓았으며,

 

맥북의 Xcode에서 프로젝트 생성해서 실행시키면 그냥 사용할 수 있는 코드이다.

 

윈도에서 이용하기 위해서는 설정을 좀 만져줘야 된다.

 

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

#define BUFSIZE 8192 //버퍼 사이즈
#define PORT 3000    //포트번호 

int srcSocket;  // 자신
int dstSocket;  // 상대방

// sockaddr_in 구조체
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
socklen_t len;

char buf[BUFSIZE];

void server_init(){
    //소켓의 생성
    if ((srcSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        //에러가 생겼을 경우의 처리
        perror("socket error");
        exit(EXIT_FAILURE);
    }
    
    //server의 IP해제
    int on = 1;
    printf("Server Started\n");
    setsockopt(srcSocket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); //소켓 옵션을 설정하는 함수
    
    // sockaddr_in 구조체의 세트
    memset((char *) &s_addr, 0, sizeof(s_addr));
    s_addr.sin_family      = AF_INET;
    s_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    s_addr.sin_port        = htons(TCP_PORT);
    
    // 소켓의 바인드
    if (bind(srcSocket, (struct sockaddr *) &s_addr, sizeof(s_addr)) < 0) {
        perror("bind");
        exit(EXIT_FAILURE);
    }
    
    // 접속 허가
    listen(srcSocket, 5);
    
    // 클라이언트에서 접속요구를 수신
    len = sizeof(dstSocket);
}

void server_main(){
    // 소켓의 접속
    if ((dstSocket = accept(srcSocket, (struct sockaddr *) &c_addr, &len)) < 0) {
        // 소켓접속 실패시의 에러 표시
        perror("accept error");
        exit(EXIT_FAILURE);
    }
    printf("connected from '%s' \n", inet_ntoa(s_addr.sin_addr));

}

int main()
{
    // server 의 초기화
    server_init();

    // 소켓의 접속
    server_main();
    
    while (1) {
        memset(buf, 0, sizeof(buf));
        // 패킷의 수신
        recv(dstSocket, buf, sizeof(buf),0);
        printf("Ricived from client %s \n",buf);
		
        // 패킷의 송신
        send(dstSocket, buf, sizeof(buf),0);
        printf("Sent to client %s \n",buf);
    }
    
    // 클라이언트와의 접속을 종료한다 (소켓 닫기)
    close(srcSocket);

    return EXIT_SUCCESS;
}

위의 소스에서는 아래와 같이 크게 두 부분으로 나위에서 사용하고 있다.

 

1. 소켓의 초기화 부분

2. 소켓의 접속 부분

 

지금 보이고 있는 예제는 소켓의 접속이 이루어진 다음에는 접속을 유지한 체 통신을 하는 구조이다.

 

한번 접속해서 데이터를 송신 혹은 수신한 다음에 소켓을 닫는 작업을 반복하는 경우에는,

 

1번과 2번의 소스 그리고 소켓을 닫는 부분을 while 문 안에 넣어줘서 접속과 해제를 반복하는 작업을 해 주면 된다.

 

시간 날 때 C언어로 작성된 클라이언트와 Swift로 작성된 클라이언트도 한번 설명해 볼까 한다.

반응형