TCP/IP 윈도우 소켓 프로그래밍 2장 [소켓 시작하기]

김예은·2024년 11월 29일
0

1) 오류처리

  1. 오류를 처리할 필요가 없는 경우 : 리턴 값이 없거나 호출 시 항상 성공하는 일부 소켓함수
  2. 리턴값만으로 오류를 확인하고 처리하는 경우 : 윈도우의 WSAStartup() 함수
  3. 리턴값으로 오류 발생을 확인하고, 구체적인 내용은 오류 코드로 확인하는 경우 : 대부분의 소켓 함수

1. 윈도우 오류처리

#define _CRT_SECURE_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS

#include <winsock2.h>
#include <ws2tcpip.h>

#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#pragma comment(lib,"ws2_32")

// 에러메세지를 띄우고 화면을 종료하는 함수
void err_quit(const char* msg) {
	LPVOID lpMsgBuf;
	FormatMessageA(
		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
		NULL, WSAGetLastError(),
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
		(char *)&lpMsgBuf, 0, NULL);
	MessageBoxA(NULL, (const char*)lpMsgBuf, msg, MB_ICONERROR);
	LocalFree(lpMsgBuf);
	exit(1);
}

// 에러메세지를 띄우는 함수
void err_display(const char* msg) {
	LPVOID lpMsgBuf;
	FormatMessageA(
		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
		NULL, WSAGetLastError(),
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
		(char *)&lpMsgBuf, 0, NULL);
	printf("[%s] %s\n", msg, (char*)lpMsgBuf);
	LocalFree(lpMsgBuf);
}

2. 리눅스 오류처리

void err_quit(const char *msg)
{
	char *msgbuf = strerror(errno);
	printf("[%s] %s\n" , msg, msgbuf);
	exit(1);
}

void err_display(const char *msg)
{
	char *msgbuf = strerror(errno);
	printf("[%s] %s\n" , msg, msgbuf); 
}

2) 소켓 초기화와 종료

윈도우에서는 소켓 생성 전에 윈속 초기화와 소켓 닫기 후에 윈속 종료 단계가 더 필요하다.

# include <winsock2.h>

// 프로그램 시작
int WSAStartup(
		WORD wVersionRequested, // 프로그램이 요구하는 최상위 윈속 버전
		LPWSADATA lpWSAData // 윈도우 운영체제가 제공하는 윈속 구현에 관한 정보
);

// 프로그램 종료
int WSACleanup(void);

실습 2-1

# include "..\..\Common.h"

it main(int argc, char *argv[])
{
	// 윈속 초기화
		WSADATA wsa;
		if(WSAStartup(MAKEWORD(2,2), &wsa) !=0) // 윈속 초기화가 실패(0이 아니라면) 한다면
			return 1; // 1 반환
		printf("[알림] 윈속 초기화 성공\n");
		
		// 윈속 종료
		WSACleanup();
		
		return 0;
}

3) 소켓 생성과 닫기

윈도우에서는 윈속 초기화를 먼저 해야하지만, 리눅스에서는 별도의 초기화 과정 없이 곧바로 소켓을 만들 수 있다.

1. 소켓 생성하기

소켓을 사용해 통신을 하려면 통신 양단이 같은 프로토콜을 사용해야함 (TCP, UDP)

socket() 함수는 사용자가 요청한 프로토콜을 사용해 통신할 수 있도록 내부적으로 리소스를 할당하고, 이에 접근할 수 있는 일종의 핸들값을 리턴한다. → 소켓 디스크립터

  • 주소체계 : IPv4 , IPv6 등
  • 소켓 타입 : TCP나 UDP 에 따라 달라짐
  • 프로토콜 : 명시적으로 지정해야 함

윈도우

#include <winsock2.h>
SOCKET socket(
	int af, // 주소 체계 타입
	int type, // 소켓 타입 지정
	int protocol // 사용할 프로토콜 지정
);

리눅스

#include <sys/types.h>
#include <sys/socket.h>
int socket(
	int domain, // 주소 체계 타입
	int type, // 소켓 타입 지정
	int protocol  // 사용할 프로토콜 지정
);

2. 소켓 닫기

소켓은 사용한 통신을 마치면 관련 리소스를 반환해야한다.

closesocket() 또는 close() 사용

윈도우

#include <winsock2.h>
int closesocket(SOCKET s);

리눅스

#include <unistd.h>
int close(int fd);

실습2-2

#include "V.Common.h"  

int main(int argc, char *argv[]) {
    // 윈속 초기화
    WSADATA wsa;
    
    // 윈속 초기화 확인
    if(WSAStartup(MAKEWORD(2,2) , &wsa) !=0)
	    return 1; // 초기화 실패 시 프로그램 종료
    printf("[알림] 윈속 초기화 성공\n");

    // 소켓 생성
    SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == INVALID_S0CKET) err_quit("socket()");
    printf("[알림] 소켓 생성 성공\n");
    
    // 소켓 닫기
    closesocket(sock);
    
    // 윈속 종료
    WSACleanup();
    return 0;
}
profile
소프트웨어공학 / 정보통신공학

0개의 댓글

관련 채용 정보