• 검색 결과가 없습니다.

• 데이터 타입

N/A
N/A
Protected

Academic year: 2022

Share "• 데이터 타입"

Copied!
24
0
0

로드 중.... (전체 텍스트 보기)

전체 글

(1)

‰ 16강 윈속(WinSock)

‰ TCP/IP 프로토콜 구조

• TCP와 UDP

비신뢰적인 데이터 전송 - 데이터를 재전송하지 않음 신뢰성 있는 데이터 전송

- 데이터를 재전송함

1 대 1 통신(unicast), 1 대 다 통신(broadcast), 다 대 다 통신(multicast) 1 대 1 통신(unicast)

데이터 경계를 구분함

- 데이터그램(datagram) 서비스 데이터 경계를 구분하지 않음

- 바이트 스트림(byte-stream) 서비스

비연결형(connectionless) 프로토콜 - 연결 없이 통신 가능

연결형(connection-oriented) 프로토콜 - 연결이 성공해야 통신 가능

UDP TCP

(2)

- 2 -

‰ 클라이언트/서버 모델

• 클라이언트/서버(client/server) 모델

– 두 개의 애플리케이션이 상호 작용하는 방식을 나타냄

• 서버가 먼저 실행하여 대기

• 클라이언트가 서버에게 요청을 하면 서버는 이 요청을 받아 처리

서버 클라이언트

대기

접속

‰ 소켓의 개념 (1/5)

• 세 가지 관점

① 데이터 타입

② 통신 종단점(communication end-point)

③ 네트워크 프로그래밍 인터페이스

(3)

- 4 -

‰ 소켓의 개념 (2/5)

• 데이터 타입

– 운영체제가 통신을 위해 관리하는 데이터를 간접적으로 참조할 수 있도록 만든 일종의 핸들(handle)

– 생성과 설정 과정이 끝나면 이를 이용하여 통신과 관련된 다양한 작업을 할 수 있는 간편한 데이터 타입

// 파일 생성

int fd = open("myfile", ...);

...

read(fd, ...) // 읽기 write(fd, ...) // 쓰기

// 소켓 생성

SOCKET sock = socket(...);

...

recv(sock, ...) // 받기 send(sock, ...) // 보내기

‰ 소켓의 개념 (3/5)

• 통신 종단점

– 소켓은 통신을 위해 필요한 여러 요소의 집합체

• 사용할 프로토콜(TCP/IP, UDP/IP 등)

• 송신측 IP 주소, 송신측 포트 번호

• 수신측 IP 주소, 수신측 포트 번호

– 애플리케이션은 자신의 소켓이 상대방의 소켓과 연결된 것으로 생각하고 데이터를 교환

(4)

- 6 -

‰ 소켓의 개념 (4/5)

• 통신 종단점(cont’d)

클라이언트 send (sock, ...)

서버 recv (sock, ...) 데이터

<클라이언트 소켓>

• 프로토콜: TCP/IP

• IP 주소: 147.46.114.70

• 포트 번호: 12023

<서버 소켓>

• 프로토콜: TCP/IP

• IP 주소: 61.72.244.22

• 포트 번호: 9001

‰ 소켓의 개념 (5/5)

• 네트워크 프로그래밍 인터페이스

– 통신 양단이 모두 소켓을 사용할 필요는 없음

– TCP/IP 프로토콜 구조에서 (일반적으로) 애플리케이션 계 층과 전송 계층 사이에 위치하는 것으로 간주

애플리케이션

TCP UDP

애플리케이션 애플리케이션

소켓 인터페이스

ICMP, IGMP

(5)

- 8 -

‰ 윈도우 소켓 (1/6)

• 윈도우 소켓(Windows Sockets, Winsock)

– 버클리 유닉스(Berkeley Software Distribution UNIX)에서 개발한 네트워크 프로그래밍 인터페이스를 윈도우 환경에 서 사용할 수 있도록 한 것

