본문 바로가기

사이버보안 3학년 1학기/네트워크 프로그래밍

윈도우 소켓 프로그래밍 100%

시험끝!

나오는 문제들은 보라색으로 표시를 해둔다. (2016-04-26)


TCP/IP 윈도우 소켓 프로그래밍


24p - 어떠한 구조

호스트(End user) - 라우터 - 인터넷 - 라우터 - 호스트(End user)

호스트는 응용프로그램을 사용해서 TCP/IP 프로토콜 통신을 거친다.



27p - TCP와 UDP 특징 표 -- 객관식

 TCP 

 UDP 

 연결형

 비연결형 

 신뢰성 있음 

 신뢰성 없음 

 1:1 Unicast 

 1:1 Unicast OR 1:x Broadcast, Multicast 

 byte stream

 datagram



28p - 데이터 전송 원리 간단하게

Application

 

 

 

Data

 

 TCP

 

 

 TCP Header 

 Data 

 

 IP

 

 IP Header 

 TCP Header 

 Data 

 

 Ethernet

 Ethernet Header 

 IP Header 

 TCP Header 

 Data 

 Ethernet Trailer 


송신 측에서는 응용 프로그램부터 시작해서 이더넷까지 캡슐화

수신 측에서는 이더넷부터 시작해서 응용 프로그램까지 역캡슐화



37p - 윈도우 소켓 특징 (Winsock) -- 객관식

1) DLL 초기화와 종료 작업을 위한 함수

2) 메시지 구동 방식 함수를 가지고 있다.

3) 멀티스레드 환경 함수를 가지고 있다.

4) TCP/IP 프로토콜 지원

5) IPv6 프로토콜 지원

6) IrDA 프로토콜 지원

7) 블루투스 프로토콜 지원 



38p - 윈도우소켓 장단점 -- 객관식

장점

 유닉스 소켓 수준에서 호환성이 높아 활용성이 좋다.

 많이 사용하는 네트워크 프로그래밍 인터페이스라서 호환성이 좋다.

 많은 프로토콜을 지원하므로 최소 수정으로 사용하는 프로토콜을 변경할 수 있다.

 low 또는 mid 레벨 프로그래밍으로 세부 제어가 가능하고 고성능 프로그램 개발이 가능하다.

단점

 응용 프로그램의 프로토콜을 직접 개발해야한다. 예를 들어 데이터 형식이나 전송 절차등을 생각해서 프로그래밍 해야한다.

 서로 다른 바이트 정렬(byte ordering), 32비트와 64비트가 통신할 경우 데이터 변환이 필요하다.



64p - 소켓 주소 구조체 전반, 소스 다 읽기

네트워크에서 필요한 주소 정보를 담고 있는 struct 이다.

아래는 기본적인 SOCKADDR 구조를 가진 ws2def.h 파일이다.

typedef struct sockaddr { 

// 주소 체계를 나타내는 16bit 정수. ex) AF_INET OR AF_INET6

u_short     sa_family; 

// 주소 체계에서 사용할 주소 정보를 바이트 배열로 저장. ex) IPADDR+PORT

char         sa_data[14];

} SOCKADDR;


 구조체 이름 

 전체 크기(bytes) 

 SOCKADDR

 16 

 SOCKADDR_IN

 16 

 SOCKADDR_IN6

 28 

 SOCKADDR_IRDA

 32 

 SOCKADDR_BTH

 30 


소켓 주소를 소켓 함수 인자로 전달할 때는 항상 주소 값을 사용한다.

반드시 SOCKADDR 포인터형으로 변환해야 한다.

// 소켓 주소 구조체 초기화

SOCKADDR_IN addr;

SocketFunc ( ..., (SOCKADDR *)&addr, sizeof(addr), ...);



68p - 바이트 정렬 함수 -- 객관식

Big-endian, 최상위 바이트(MSB)부터 차례로 저장

Little-endian, 최하위 바이트(LSB)부터 차례로 저장


0x12345678 을 메모리를 저장할 때 방식

 Big-endian

 0x12

 0x34

 0x56

 0x78

 Little-endian

 0x78

 0x56

 0x34

 0x12



70p - hton, ntoh (host-to-network, network-to-host)

hton 함수는 호스트 바이트 정렬로 저장된 값을 입력받아 네트워크 바이트 정렬로 변환한 값을 보낸다.

응용프로그램이 소켓 함수에 데이터를 넘겨주기 전에 hton 호출


ntoh 함수는 네트워크 바이트 정렬로 저장된 값을 입력받아 호스트 바이트 정렬로 변환한 값을 보낸다.

소켓 함수가 응용프로그램에 데이터를 넘겨주기 전에 ntoh 호출


단순하게 ntoh는 hton의 반대



73p - 주소변환


IPv4 주소 변환

// 문자열(192.168.100.1) -> 32비트 숫자(11000000 10101000 01100100 00000001)

unsigned long inet_addr(const char *cp);

// 32비트 숫자 -> 문자열

char *inet_ntoa(struct in_addr in);


IPv6 와 IPv4 주소 변환

int WSAStringToAddress(

LPTSTR AddrString, //문자열 IP주소

INT AddrFamily, //AF_INET 또는 AF_INET6

LPWSAPROTOCOL_INFO lpProtocolInfo,

LPSOCKADDR lpAddr, // IP주소를 저장할 구조체

LPINT lpAddrLen //위 구조체의 길이

);


