멀티스레드 TCP 서버

bolee·2022년 4월 19일
0

아래 코드는 스레드 생성 함수를 사용하여 만든 멀티스레드 TCP 서버의 기본 형태이다.

DWORD WINAPI ProcessClient(LPVOID arg)
{
	// 전달된 소쳇 저장 - 3
    SOCKET client_sock = (SOCKET) arg;
    ...
    // 클라이너트 정보 얻기 - 4
    int addrlen = sizeof(client_sock);
    getpeername(client_sock, (SOCKADDR *) &clientaddr, &addrlen);
    
    // 클라이언트와 데이터 통신 - 5
    while (1)
    {
    	...
    }
    ...
}

int main(int argc, char **argv)
{
	...
    while (1)
    {
    	// 클라이언트 접속 수용 - 1
        client_sock = accept(listen_sock, ...);
        ...
        // 스레드 생성 - 2
        CreateThread(NULL, 0, ProcessClient, (LPVOID) client_sock, 0, NULL);
    }
    ...
}
  • 1: 클라이언트가 접속하면 accept()함수는 클라이언트와 통신할 수 있는 소켓을 리턴한다.
  • 2: 클라이언트와 통신을 담당할 스레드를 생성한다. 이때 스레드 함수에 소켓을 넘겨준다.
  • 3: 스레드 함수는 인자로 전달된 소켓을 SOCKET 타입으로 형변환(casting)하여 저장해둔다.
  • 4: getpeername() 함수를 호출해 클라이언트 IP 주소와 포트 번호를 얻는다. 이 코드는 필수는 아니며 클라이언트 정보 출력을 원할 때만 필요하다.
  • 5: 클라이언트와 데이터를 주고 받는다.

스레드 함수에 소켓만 전달한 경우에는 별도의 주소 정보가 없으므로, 소켓을 통해 주소 정보를 얻는 기능이 필요하다.
getpeername()함수는 소켓 데이터 구조체에 저장된 IP 주소와 원격 포트 번호를 리턴하고, getsockname() 함수는 지역 IP 주소와 지역 포트 번호를 리턴한다.

// 성공: 0, 실패: SOCKET_ERROR
int getpeername(
	SOCKET 			s,
    struct sockaddr	*name,
    int 			*namelen
);

// 성공: 0, 실패: SOCKET_ERROR
int getsockname(
	SOCKET 			s,
    struct sockaddr	*name,
    int 			*namelen
);
  • s: 소켓
  • name: 소켓 주소 구조체
  • namelen: 소켓 주소 구조체의 크기

위 멀티스레드 TCP 서버의 기본 형태를 이용해 만든 멀티스레드 TCP 서버는 아래 링크와 같다.

https://github.com/LEEBONGHAK/TCP-IP_window_socket/blob/main/Chapter06/MultithreadTCPServer.cpp

실행 결과는 다음과 같다. 클라이언트가 2개 이상 접속해도 독립적으로 처리가 진행된다.

참고 자료
김성우 저, "TCP/IP 윈도우 소켓 프로그래밍", 한빛아카데미, 2018

0개의 댓글