• 소스 코드 수준에서 호환성이 높음

– 윈도우 95 버전부터 API (Application Programming Interface)에 정식으로 포함되어 제공

‰ 윈도우 소켓 (2/6)

• 유닉스 소켓과의 차이점

– 윈도우 소켓은 DLL을 통해 대부분의 기능이 제공되므로 DLL 초기화와 종료 작업을 위한 함수가 필요

– 윈도우 애플리케이션은 대개 그래픽 사용자 인터페이스 (GUI, Graphical User Interface)를 기반으로 하며, 메시지 구동 방식으로 동작하므로 이를 위한 확장 함수가 존재 – 윈도우는 운영체제 차원에서 멀티스레드(multithread)를

지원하므로 멀티스레드 환경에서 안정적으로 동작하기 위 한 구조와 이를 위한 함수가 필요

(6)

- 10 -

‰ 윈도우 소켓 (3/6)

• 운영체제별 지원 사항

• 지원 프로토콜

– TCP/IP, IPv6(윈도우 XP 이상), IrDA(윈도우 98 이상), Bluetooth(윈도우 XP SP2 이상), IPX/SPX,

ATM, DECNet, TP4(윈도우 2000부터 지원하지 않음), DLC(윈도우 XP부터 지원하지 않음),

NetBEUI(윈도우 XP부터 지원하지 않음)

1.1 (2.2) 윈도우 CE

2.2 윈도우 98/Me, 윈도우 NT/2000/XP/2003

1.1 (2.2) 윈도우 95

윈속 버전 운영체제

‰ 윈도우 소켓 (4/6)

• 장점

– 유닉스 소켓과 소스 코드 수준에서 호환성이 높으므로 기 존 프로그램을 포팅하기가 쉬움

– 가장 널리 쓰이는 네트워크 프로그래밍 인터페이스이므로 한번 배워두면 여러 환경(윈도우, 유닉스, ...)에서 사용할 수 있음

– TCP/IP 이외에도 다양한 종류의 프로토콜을 지원하므로 최소한의 코드 수정으로 애플리케이션에서 사용할 프로토 콜을 변경 가능

– 비교적 저수준(low-level 혹은 mid-level)의 프로그래밍 인터페이스로, 세부적인 제어가 가능하므로 고성능의 네 트워크 애플리케이션을 개발할 수 있음

(7)

- 12 -

‰ 윈도우 소켓 (5/6)

• 단점

– 애플리케이션 수준의 프로토콜을 프로그래머가 직접 설계 해야 함

• 데이터 포맷이나 전송 절차 등을 고려하여 프로그래밍해야 하므로 프로토콜을 변경할 경우 코드 수정이 불가피

– 서로 다른 바이트 정렬(byte ordering) 방식을 사용하거나 데이터 처리 단위(32비트, 64비트, ...)가 서로 다른 종단 시스템간 통신을 할 경우, 애플리케이션 수준에서 데이터 변환을 처리해야 함

‰ 윈속 애플리케이션 작성

• 윈속 라이브러리 추가

(8)

- 14 -

‰ 윈속 함수 오류 처리 (1/2)

• 오류 유형

① 오류를 처리할 필요가 없는 경우

• 리턴값이 없거나 호출시 항상 성공하는 일부 소켓 함수

② 리턴값만으로 오류를 처리하는 경우

• WSAStartup() 함수

③ 리턴값으로 오류 발생을 확인하고, 구체적인 내용은 오류 코드를 이용하여 확인하는 경우

• 대부분의 소켓 함수

‰ 윈속 함수 오류 처리 (2/2)

• 오류 코드 얻기

• 사용 예

int WSAGetLastError (void) ;

if (소켓함수(...) == 오류) {

int errcode = WSAGetLastError();

printf(errcode에 해당하는 오류 메시지);

}

(9)

- 16 -

‰ 오류 코드를 문자열로 바꾸기 (1/4)