int WSAAddressToString(

LPSOCKADDR lpsaAddr, //32비트 숫자 IP주소

DWORD dwAddrLen, // 구조체 길이

LPWSAPROTOCOL_INFO lpProtocolInfo,

LPSTR lpszAddrString, // 문자열 IP주소를 저장할 구조체

LPDWORD lpdwAddrStringLen // 버퍼 길이

);


inet_addr 과 addr.sin_addr 함수는 이미 32비트 정렬된 IP 이므로 htonl이나 ntohl 함수를 쓰면 아니된다.



92p - 서버와 클라이언트 동작원리

서버는 소켓을 생성한다. ▶ 서버는 클라이언트 연결을 기다린다. (특정 포트번호만 연결)

▶ 클라이언트가 서버에 접속한다. (TCP 패킷교환, 1:SYN, 2:SYN/ACK, 3:ACK)

▶ 서버는 통신을 위한 새로운 소켓을 생성한다. (기존 소켓은 새로운 클라이언트를 받음)

▶ 다른 클라이언트가 접속한다면 새로 생성한 것을 제외하고 기존에 있던 소켓을 사용한다.



94p - TCPServer 와 TCPClient 소스코드 괄호넣기, socket(), bind(), listen(), connect(), accept(), 중요한부분

주관식 빈칸문제이며 빈칸인 부분은 보라색 표시함.


SEVERPORT와 SERVERIP는 정의된 값입니다.


socket ()

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

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


bind ()

SOCKADDR_IN serveraddr;

ZeroMemory(&serveraddr, sizeof(serveraddr)); // memset (&saddr, 0, sizeof()); 도 가능함.

serveraddr.sin_family = AF_INET; // IPv4 사용

serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); // 아무 클라이언트IP 접속가능

serveraddr.sin_port = htons(SERVERPORT);

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

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


listen ()

retval = listen(listen_sock, SOMAXCONN);

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


accept ()

addrlen = sizeof(clientaddr);

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

if(client_sock == INVALID_SOCKET) {

err_display("accept()");

break; // While문이 앞에 열려 있음.

}


connect ()

SOCKADDR_IN serveraddr;

ZeroMemory(&serveraddr, sizeof(serveraddr));

serveraddr.sin_family = AF_INET;

serveraddr.sin_addr.s_addr = inet_addr(SERVERIP);

serveraddr.sin_port = htons(SERVERPORT);

retval = connect(sock, (SOCKADDR *)&serveraddr, sizeof(serveraddr));

if(retval == SOCKET_ERROR) err_quit("connect()");



106p - TCP 서버 함수들이 무엇을 하는 기능인지 설명 -- 주관식


TCP 서버 함수

 socket( )

 소켓을 생성하여 사용할 프로토콜을 결정

 bind( )

 지역 IP주소와 포트 번호를 설정

 listen( )

 TCP를 LISTENING상태로 변경

 accept( )

 클라이언트와 통신할 수 있는 새로운 소켓 생성(원격IP주소+포트 결정)

 closesocket( )

 send, recv 실행 후 소켓을 닫음



112p - TCP 클라이언트 함수들이 무엇을 하는 기능인지 설명 -- 주관식


TCP 클라이언트 함수

 socket( )

 소켓을 생성하여 사용할 프로토콜을 설정 

 connect( )

 서버 접속 시 원격IP+포트 와 지역IP+포트 설정

 closesocket( )

 send, recv 실행 후 소켓을 닫음



134p - 데이터 전송 경계 구분 4가지 -- 주관식

번호

 수신자

 송신자

 1

 고정길이 데이터 보냄

 고정길이 데이터 읽음 

 2

 가변길이 데이터+EOR

 EOR이 나올 때까지 데이터 읽음

 3

 보낼 크기: 고정길이 데이터

 가변길이 데이터 보냄

 고정길이 데이터를 읽고 가변 길이 알아냄

 그 길이만큼 데이터 읽음

 4

 가변길이 데이터 전송 후 접속 종료

 recv함수의 return값이 0이 될 때까지 읽음



138p - 고정길이 데이터전송, 고정길이+가변길이 데이터 전송 개념 알기

이 부분은 책을 참고한다. 소스 코드의 전체를 복붙할 수는 없다..


174p - 스레드 기본 개념 -- 객관식

일반적인 프로세스 = 윈도우 프로세스 + 스레드

윈도우에서 프로세스 

 code, data 등을 저장하는 컨테이너, 정적임

 스레드

 CPU 시간을 받아 프로세스 메모리의 code 수행, 동적임

 메인 스레드

 Winmain() 또는 main() 함수에서 시작.

 이를 활용하여 멀티스레드로 만듦


스레드의 context switch (간단하게 표현)

조건: 메모리의 스택은 유지된다. / CPU 레지스터의 값이 수정된다.

스레드가 A, B가 있다.

스레드 A가 실행 중 일 때, 스레드A의 상태를 저장하고, 

스레드B를 불러와 실행하고, 스레드B의 상태를 저장하고, 저장된 스레드 A를 불러와서 실행한다.



180p - 스레드 종료하는 방법 4가지 -- 객관식

 스레드 함수가 리턴한다. 

 권장사항

 스레드 함수 안에서 ExitThread( ) 함수를 호출한다.

 다른 스레드가 TerminateThread( ) 함수를 호출해 스레드를 강제 종료시킨다.

 필요한 경우

 주 스레드가 종료하면 모든 스레드가 종료된다.

 메인스레드 특성