• FormatMessage() 함수

DWORD FormatMessage ( DWORD dwFlags, // ① 옵션 LPCVOID lpSource, // NULL

DWORD dwMessageId, // ② 오류 코드 DWORD dwLanguageId, // ③ 언어

LPTSTR lpBuffer, // ④ 오류 문자열 시작 주소 DWORD nSize, // 0

va_list* Arguments // NULL ) ;

성공: 오류 메시지의 길이, 실패: 0

‰ 오류 코드를 문자열로 바꾸기 (2/4)

• err_quit() 함수 정의

#include <winsock2.h>

#include <stdlib.h>

void err_quit(char *msg) {

LPVOID lpMsgBuf;

FormatMessage(

FORMAT_MESSAGE_ALLOCATE_BUFFER|

FORMAT_MESSAGE_FROM_SYSTEM, NULL, WSAGetLastError(),

MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL);

MessageBox(NULL, (LPCTSTR)lpMsgBuf, msg, MB_ICONERROR);

LocalFree(lpMsgBuf);

exit(-1);

}

(10)

- 18 -

‰ 오류 코드를 문자열로 바꾸기 (3/4)

• err_quit() 함수 사용 예

• 오류 출력 화면

if (socket(...) == SOCKET_ERROR) err_quit("socket()");

if (bind(...) == SOCKET_ERROR) err_quit("bind()");

err_quit() 함수에 전달한 문자열

오류 코드에 해당하는 문자열

‰ 오류 코드를 문자열로 바꾸기 (4/4)

• err_display() 함수 정의

#include <winsock2.h>

#include <stdlib.h>

void err_display(char *msg) {

LPVOID lpMsgBuf;

FormatMessage(

FORMAT_MESSAGE_ALLOCATE_BUFFER|

FORMAT_MESSAGE_FROM_SYSTEM, NULL, WSAGetLastError(),

MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL);

printf("[%s] %s", msg, (LPCTSTR)lpMsgBuf);

LocalFree(lpMsgBuf);

}

(11)

- 20 -

‰ 윈속 초기화와 종료 (1/3)

• 윈속 초기화 함수

– wVersionRequested

• 프로그램이 요구하는 최상위 윈속 버전. 하위 8비트에 주(major) 버전을, 상위 8비트에 부(minor) 버전을 넣어서 전달함

– lpWSAData

• WSADATA 타입 변수의 주소. 시스템에서 제공하는 윈속 구현에 대한 세부 사항을 얻을 수 있음

int WSAStartup (

WORD wVersionRequested, LPWSADATA lpWSAData ) ;

성공: 0, 실패: 오류 코드

‰ 윈속 초기화와 종료 (2/3)

• 윈속 종료 함수

int WSACleanup (void) ;

성공: 0, 실패: SOCKET_ERROR

(12)

- 22 -

‰ 윈속 초기화와 종료 (3/3)

• 예제 코드

#include <winsock2.h>

int main(int argc, char* argv[]) {

// 윈속 초기화 WSADATA wsa;

if(WSAStartup(MAKEWORD(2,2), &wsa) != 0) return -1;

MessageBox(NULL, "윈속 초기화 성공", "성공", MB_OK);

// 윈속 종료 WSACleanup();

return 0;

}

‰ 소켓 생성과 닫기 (1/6)

• 소켓 생성 함수

– 사용자가 요청한 프로토콜을 이용하여 통신을 할 수 있도 록 내부적으로 리소스를 할당하고, 이를 접근할 수 있는 일종의 핸들값(SOCKET 타입, 32비트 정수)인 소켓 디스 크립터(socket descriptor)를 리턴

SOCKET socket ( int af, // 주소 체계 int type, // 소켓 타입 int protocol // 프로토콜 ) ;

성공: 새로운 소켓, 실패: INVALID_SOCKET

(13)

- 24 -

‰ 소켓 생성과 닫기 (2/6)

• 주소 체계

#define AF_UNIX 1 /* local to host (pipes, portals) */

#define AF_INET 2 /* internetwork: UDP, TCP, etc. */

#define AF_IMPLINK 3 /* arpanet imp addresses */

#define AF_PUP 4 /* pup protocols: e.g. BSP */

#define AF_CHAOS 5 /* mit CHAOS protocols */

#define AF_NS 6 /* XEROX NS protocols */

#define AF_IPX AF_NS /* IPX protocols: IPX, SPX, etc. */

#define AF_ISO 7 /* ISO protocols */

#define AF_OSI AF_ISO /* OSI is ISO */

...

‰ 소켓 생성과 닫기 (3/6)

• 소켓 타입

– 사용할 프로토콜의 특성

• 예) TCP와 UDP 프로토콜 설정(1)

비신뢰적인 데이터 전송 기능 제공 비연결형 프로토콜

SOCK_DGRAM

신뢰성 있는 데이터 전송 기능 제공 연결형 프로토콜

SOCK_STREAM

특성 소켓 타입

SOCK_DGRAM UDP

SOCK_STREAM AF_INET

TCP

소켓 타입 주소 체계

사용할 프로토콜

(14)

- 26 -

‰ 소켓 생성과 닫기 (4/6)

• 프로토콜

– 주소 체계와 소켓 타입이 같더라도 이에 해당하는 프로토 콜이 두 개 이상 존재할 경우 프로토콜을 명시적으로 지정

• 예) TCP와 UDP 프로토콜 설정(2)

• 예) TCP와 UDP 프로토콜 설정(3)

SOCK_DGRAM SOCK_STREAM

소켓 타입

IPPROTO_UDP UDP

IPPROTO_TCP AF_INET

TCP

프로토콜 주소 체계

사용할 프로토콜

SOCK_DGRAM SOCK_STREAM

소켓 타입

0 UDP

AF_INET 0 TCP

프로토콜 주소 체계

사용할 프로토콜

‰ 소켓 생성과 닫기 (5/6)

• 소켓 종료 함수

– 소켓을 닫고 관련 리소스를 반환

int closesocket ( SOCKET s ) ;

성공: 0, 실패: SOCKET_ERROR

(15)

- 28 -

‰ 소켓 생성과 닫기 (6/6)

• 예제 코드

int main(int argc, char* argv[]) {

// 윈속 초기화 ...

// socket()

SOCKET tcp_sock = socket(AF_INET, SOCK_STREAM, 0);

if(tcp_sock == INVALID_SOCKET) err_quit("socket()");

MessageBox(NULL, "TCP 소켓 생성 성공", "성공", MB_OK);

// closesocket()

closesocket(tcp_sock);

// 윈속 종료 ...

}

‰ 바이트 정렬 함수 (1/5)

• 바이트 정렬(byte ordering)

– 메모리에 데이터를 저장할 때의 방식(바이트 순서)

• 빅 엔디안(big-endian, RISC 계열)

– 낮은 메모리주소에 높은 자리수의 값을 저장하는 방식

• 리틀 엔디안(little-endian, Intel 계열)

0x12 0x34 0x56 0x78

0x78 0x56 0x34 0x12

빅 엔디안

리틀 엔디안

0x1000 0x1001 0x1002 0x1003

‚ ‚ ‚

‚ ‚ ‚

‚ ‚ ‚

‚ ‚ ‚

(16)

- 30 -

‰ 바이트 정렬 함수 (2/5)

• 네트워크 애플리케이션에서 바이트 정렬 방식을 고 려해야 하는 경우(cont’d)

– 프로토콜 구현을 위해 필요한 정보

• (a) IP 주소 Ö 빅 엔디안

• (b) 포트 번호 Ö 빅 엔디안

– 애플리케이션이 주고 받는 데이터

• (c) 빅 엔디안 또는 리틀 엔디안으로 통일

™ 네트워크 바이트 정렬(network byte ordering) : 빅 엔디안 방식

™ 호스트 바이트 정렬(host byte ordering) : 시스템이 사용하는 고유한 바이트 정렬 방식 참고

‰ 바이트 정렬 함수 (3/5)

• 바이트 정렬 함수(유닉스 호환)

• 바이트 정렬 함수(윈속 확장)

u_short htons (u_short hostshort); // host-to-network-short

u_long htonl (u_long hostlong); // host-to-network-long, 클라이언트측 u_short ntohs (u_short netshort); // network-to-host-short

u_long ntohl (u_long netlong); // network-to-host-long, 서버측

int WSAHtons (SOCKET s, u_short hostshort, u_short* lpnetshort);

int WSAHtonl (SOCKET s, u_long hostlong, u_long* lpnetlong);

int WSANtohs (SOCKET s, u_short netshort, u_short* lphostshort);

int WSANtohl (SOCKET s, u_long netlong, u_long* lphostlong);

(17)

- 32 -

‰ 바이트 정렬 함수 (4/5)

• 바이트 정렬 함수 사용

소켓 함수

hton*( )

소켓 함수에게 넘겨줄 데이터

소켓 함수

ntoh*( )

애플리케이션이 사용

소켓 함수가 결과로 전달

‰ 바이트 정렬 함수 (5/5)

• SOCKADDR_IN 구조체의 바이트 정렬 방식

sin_family (2) sin_port

(2) sin_addr

(4)

sin_zero (8)

SOCKADDR_IN{}

호스트 바이트 정렬

네트워크 바이트 정렬

(18)

- 34 -

‰ IP 주소 변환 함수 (1/2)

• IP 주소 변환 예

‰ IP 주소 변환 함수 (2/2)

• IP 주소 변환 함수

– 문자열 형태로 IP 주소를 입력받아 32비트 숫자(네트워크 바이트 정렬)로 리턴

– 32비트 숫자(네트워크 바이트 정렬)로 IP 주소를 입력받아 문자열 형태로 리턴

unsigned long inet_addr (const char* cp);

char* inet_ntoa (struct in_addr in); // network-to-ascii

(19)

- 36 -

‰ 도메인 이름 시스템과 이름 변환 함수 (1/2)

• 도메인 이름(domain name)

– IP 주소와 대응되는 (기억하기 쉬운) 이름

• 도메인 이름 Ö IP 주소 변환 예

‰ 도메인 이름 시스템과 이름 변환 함수 (2/2)

• 도메인 이름 Ù IP 주소 변환 함수

/* 도메인 이름 Œ IP 주소(네트워크 바이트 정렬) */

struct hostent* gethostbyname ( const char* name // 도메인 이름 );

/* IP 주소(네트워크 바이트 정렬) Œ 도메인 이름 */

struct hostent* gethostbyaddr (

const char* addr, // 네트워크 바이트 정렬된 IP 주소 int len, // IP 주소의 길이(예: 4)

int type // 주소 체계(예: AF_INET) );

(20)

- 38 -

‰ TCP 서버/클라이언트 예제

• 예제 동작 방식

TCP 클라이언트 TCP 서버

fgets() send()

printf()

recv() printf()

send() recv()

‰ TCP 서버 함수 (1/8)

• TCP 서버 함수

socket() bind()

recv() send()

socket()

send() recv()

TCP 서버 TCP 클라이언트

connect() listen()

accept()

네트워크

(21)

- 40 -

‰ TCP 서버 함수 (2/8)

• bind() 함수

– 서버의 지역 IP 주소와 지역 포트 번호를 결정

int bind ( SOCKET s,

const struct sockaddr* name, int namelen

) ;

성공: 0, 실패: SOCKET_ERROR

‰ TCP 서버 함수 (3/8)

• bind() 함수 사용 예

050 SOCKADDR_IN serveraddr;

051 ZeroMemory(&serveraddr, sizeof(serveraddr));

052 serveraddr.sin_family = AF_INET;

053 serveraddr.sin_port = htons(9000);

054 serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);

055 retval = bind(listen_sock, (SOCKADDR *)&serveraddr, sizeof(serveraddr));

056 if(retval == SOCKET_ERROR) err_quit("bind()");

(22)

- 42 -

‰ TCP 서버 함수 (4/8)

• listen() 함수

– 소켓과 결합된 TCP 포트 상태를 LISTENING으로 변경

int listen ( SOCKET s, int backlog ) ;

성공: 0, 실패: SOCKET_ERROR

‰ TCP 서버 함수 (5/8)

• listen() 함수 사용 예

059 retval = listen(listen_sock, SOMAXCONN);

060 if(retval == SOCKET_ERROR) err_quit("listen()");

(23)

- 44 -

‰ TCP 서버 함수 (6/8)

• accept() 함수

– 접속한 클라이언트와 통신할 수 있도록 새로운 소켓을 생 성하여 리턴

– 접속한 클라이언트의 IP 주소와 포트 번호를 알려줌

SOCKET accept ( SOCKET s,

struct sockaddr* addr, int* addrlen

) ;

성공: 새로운 소켓, 실패: INVALID_SOCKET

‰ TCP 서버 함수 (7/8)

• accept() 함수 사용 예

062 // 데이터 통신에 사용할 변수 063 SOCKET client_sock;

064 SOCKADDR_IN clientaddr;

065 int addrlen;

...

068 while(1){

069 // accept()

070 addrlen = sizeof(clientaddr);

071 client_sock = accept(listen_sock, (SOCKADDR *)&clientaddr, &addrlen);

072 if(client_sock == INVALID_SOCKET){

073 err_display("accept()");

074 continue;

075 }

(24)

- 46 -

‰ TCP 서버 함수 (8/8)

• accept() 함수 사용 예 (cont’d)

076 printf("₩n[TCP 서버] 클라이언트 접속: IP 주소=%s, 포트 번호=%d₩n", 077 inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));

078

079 // 클라이언트와 데이터 통신 080 while(1){

...

101 } 102

103 // closesocket()

104 closesocket(client_sock);

105 printf("[TCP 서버] 클라이언트 종료: IP 주소=%s, 포트 번호=%d₩n", 106 inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));

107 }

‰ TCP 클라이언트 함수

• TCP 클라이언트 함수

socket() bind()

recv() send()

socket()

send() recv()

TCP 서버 TCP 클라이언트

connect() listen()

accept()

네트워크

참조

관련 문서

- 인적자원 종합정보체계는 교육시장과 노동시장의 정보를 기반으로 인적 자원 정책조정을 위한 정보 인프라를 구축하여야 하며, 이를 위하여 교

데이터 전송 및 함수 로딩 요청 메시지 타입인 MAPI_FREQ 와 데이터 전송 및 함수 로딩 요청 메시지의 응답 타입인 MAPI_FACK 의 경우만 메시지 패 킹과

훈련생은 그래픽 사용자 인터페이스를 통해 실제 기관실의 기기를 운전하듯이 모의 운전훈련을 받을 수 있으며,교육자 역시 이를 통해 관련 기기의 운전 특성 에

사용자 경험 측정 사용자 경험 측정 (Measuring User Experience) (Measuring User Experience)6. Self-Recorded Metrics

사용자 경험 측정 사용자 경험 측정 (Measuring User Experience) (Measuring User Experience)6. Self-Recorded Metrics

기존의 형광등과 평균수명에서 차이가 나는지 검정하기 위해 각각의 형광등에서 표본을 30 개씩 추출하여 다음과 같은

 Study Goals, User Goals, Choosing Right

사용자 경험 측정 사용자 경험 측정 (Measuring User Experience) (Measuring User Experience)5. Issue-Based Metrics