Network Programming

Similar documents
Network Programming

Microsoft PowerPoint - Supplement-02-Socket Overview.ppt [호환 모드]

The Pocket Guide to TCP/IP Sockets: C Version

Microsoft PowerPoint - 12 ¼ÒÄÏÀ» ÀÌ¿ëÇÑ Åë½Å 1.ppt

Microsoft PowerPoint - Lecture_Note_5.ppt [Compatibility Mode]

제1장 Unix란 무엇인가?

Microsoft PowerPoint - 13 ¼ÒÄÏÀ» ÀÌ¿ëÇÑ Åë½Å 2.ppt

The Pocket Guide to TCP/IP Sockets: C Version

PowerPoint 프레젠테이션

À©µµ³×Æ®¿÷ÇÁ·Î±×·¡¹Ö4Àå_ÃÖÁ¾

2009년 상반기 사업계획

슬라이드 1

본 강의에 들어가기 전

<4D F736F F F696E74202D E20B3D7C6AEBFF6C5A920C7C1B7CEB1D7B7A1B9D62E >

Microsoft PowerPoint - 06-CompSys-16-Socket.ppt

PowerPoint 프레젠테이션

제1장 Unix란 무엇인가?

슬라이드 1

본 강의에 들어가기 전

PowerPoint 프레젠테이션

슬라이드 1

2009년 상반기 사업계획

Microsoft PowerPoint - 09-CE-23-윈도우 소켓

vi 사용법

Chapter 4 UDP 소켓 사용법

The Pocket Guide to TCP/IP Sockets: C Version

The OSI Model

Microsoft PowerPoint - all_CDSP_2(2009).ppt [호환 모드]

슬라이드 1

Microsoft PowerPoint - Supplement-03-TCP Programming.ppt [호환 모드]

Microsoft PowerPoint - 15-EmbedSW-10-Socket

SYN flooding

<4D F736F F D2034C0E52D554E495820BCD2C4CF20C0C0BFEB20C7C1B7CEB1D7B7A1B9D6>

Microsoft PowerPoint - 03-TCP Programming.ppt

제1장 Unix란 무엇인가?

Microsoft PowerPoint - 04-UDP Programming.ppt

<43B7CE20BECBBEC6BAB8B4C220BCD2C4CFC7C1B7CEB1D7B7A1B9D62E687770>

<C0CCBCBCBFB52DC1A4B4EBBFF82DBCAEBBE7B3EDB9AE2D D382E687770>

The Pocket Guide to TCP/IP Sockets: C Version

6주차.key

본 강의에 들어가기 전

Microsoft Word - Network Programming_NewVersion_01_.docx

Microsoft PowerPoint - Lecture_Note_7.ppt [Compatibility Mode]

Microsoft PowerPoint PythonGUI-socket

The Pocket Guide to TCP/IP Sockets: C Version

임베디드시스템설계강의자료 6 system call 2/2 (2014 년도 1 학기 ) 김영진 아주대학교전자공학과

The Pocket Guide to TCP/IP Sockets: C Version

좀비프로세스 2

3. 다음장에나오는 sigprocmask 함수의설명을참고하여다음프로그램의출력물과그출력물이화면이표시되는시점을예측하세요. ( 힌트 : 각줄이표시되는시점은다음 4 가지중하나. (1) 프로그램수행직후, (2) kill 명령실행직후, (3) 15 #include <signal.

1장. 유닉스 시스템 프로그래밍 개요

Microsoft PowerPoint - ch09_파이프 [호환 모드]

2009년 상반기 사업계획

ABC 11장

10.

The Pocket Guide to TCP/IP Sockets: C Version

슬라이드 1

3. 다음장에나오는 sigprocmask 함수의설명을참고하여다음프로그램의출력물과그출력물이화면이표시되는시점을예측하세요. ( 힌트 : 각줄이표시되는시점은다음 6 가지중하나. (1) 프로그램수행직후, (2) 5 초후 (3) 10 초후 (4) 15 #include <signa

Chapter #01 Subject

PowerPoint 프레젠테이션

<4D F736F F F696E74202D20B8AEB4AABDBA20BFC0B7F920C3B3B8AEC7CFB1E22E BC8A3C8AF20B8F0B5E55D>

10. 시스템 프로그래밍

슬라이드 1

Microsoft PowerPoint - chap06-2pointer.ppt

Microsoft PowerPoint - Lecture_Note_2.ppt [Compatibility Mode]

Microsoft PowerPoint - 09-Pipe

Unix Network Programming Chapter 4. Elementary TCP Sockets

9장 윈도우 소켓 프로그래밍

Chap06(Interprocess Communication).PDF

1장. 유닉스 시스템 프로그래밍 개요

bn2019_2

금오공대 컴퓨터공학전공 강의자료

SMB_ICMP_UDP(huichang).PDF

[ 마이크로프로세서 1] 2 주차 3 차시. 포인터와구조체 2 주차 3 차시포인터와구조체 학습목표 1. C 언어에서가장어려운포인터와구조체를설명할수있다. 2. Call By Value 와 Call By Reference 를구분할수있다. 학습내용 1 : 함수 (Functi

1. What is AX1 AX1 Program은 WIZnet 사의 Hardwired TCP/IP Chip인 iinchip 들의성능평가및 Test를위해제작된 Windows 기반의 PC Program이다. AX1은 Internet을통해 iinchip Evaluation

Microsoft PowerPoint - chap13-입출력라이브러리.pptx

TCP.IP.ppt

Microsoft Word - KPMC-400,401 SW 사용 설명서

PowerPoint 프레젠테이션

untitled

자바-11장N'1-502

The Pocket Guide to TCP/IP Sockets: C Version

Microsoft PowerPoint UnixNetProg.ppt [호환 모드]

Microsoft PowerPoint - ch09 - 연결형리스트, Stack, Queue와 응용 pm0100

chap7.key

1217 WebTrafMon II

Microsoft PowerPoint - ch07 - 포인터 pm0415

11장 포인터

PowerPoint 프레젠테이션

Microsoft PowerPoint - UnixNetProg.ppt [호환 모드]

IPv6 적용

hd132x_k_v1r3_Final_.PDF

Microsoft PowerPoint - 3ÀÏ°_º¯¼ö¿Í »ó¼ö.ppt

[ 네트워크 1] 3 주차 1 차시. IPv4 주소클래스 3 주차 1 차시 IPv4 주소클래스 학습목표 1. IP 헤더필드의구성을파악하고요약하여설명할수있다. 2. Subnet ID 및 Subnet Mask 를설명할수있고, 각클래스의사용가능한호스트수와사설 IP 주소및네트

Microsoft Word doc

게시판 스팸 실시간 차단 시스템

Microsoft PowerPoint - chap02-C프로그램시작하기.pptx

학번 : 이름 1. 다음프로그램실행결과를예측하시오. $./a.out & [1] 7216 $ kill -USR $ kill -USR 아래학생이작성한쓰레드코드의문제점을설명하시오. void* thread_main() { pthread_mutex_t

PowerPoint 프레젠테이션

임베디드시스템설계강의자료 6 system call 1/2 (2014 년도 1 학기 ) 김영진 아주대학교전자공학과

0x00 Contents 0x About Nickster 0x Analaysis 0x Exploit

Transcription:

<1> <CDP: Socket Programming> Part 3 Socket Programming (Unix 기반 )

<2> <CDP: Socket Programming> 목차 Socket 의개념 BSD 소켓 API 의소개 Socket 생성및 ID IP 주소변환설명 Socket 사용형태 소켓을이용한클라이언트및서버프로그램작성방법소개 채칭프로그램작성

<3> <CDP: Socket Programming> 1. Socket 개념

<4> <CDP: Socket Programming> 1.1 Socket 의개념 (1/2) TCP/IP 를이용하는 API 1982 년 BSD(Berkeley Software Distribution) 유닉스 4.1 윈도우소켓 ( 윈속 ), 자바소켓등도 TCP/IP 를이용하기 위한 API 를제공

<5> <CDP: Socket Programming> 1.1 Socket 의개념 (2/2) Socket 소개 IP 어드레스와포트, 소켓의관계

<6> <CDP: Socket Programming> 1.2 Berkeley socket (1/2) o UNIX system을위하여가장많이보급되고있는두가지통신 API - Berkeley socket - System V TLI(Transport Layer Interface) - C programming language를위하여개발 o Network I/O는 File I/O보다더욱상세하고많은선택사항들을필요로한다. - 망연결을초기화하기위해서프로그램은자신의역할이어떤것인지알아야함 - 망연결은연결지향형또는비연결형이될수있음 - 이름은화일운용에대해서보다망에있어서더욱중요하다. - 망연결에필요한매개변수들은 file I/O보다많다. { 규약, 지역주소, 지역프로세스, 상대주소, 상대프로세스 }

<7> <CDP: Socket Programming> 1.2 Berkeley socket (2/2) o Berkeley Socket( 계속 ) Sockets TLI Messages FIFOs Server: allocate space t_alloc() create endpoint socket() t_open() msgget() mknod() open() bind address bind() t_bind() specify queue listen() wait for connection accept() t_listen() get new fd t_open() Client: allocate space t_alloc() create endpoint socket() t_open() msgget() open() bind address bind() t_bind() connect to server connect() t_connect() transfer data read() write() recv() send() read() write() t_rcv() t_snd() msgrcv() msgsnd() read() write() datagrams recvfrom() t_rcvudata( sendto() ) t_sndudata( ) terminate close() t_close() msgctl() close() shutdown() t_sndrel() unlink() t_snddis()

<8> <CDP: Socket Programming> 1.3 Socket 프로그램작성구조 (1/4) C 언어에서 TCP 소켓프로그램 connection-oriented protocol

<9> <CDP: Socket Programming> 1.3 Socket 프로그램작성구조 (2/4) Java 언어에서 TCP 소켓프로그램 connection-oriented protocol

<10> <CDP: Socket Programming> 1.3 Socket 프로그램작성구조 (3/4) Server (connectionless protocol) socket() C 언어에서 UDP 소켓프로그램 connectionless protocol bind() Client recvfrom() socket() blocks until data received from a client data (request) bind() sendto() process request write() data (reply) recvfrom()

<11> <CDP: Socket Programming> 1.3 Socket 프로그램작성구조 (4/4) Java 언어에서 UDP 소켓프로그램 connectionless protocol Java 에서 DatagramSocket

<12> <CDP: Socket Programming> 2. Socket 생성및 ID 1. Socket 생성 2. Socket Data Structure 3. Socket Address Structure

<13> <CDP: Socket Programming> 2.1 Socket 생성 (1/5) Socket ID ( 소켓번호 ): Socket 생성시리턴되는값 기술자테이블 (descriptor table) 에위치

<14> <CDP: Socket Programming> 2.1 Socket 생성 (2/5)

<15> <CDP: Socket Programming> 2.1 Socket 생성 (3/5) Socket 생성을위한시스템 Call #include <sys/socket.h> Int socket ( int domain, /* 프로토콜체계 */ int type, /* 서비스타입 */ int protocol ); /* 프로토콜 */ socket_id = socket(domain, type, protocol)

<16> <CDP: Socket Programming> 2.1 Socket 생성 (4/5) Domain PF_INET / AF_INET PF_INET6 / AF_INET6 PF_UNIX / AF_UNIX PF : Protocol Family, AF: Address Family Sockaddr / sockaddr_in의구조체 Type SOCK_STREAM SOCK_DGRAM SOCK_RAW Protocol 0( 자동적으로프로토콜이선택되어진다 )

<17> <CDP: Socket Programming> 2.1 Socket 생성 (5/5) open_socket.c 예제 ( 실습 ) int fd1, sd1; fd1 = open( /etc/passwd, O_RDONLY, 0); sd1 = socket(pf_inet, SOCK_STREAM, 0); printf( File Descriptor %d\n, fd1); printf( Socket Descriptor %d\n, sd1); close(fd1); close(sd1); 실행결과 File Descriptor = 3 Socket Descriptor = 4

<18> <CDP: Socket Programming> 2.2 Socket Data Structure (1/5) Socket Program 상에서미디어의송수신시필요한정보 1. 프로토콜 Type (TCP or UDP) 2. 자신의 IP 주소 3. 자신의포트번호 4. 상대방의 IP 주소 5. 상대방의포트번호

<19> <CDP: Socket Programming> 2.2 Socket Data Structure (2/5) 1. Socket 의 Data Structure Socket Program 상에서필요한정보들을유지하기위한자료구조 (Socket 구조체 )

<20> <CDP: Socket Programming> 2.2 Socket Data Structure (3/5) 2. Family - 지원하는프로토콜그룹중에서사용하려는소켓이적용될프로토콜을선택

<21> <CDP: Socket Programming> 2.2 Socket Data Structure (4/5) 3. Type - 연결지향형과비연결지향형 SOCK_STREAM, SOCK_DGRAM - 저수준제어형 IP 프로토콜과같은레벨에있는프로토콜을사용시필요 ex) ICMP (Internet Control Message Protocol) TCP/UDP 보다하위계층으로사용이까다로운반면직접적인제어가가능

<22> <CDP: Socket Programming> 2.2 Socket Data Structure (5/5) 1. Stream Socket - 연결지향형 (TCP 기반 ) - 소켓간의연결후데이터전송 - 일상생활의전화개념과유사 2. Datagram Socket - 비연결형 (UDP 기반 ) - 송수신시도착지주소필수 - 일상생활의편지개념과유사 3. Raw Socket - 저수준프로토콜액세스 - ICMP, OSPF 등이사용 -IP 계층이용 4. Protocol 여러소켓형태를제공하는경우사용, 기본값은 0

<23> <CDP: Socket Programming> 2.3 Socket Address s Data Structure (1/7)

<24> <CDP: Socket Programming> 2.3 Socket Address s Data Structure (2/7) 1. sockaddr 구조체 - 기본적인소켓주소구조체 - 호환성을위해존재 - 변수 : 구조체의크기, Family Type, 소켓의주소데이터 2. sockaddr_in 구조체 - IPv4 소켓주소구조체 - 주소를담기위해 in_addr 구조체사용 - 변수 : 구조체의크기, Family Type, 소켓의주소및포트번호 3. sockaddr_un 구조체 - 유닉스소켓주소구조체 - 동일호스트에서의통신이일반 TCP 통신보다두배빠름 - 변수 : 소켓상수, 호스트경로

<25> <CDP: Socket Programming> 2.3 Socket Address s Data Structure (3/7) struct sockaddr { u_short sa_family; /* address family */ char sa_data[14]; /* 주소 */ } struct in_addr { u_long s_addr; /* 32bit IP 주소 */ } struct sockaddr_in { short sin_family; /* 주소체계 */ u_short sin_port; /* 16bit 포트번호 */ struct in_addr sin_addr; /* 32bit IP 주소 */ char sin_zero[8]; /* dummy */ }

<26> <CDP: Socket Programming> 2.3 Socket Address s Data Structure (4/7) sockaddr_in 구조체를사용 sockaddr 과의호환성을위해 dummy 삽입 sin_family AF_INET AF_UNIX AF_NS 인터넷주소체계 유닉스파일주소체계 XEROX 주소체계

<27> <CDP: Socket Programming> 2.3 Socket Address s Data Structure (5/7) o 많은 BSD network system call 은독립변수로서 socket address 구조의지시자를필요로한다. - 이구조의정의는 <sys/socket.h> 에있다. struct sockaddr { u_short sa_family; /* address family: AF_xxx value */ char sa_data[14]; /* up to 14 bytes of protocol-specific address */ }; o 14 byte 의 protocol-specific address 의내용은 address 의 type 에따라서해석 o Internet family 에대하여다음구조가 <netinet/in.h> 에정의 struct in_addr { u_short s_addr; /* 32-bit netid/hostid */ }; struct sockaddr_in { short sin_family; /* AF_INET */ u_short sin_port; /* 16-bit port number */ /* network byte ordered */ struct in_addr sin_addr; /* 32-bit netid/hostid */ /* netowrk byte ordered */ char sin_zero[8]; /* unused */ };

<28> <CDP: Socket Programming> 2.3 Socket Address s Data Structure (6/7) o <sys/types.h> 에정의된 unsigned data type C Data type 4.3 BSD System V unsigned char unsigned short unsigned int unsigned long u_char u_short u_int u_long unchar ushort uint ulong o Internet, XNS, Unix family 에대한 socket address 구조 struct sockaddr_in family 2-byte port 4-byte net ID, host ID (unused) struct sockaddr_ns family 4-byte net ID 6-byte host ID 2-byte port (unused) struct sockaddr_un family pathname (up to 108 bytes)

<29> <CDP: Socket Programming> 2.3 Socket Address s Data Structure (7/7) Socket Address 구조체의사용실예 : /* 서버소켓생성 */ server_socket = socket(af_inet, SOCK_STREAM, 0); /* 서버주소및포트설정 */ server_addr.sin_family = AF_INET; server_addr.sin_port = htons(server_port); server_addr.sin_addr.s_addr = htonl(inaddr_any); memset(&(server_addr.sin_zero), 0, 8); /* Client 소켓생성 */ connect_fd = socket(af_inet, SOCK_STREAM, 0); /* 사용자의서버 IP 및포트에대한입력을받아서 sockaddr_in 구조체를구성 */ connect_addr.sin_family = AF_INET; connect_addr.sin_port = htons(atoi(argv[2])); connect_addr.sin_addr.s_addr = inet_addr(argv[1]); memset(&(connect_addr.sin_zero), 0, 8); 실습 : /Soc/Sim_Soc/*.c : Server 와 Client 의단방향접속기능

<30> <CDP: Socket Programming> 3. 네트워크프로그래밍을위한함수 1. 시스템호출함수의개요 2. 소켓관련함수 3. 소켓옵션관련함수 4. 동시처리를위한함수

<31> <CDP: Socket Programming> 3.1 시스템호출함수의개요 - 시스템콜이란개발의편의를위해운영체제의고유기능을호출하는것 - 동작매커니즘 1. 필요에의해시스템함수호출 2. 제어권한이동 ( 어플리케이션 > 시스템호출인터페이스 > 운영체제 ) 3. 운영체제내부모듈이호출에대한처리를진행 4. 제어권한이동 ( 운영체제 > 시스템호출인터페이스 > 어플리케이션 )

<32> <CDP: Socket Programming> 3.2 소켓관련함수 (1/10) 1. 소켓함수를이용한클라이언트 / 서버의구조

<33> <CDP: Socket Programming> 3.2 소켓관련함수 (2/10) o socket system call - 원하는통신 protocol(internet TCP, Internet UDP, XNS SPP 등 ) 의 type 을지정 o Syntax int socket (int family, int type, int protocol); #include <sys/types.h> #include <sys/socket.h> o socket system call 1. 네트워크통신을위해사용될새로운소켓생성 2. 파일기술자테이블에새로생성된소켓의인덱스를파일기술자번호로변환 return value : sock 지정번호, sockfd 3. 입력인자 family : 프로토콜의부류입력 AF_UNIX UNIX internal protocols AF_INET Internet protocols AF_NS Xerox NS protocols AF_IMPLINK IMP link layer type : 소켓과함께사용할통신형태입력 protocol : TCP/UDP/RAW 입력, 일반적으로 0 int socket (int family, int type, int protocol); o socket type -SOCK_STREAM -SOCK_DGRAM -SOCK_RAW -SOCK_SEQPACKET -SOCK_RDM stream socket datagram socket raw socket sequenced packet socket reliably delivered message socket (not implemented yet)

<34> <CDP: Socket Programming> 3.2 소켓관련함수 (3/10) o socket family와 type에대응하는 protocol AF_UNIX AF_INET AF_NS SOCK_STREAM Yes TCP SPP SOCK_DGRAM Yes UDP IDP SOCK_RAW IP Yes SOCK_SEQPACKET SPP o family, type 그리고 protocol 간의조합 family type protocol Actual protocol AF_INET AF_INET AF_INET AF_INET SOCK_DGRAM SOCK_STREAM SOCK_RAW SOCK_RAW IPPROTO_UDP IPPROTO_TCP IPPROTO_ICMP IPPROTO_RAW UDP TCP ICMP (raw) AF_NS AF_NS AF_NS AF_NS SOCK_STREAM SOCK_SEQPACKET SOCK_RAW SOCK_RAW NSPROTO_SPP NSPROTO_SPP NSPROTO_ERROR NSPROTO_RAW SPP SPP Error protocol (raw) IPPROTO_xxx - <netinet/in.h> NSPROTO_xxx - <netns/ns.h>

<35> <CDP: Socket Programming> o socket system calls 과연계요소들 3.2 소켓관련함수 (4/10) connection-oriented server connection-oriented client protocol local-addr, local-process foreign-addr, foreign-process socket() bind() listen(), accept() socket() connect() connectionless server scoket() bind() recvfrom() connectionless client socket() bind() sendto()

<36> <CDP: Socket Programming> 3.2 소켓관련함수 (5/10) o o bind system call - 이름없는 socket 에이름을부여 - 로컬인터페이스어드레스와포트번호를소켓과서로연관되게묶는함수입니다 Syntax int bind (int sockfd, struct sockaddr * myaddr, int addrlen); #include <sys/types.h> #include <sys/socket.h> int bind (int sockfd, struct sockaddr *myaddr, int addrlen); o bind 의용도 1. 서버측에서처음생성된소켓이어떤주소값도갖고있지않음 2. server 는주지된주소를시스템에기록한다. 소켓에지역주소및포트 (Well-Known Port) 를할당하여활성화 3. 입력인자 sockfd : socket() 함수호출로얻은소켓의기술자입력 myaddr : 로컬 IP 및포트에대한정보가담긴 sockaddr_in 주소입력 addrlen : sockaddr_in 의크기입력 4. client는자신을위한특정주소를기록할수있다. 5. connectionless client는시스템이자신에게유일한주소를부여하였음을확인할필요가있으며, 이로써상대측 server가응답을보낼유효한반송주소를갖게되는것이다.

<37> <CDP: Socket Programming> 3.2 소켓관련함수 (6/10) o listen system call - connection을받아들이겠다는의지를나타내기위하여 connection-oriented server가사용 - socket과 bind system call 후와 accept system call전에수행 o Syntax - intlisten (int sockfd, int backlog); #include <sys/types.h> #include <sys/socket.h> int listen (int sockfd, int backlog); 1. 서버측의접속대기큐의최대연결가능수설정 2. 입력인자 1. sockfd : socket() 함수호출로획득한소켓의소켓기술자입력 2. backlog : 접속대기큐의최대연결가능수를지정 (TCP 서버에서만사용 )

<38> <CDP: Socket Programming> 3.2 소켓관련함수 (7/10) o o accept system call - connection-oriented server 가 listen system call 을수행한후, server 가 accept system call 을수행함으로써어떤 client process 로부터실제적 connection 을기다린다. Syntax int accept (int sockfd, struct sockaddr * cliaddr, socklen_t * addrlen); #include <sys/types.h> #include <sys/socket.h> int accept (int sockfd, struct sockaddr *peer, int *addrlen); 1. TCP 서버에서호출되고연결이완료된큐의최초에위치한데이터반환 2. 큐가비어있는상태에는클라이언트의접속이이루어질때까지블록됨 3. 정상적으로함수가종료되면새로연결된파일기술자를반환 4. 입력인자 sockfd : listen() 함수호출로설정한소켓의소켓기술자입력 cliaddr : 클라이언트의 IP 주소와로컬포트정도를설정한구조체입력 addrlen : sockaddr 구조체의크기입력

<39> <CDP: Socket Programming> 3.2 소켓관련함수 (8/10) o o connect system call - local system 과외부 system 사이의실제적인 connection 을설정 Syntax int connect (int sockfd, const struct sockaddr * servaddr, socklen_t addrlen); #include <sys/types.h> #include <sys/socket.h> int connect (int sockfd, struct sockaddr *servaddr, int addrlen); 1. 클라이언트에서서버로의연결을담당 2. 소켓기술자와상대서버에대한주소정보를바탕으로서버로접속시도 3. 클라이언트에서 connect() 호출전에 bind() 를호출하지않았다고해도임의의포트와로컬 IP 를자동으로설정하여함수호출 4. 3-way handshaking 으로서버와연결을설정함 5. 입력인자 sockfd : socket() 함수호출로저장된소켓의소켓기술자입력 servaddr : 접속할서버의주소와포트에관한정보를담은구조체입력 addrlen : sockaddr 구조체의크기입력

<40> <CDP: Socket Programming> 3.2 소켓관련함수 (9/10) read / write / recv / send 1. ssize_t read (int sockfd, void * buffer, size_t len); - 원하는소켓 (sockfd) 에서특정길이 (len) 만큼을사용자버퍼 (buffer) 로읽어들임 2. ssize_t write (int sockfd, void * buffer, size_t len); - 원하는소켓 (sockfd) 에서특정길이 (len) 만큼을사용자버퍼 (buffer) 로보냄 3. ssize_t recv (int sockfd, void * buffer, size_t len, int flags); - read 함수와동일하나 flags 변수의값에따라데이터수신방법이다름 - flags 옵션 MSG_PEEK : 네트워크버퍼에서데이터제거를하지않고버퍼에복사만 함 MSG_OOB : 긴급메시지전달에사용하며 TCP 헤더의 URG bit을 1로변경 MSG_WAITALL : 완전한양의데이터를수신할때만 recv 호출에서복귀 4. ssize_t send (int sockfd, void * buffer, size_t len, int flags); - Write 함수와동일하나 flags 변수의값에따라데이터송신방법이다름 - flags 옵션 MSG_OOB : OOB Data 송신 MSG_DONTROUTE : 데이터를라우팅하지않는다. 즉라우팅조건을무시

<41> <CDP: Socket Programming> int shutdown (int sockfd, int howto); - TCP 연결에대한종료를담당하고옵션에따라종료방법조절가능 - close() 함수와다르게별다른작업없이바로종료시킨다는차이 - howto 인자에따른옵션 SHUT_RD : Read 불가, Write 가능 SHUT_WR : Read 가능, Write 불가 SHUT RDWR : Read / Write 모두불가 3.2 소켓관련함수 (10/10) sendto / recvfrom ssize_t recvfrom (int sockfd, void * message, size_t len, int flags, struct sockaddr * send_addr, size_t * add_len); ssize_t sendto (int sockfd, void * message, size_t len, int flags, const struct sockaddr * dest_addr, size_t dest_len); - 두함수도데이터송수신을담당하지만 recvfrom( 수신 ) 과 sendto( 송신 ) 함수는 UDP 통신에서사용 - recv/send와의차이점은목적지에대한정보가추가된다는것으로이는 UDP의특징인비연결성을생각하면송수신에반드시필요한정보임을알수있음 close / shutdown int close (int sockfd); - 소켓종료후에는이전에연결된상대방에게데이터송신불가 - 대기열의데이터에대해서해당데이터수신작업완료후소켓종료

<42> <CDP: Socket Programming> 3.3 소켓옵션관련함수 (1/2) intgetsockopt (int sockfd, int level, int optname, void * optval, socklen_t * optlen); - 소켓 (sockfd) 의지정된옵션 (optname) 의값 (optval) 과바이트수 (optlen) 을반환 intsetsockopt (int sockfd, int level, int optname, void * optval, socklen_t optlen); - 소켓 (sockfd) 에옵션 (optname) 을지정하고그에따른값 (optval) 과바이트수 (optlen) 을설정 소켓및프로토콜종류와그에따른옵션, 데이터값으로구성 level : 소켓및프로토콜의종류 (IP, ICMP, IPv6, TCP 등 ) optname : 세부옵션 optval : 선택한옵션에대한데이터값 optlen : optval 의크기입력

<43> <CDP: Socket Programming> 3.3 소켓옵션관련함수 (2/2) 2. 옵션의주요내용

<44> <CDP: Socket Programming> 1. signal() 함수 3.4 동시처리를위한함수 (1/9) i) 시스템에정의된이벤트발생시사용자가정의한처리를하는함 ii) 형태 - void (*signal)(int sig, void (*func)(int))(int); iii) 인자 - func : 시그널이전달될때호출되는함수의주소값입력 - sig : 처리하거나무시할시그널을설정 ( 요약 )

<45> <CDP: Socket Programming> 3.4 동시처리를위한함수 (2/9) signal() 사용방법 유닉스에서어떤이벤트 (event) 가발생하면이것을프로세스에게알리는수단으로사용 #include <signal.h> main() {. signal(sigint, sigint_func); /* 시그널처리함수지정 */. } int sigint_func() { } /* SIGINT 시그널발생시처리내용 */

<46> <CDP: Socket Programming> 3.4 동시처리를위한함수 (3/9) 2. fork() 함수 i) 새로운프로세스를생성하고복제된프로세스는현재프로세스 ii) 와같은속성과코드를소유부모프로세스는자식프로세스에대한개수에대한제한이있으므로에러발생에대한제어필요 iii) 형태 pid_t fork (void); iv) 동작 v) 특징 코드, 스택,, 파일기술자, 소켓번호등을공유 PID 와변수는공유하지않음

<47> <CDP: Socket Programming> 3.4 동시처리를위한함수 (4/9) 3. select () 함수 i) 파일기술자의상태변화감지후해당상태에대한처리 ii) 상태변화는읽기 / 쓰기 / 예외처리의 3 가지 iii) 형태 -int select ( int n, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, const struct timeval * timeout); iv) 입력인자 - n : 상태를살펴볼최대기술자크기 - timeout : 상태를살펴볼주기설정 (0 인경우무한반복 ) - readfds / writefds / exceptfds : 읽기 / 쓰기 / 예외처리관련기술자 v) 상태기술자관리를위한매크로들

<48> <CDP: Socket Programming> select() 시스템콜 3.4 동시처리를위한함수 (5/9) int select ( int maxfdp1, /* 최대소켓번호크기 + 1 */ fd_set *readfds, /* 읽기변화를감지할소켓번호 */ fd_set *writefds, /* 쓰기변화를감지할소켓번호 */ fd_set *exceptfds, /* 예외변화를감지할소켓번호 */ struct timeval *tvptr); /* select 시스템콜이기다리는시간 */

<49> <CDP: Socket Programming> 3.4 동시처리를위한함수 (6/9) select() 시스템콜 (Cont d) 매크로 FD_ZERO(fd_set *fdset) fdset 의모든비트를지운다 FD_SET(int fd, fd_set *fdset) fdset 중소켓 fd 에해당하는비트를 1 로한다 FD_CLR(int fd, fd_set *fdset) fdset 중소켓 fd 에해당하는비트를 0 으로한다 FD_ISSET(int fd, fd_set *fdset) fdset 중소켓 fd 에해당하는비트가세트되어있으면양수값을리턴

<50> <CDP: Socket Programming> 3.4 동시처리를위한함수 (7/9) Select 를이용한예

<51> <CDP: Socket Programming> 4. poll() 함수 3.4 동시처리를위한함수 (8/9) i) select 함수와같은기술자관리방식 ii) select 에비하여관리할기술자를선택할수있 iii) select 함수보다빠른응답속도를보이나사용이불편한단점 iv) 형태 - Int poll (struct pollfd *ufds, unsigned int nfds, int timeout); v) 입력인자

<52> <CDP: Socket Programming> 3.4 동시처리를위한함수 (9/9) 5. Thread i) 스레드는프로세스와는다르게메모리공유가능 ii) 메모리공유로인하여동기화문제발생 ( 관련도서참고 ) iii) 사용함수 Int pthread_create (pthread_t * thread, pthread_attr_t * attr, void * (* start_routine)(void *), void * arg); void pthread_join (pthread_t th, void ** thread_return); fork 에서자식프로세스를기다리는 wait 함수와같은기능 void pthread_exit (void *retval); 스레드를종료시킬때호출

<53> <CDP: Socket Programming> Socket System call( 예제 ) o concurrent server 로가정할경우의전형적인시나리오 int sockfd, newsockfd; if ( (sockfd = socket(...)) < 0) err_sys("socket error"); if (bind(sockfd,...) < 0) err_sys("bind error"); if (listen(sockfd, 5) < <0) err_sys("listen error"); for ( ; ; ) { newsockfd = accept(sockfd,...); /* blocks */ if (newsockfd < 0) err_sys("accept error"); if (fork() == 0) { close(sockfd); /* child */ doit(newsockfd); /* process the request */ exit(0); } } close(newsockfd); /* parent */

<54> <CDP: Socket Programming> Socket System call( 예제 ) o iterative server 로가정할경우의전형적인시나리오 int sockfd, newsockfd; if ( (sockfd = soket(...)) < 0) err_sys("socket error"); if (bind(sockfd,...) < 0) err_sys("bind error"); if (listen(sockfd, 5) < <0) err_sys("listen error"); for ( ; ; ) { newsockfd = accept(sockfd,...); /* blocks */ if (newsockfd < 0) err_sys("accept error"); } doit(newsockfd); /* process the request */ close(newsockfd);

<55> <CDP: Socket Programming> 4. Socket 프로그래밍을위한유틸리티함수들 1. 바이트순서변환함수 2. 주소변환구조체 3. 인터넷주소변환함수 4. 원격지호스트정보를얻는함수

<56> <CDP: Socket Programming> 4.1 바이트순서변환함수 (1/3) 호스트바이트순서 CPU 에따라메모리에저장하는순서가틀림 네트워크바이트순서 CPU 에관계없이 High-order 순서로전송 Internet protocol 을위하여설계 htonl(), htons(), ntohl(), ntohs() htonl convert host-to-network, long integer htons convert host-to-network, short integer ntohl convert network-to-host, long integer ntohs convert network-to-host, short integer #include <sys/types.h> #include <netinet/in.h> u_long u_short u_long u_short htol(u_long hostlong); htons(u_short hostshort); ntohl(u_long netlong); ntohs(u_short netshort);

<57> <CDP: Socket Programming> 4.1 바이트순서변환함수 (2/3) 바이트순서 ( 예 ) Big-Endian Little-Endian - 데이터의최상위바이트의내용을저장될메모리의시작주소에저장 - 모토로라마이크로프로세서및 IBM 메인프레임기반 - 데이터의최하위바이트의내용을저장될메모리의시작주소에저장 - DEC VAX 컴퓨터및인텔마이크로프로세서

<58> <CDP: Socket Programming> 4.1 바이트순서변환함수 (3/3) byte_order.c 예제 pmyservent = getservbyname("echo", "udp"); printf("port number of 'echo', 'udp' without ntohs() : %d \n", pmyservent->s_port); printf("port number of 'echo', 'udp' with ntohs() : %d \n", ntohs(pmyservent->s_port)); 실행결과 (x86 Linux System) Port number of 'echo', 'udp' without ntohs() : 1792 Port number of 'echo', 'udp' with ntohs() : 7 실행결과 (mc68000 계열 ) Port number of 'echo', 'udp' without ntohs() : 7 Port number of 'echo', 'udp' with ntohs() : 7

<59> <CDP: Socket Programming> 4.2 주소변환구조체 (1/5) - 기본적인 IP 주소체계를도메인주소로변환시사용 A. hostent 구조체 - gethostbyaddr(), gethostbyname() 함수에사용 - 변수 : 호스트의공식명칭, 별칭, 호스트주소의종류, 주소체계의바이트수, 도메인에포함된 IP list B. servent 구조체 - getservbyname(), getservbyport() 함수에사용 - 변수 : 서버의공식명칭, 별칭, 서버가제공하는포트번호, 서버가사용하는프로토콜타입의문자열

<60> <CDP: Socket Programming> 4.2 주소변환구조체 (2/5) * 원격지호스트정보를위한구조체 : hostent 구조체

<61> <CDP: Socket Programming> 4.2 주소변환구조체 (3/5) hostent 구조체정의 struct hostent { char *h_name; /* 호스트이름 */ char **h_aliases; /* 호스트별명들 */ int h_addrtype; /* 호스트주소의종류 */ int h_length; /* 주소의크기 */ char **h_addr_list; /* IP 주소리스트 */ }; #define h_addr haddr_list[0] /* 첫번째주소 */

<62> <CDP: Socket Programming> 4.2 주소변환구조체 (4/5) * 원격지호스트정보를위한구조체 : servtent 구조체

<63> <CDP: Socket Programming> getservbyname() 4.2 주소변환구조체 (5/5) 시스템이현재지원하는 TCP/IP 응용프로그램의정보를알아내는함수로, 서비스이름과프로토콜을인자로주어호출하면서비스관련각종정보를포함하고있는 servent 라는구조체의포인터를리턴한다. pmyservent = getservbyname("echo", "udp"); servent 구조체의정의 (netdb.h 파일참조 ). struct servent { char *s_name; /* 서비스이름 */ char **s_aliases; /* 별명목록 */ int s_port; /* 포트번호 */ char *s_proto; /* 사용하는프로토콜 */ }; servent 구조체는네트워크로부터얻은정보이므로그내용이네트워크바이트순서로되어있고이를화면에출력해보려면호스트바이트순서로바꾸어야한다.

<64> <CDP: Socket Programming> 4.3 인터넷주소 (IP 주소 ) 변환 (1/4) 인터넷주소를표현하는방식 도메인네임 32bit IP 주소 십진수표시법 (dotted decimal) IP 주소변환함수예 mm.sookmyung.ac.kr : : 203.252.201.16 Domain Name : IP 주소 (binary) : dotted decimal gethostbyname() inet_ntoa() gethostbyaddr() inet_addr()

<65> <CDP: Socket Programming> 4.3 인터넷주소 (IP 주소 ) 변환 (2/4) 주소변환함수 (Address Conversion Routines) unsigned long int inet_addr (const char * strptr); - Dotted Decimal' 문자열형태의주소를네트워크바이트순서를 갖는이진바이너리로바꾸는함 수 - 점으로분리된십진수개념의문자열을 32-비트 Internet 주소로변환 - 입력값이적절치못할경우 INADDR_NONE('-1') 을반환 - -1 은 Dotted Decimal 로표현시 255.255.255.255 이므로유효성검사가반드시필요 int inet_aton (const char * strptr, struct in_addr * addrptr); - 'Dotted Decimal' 형태의문자열을바이너리형태로바꾸는함수 - strptr 로들어온 Dotted Decimal' 형태의문자열은변환되어 'in_addr' 타입의 addrptr 에저장됨 - 주소가올바르다면 0 이아닌값, 그렇지않다면 0 을반환 char * inet_ntoa (struct in_addr inaddr); - 'in_addr' 형의바이너리주소 inaddr 을 Dotted Decimal' 형태의문자열로변경 - 반환되는문자열은정적으로할당된버퍼에저장 - 함수의연속적인호출은버퍼를중복하여덮어쓰므로주의 inet_addr > inet_ntoa : 역변환 #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> unsigned long inet_addr(char *ptr); char *inet_ntoa(struct in_addr inaddr);

<66> <CDP: Socket Programming> 4.3 인터넷주소 (IP 주소 ) 변환 (3/4) IP 주소변환 : ascii_ip.c 예제 struct in_addr host_ip; haddr = argv[1]; /* dotted decimal 주소 */ host_ip.s_addr = inet_addr(haddr); /* IP 주소 (hexa 4byte) 출력 */ printf( IP Address (hexa) 0x%x\n, host_ip.s_addr); /* dotted decimal 로다시변환하여출력 */ printf( %s\n, inet_ntoa(host_ip));

<67> <CDP: Socket Programming> 4.3 인터넷주소 (IP 주소 ) 변환 (4/4) get_hostent.c 예제 struct in_addr host_ip; haddr = argv[1]; /* dotted decimal 주소 */ host_ip.s_addr = inet_addr(haddr); /* IP 주소 (hexa 4byte) 출력 */ printf( IP Address (hexa) 0x%x\n, host_ip.s_addr); /* dotted decimal 로다시변환하여출력 */ printf( %s\n, inet_ntoa(host_ip)); get_hostent.c 실행결과 #> get_hostent mm.sookmyung.ac.kr official host name : mm.sookmyung.ac.kr host address type : 2 length of host address : 4 IP address : 203.252.201.16 dotted decimal => 도메인네임 gethostbyaddr() 이용

<68> <CDP: Socket Programming> 4.4 원격지호스트정보를얻는함수 (1/2) 1. struct hostent * gethostbyname (const char * hostname); - 전달값으로호스트의이름 ( 도메인 ) 을받아서 hostent 구조체에결과값을돌려주는함수 2. struct hostent * gethostbyaddr (const char * addr, size_t len, int family); - 호스트의 IP 주소 ( 바이너리형태의주소 ) 를이용하여해당호스트에대한정보를저장 - addr 은호스트 IP 주소이고 len 은 IP 주소의크기 (IPv4 = 4, IPv6 = 16) 3. int gethostname (char * name, size_t namelen); - 현재의호스트이름을반환 - 전달인자 name 은호스트의이름을저장할곳의주소 - namelen 은 name 의바이트길이 - 성공한경우반환값 0, 실패인경우반환값 -1

<69> <CDP: Socket Programming> 4.4 원격지호스트정보를얻는함수 (2/2) 4. struct servent * getservbyname (const char * servname, const char * protoname); - 해당호스트에서진행되고있는서비스에대한각정보를서비스에대한이름과해당프로토콜로얻을수있게해주는함수 - 수행중에러발생시에는결과값으로 NULL 반환 5. struct servent * getservbyport (int port, const char * protoname); - 해당호스트에서진행되고있는서비스에대한각정보를포트번호로얻을수있게해주는함수 - 수행중에러발생시에는결과값으로 NULL 반환

<70> <CDP: Socket Programming> 5. 클라이언트 / 서버의작성방법 1. 작성절차 2. 연결형클라이언트 / 서버의작성 3. 비연결형클라이언트 / 서버의작성

<71> <CDP: Socket Programming> 5.1 작성절차 : 서버프로그램 서버프로그램이먼저수행되고있어야한다. 서버는 socket() 을호출하여통신에사용할소켓을개설한다. 소켓번호와자신의소켓주소를 bind() 로서로연결한다. 소켓주소 ( 자신의 IP 주소자신의포트번호 ) 소켓번호는응용프로그램이알고있는통신창구번호이고, 소켓주소는네트워크시스템 ( 즉, TCP/IP) 이알고있는주소이므로이들의관계를묶어두어야한다. listen() 을호출하여클라이언트로부터의연결요청을기다리는수동대기모드로들어간다. 클라이언트로부터연결요청이왔을때이를처리하기위하여 accept() 를호출한다. 클라이언트가 connect() 를호출하여연결요청을해오면이를처리한다. 메시지를송수신한다.

<72> <CDP: Socket Programming> 5.1 작성절차 : 클라이언트프로그램 socket() 을호출하여소켓을만든다. 서버에게연결요청을보내기위하여 connect() 를호출한다. 이때서버의소켓주소 (4+5) 구조체를만들어인자로준다. 소켓주소 ( 상대방의 IP 주소상대방의포트번호 ) 상대방 == 서버의 IP 주소및포트번호 대부분의클라이언트는 bind() 를사용하여포트번호를특정한값으로지정할필요가없다 ( 클라이언트는보통시스템이자동으로배정하는포트번호를사용한다 ). connect() 를호출하여연결요청을한다. 메시지를송수신한다.

<73> <CDP: Socket Programming> 5.1 작성절차 소켓의동작모드 blocking 모드 함수를호출했을경우동작완료때까지멈춤 listen(), connect(), accept(), read(), write() 등 non-blocking 모드 시스템콜호출후바로값이리턴 계속루프 (loop) 를돌면서확인 ( 폴링 ) 비동기 (asynchronous) 모드 IO 변화를감지 select() 함수를사용

<74> <CDP: Socket Programming> 5.1 작성절차 1. 서버유형의결정 i) 클라이언트접속빈도 - 얼마만큼의클라이언트가어느정도의빈도로접속하는지에따름 ii) 필요한규모와처리량 - 주고받는데이터의크기가어느정도이며필요한대역폭에따름 iii) 데이터의안정성 - 클라이언트간혹은서버와클라이언트간의데이터신뢰도 - 요즘의네트워크망은설비가잘되어있어안정성에대한문제는줄어듬 2. 기본적인서버의유형 서버타입 선택사항 클라이언트의요청에대한처리방식 동시처리형 단순형 서버로의접근방식 연결형 (TCP) 비연결형 (UDP)

<75> <CDP: Socket Programming> 5.1 작성절차 - 연결형클라이언트 socket() 호출시소켓번호와소켓인터페이스의관계

<76> <CDP: Socket Programming> 5.1 작성절차 - 연결형 Server Iterative 모델의 TCP 서버프로그램작성절차

<77> <CDP: Socket Programming> 5.1 작성절차 - 비연결형클라이언트 SOCK_DGRAM 으로소켓생성 connect() 없이바로메시지송수신 각패킷마다 IP 주소와포트번호를입력 sendto(int s, char* buf, int length, int flag, sockaddr* to, int tolen) recvfrom(int s, char* buf, int length, int flags, sockaddr* from, int fromlen)

<78> <CDP: Socket Programming> 5.1 작성절차 - 포트번호배정 클라이언트포트번호배정시기 TCP 소켓의경우 connect() 호출이후에 UDP 소켓의경우 sendto() 호출이후에 getsockname() 을이용확인 getsockname(s, (struct sockaddr *)&clinet_addr, &addr_len); port = clinet_addr.sin_port; printf( client port number : %d\n, port);

<79> <CDP: Socket Programming> 5.2 연결형클라이언트 / 서버의작성 1. 단순연결형클라이언트 / 서버 1) 서버와클라이언트의소켓생성 2) 서버는 BIND 작업후대기큐설정 (LISTEN) 3) 서버는클라이언트의접속대기 (ACCEPT) 4) 클라이언트가서버로접속시도 (CONNECT) 5) 접속이완료되면서버와클라이언트간의데이터송수신작업 6) 서버종료작업 7) 서버와클라이언트소켓닫음 (CLOSE)

<80> <CDP: Socket Programming> ( 예 ) 단순연결형서버 socket 생성및수행 /* 서버소켓생성 */ server_socket = socket(af_inet, SOCK_STREAM, 0); /* 서버주소및포트설정 */ server_addr.sin_family = AF_INET; server_addr.sin_port = htons(server_port); server_addr.sin_addr.s_addr = htonl(inaddr_any); memset(&(server_addr.sin_zero), 0, 8); /* 해당주소및포트로바인딩작업 */ bind(server_socket, (struct sockaddr*)&server_addr, sizeof(struct sockaddr)); /* 클라이언트의대기열수설정 */ listen(server_socket, 10); client_socket = accept(server_socket, (struct sockaddr*)&server_addr, &addrsize); msgsize = read(client_socket, BUFF, sizeof(buff)); if (msgsize <= 0) { printf( message receive error\n ); continue; } write(client_socket, BUFF, strlen(buff) );

<81> <CDP: Socket Programming> ( 예 ) 단순 Client socket 생성및수행 /* 소켓생성 TCP 이므로 SOCK_STREAM*/ connect_fd = socket(af_inet, SOCK_STREAM, 0); /* 사용자의서버 IP 및포트에대한입력을받아서 sockaddr_in 구조체를구성 */ connect_addr.sin_family = AF_INET; connect_addr.sin_port = htons(atoi(argv[2])); connect_addr.sin_addr.s_addr = inet_addr(argv[1]); memset(&(connect_addr.sin_zero), 0, 8); /* 서버로의소켓접속 */ connect(connect_fd, (struct sockaddr*)&connect_addr, sizeof(connect_addr)); msgsize = read(connect_fd, msg, sizeof(msg)); if (msgsize <= 0) continue; printf("server Message>>%s", msg); memset(msg, '\0', sizeof(msg)); fgets(msg, 1024, stdin); msgsize = strlen(msg); write(connect_fd, msg, msgsize);

<82> <CDP: Socket Programming> 5.2 연결형클라이언트 / 서버의작성 2. 다중연결연결형클라이언트 / 서버 1) 서버와클라이언트의통신초기화 (SELECT 관련 ) 2) 서버와클라이언트소켓의생성 3) 서버는 BIND 작업후대기큐설정 (LISTEN) 4) 서버는클라이언트의접속대기 (ACCEPT) 5) 클라이언트가서버로접속시도 (CONNECT) 6) 서버측의기술자에이벤트가발생 7) 접속처리후클라이언트와데이터송수신 8) 서버종료작업 9) 서버와클라이언트소켓닫음 (CLOSE)

<83> <CDP: Socket Programming> ( 예 ) 다중연결형서버 socket 생성및수행 /* 서버소켓생성 */ server_socket = Socket(AF_INET, SOCK_STREAM, 0); /* 서버주소및포트설정 */.. /* 해당주소및포트로바인딩작업 */ Bind(server_socket, (struct sockaddr*)&server_addr, sizeof(struct sockaddr)); /* 클라이언트의대기열수설정 */ Listen(server_socket, 10); /*fd_set 데이타필드초기화 */ FD_ZERO(&readfd); maxfd = server_socket; client_index = 0; while(1) { /*fd_set 를해당소켓기술자로설정 */ FD_SET(server_socket, &readfd); /* 접속된클라이언트의소켓기술자를 fd_set 에설정 */ for (start_index = 0; start_index < client_index; start_index++) { FD_SET(client_fd[start_index], &readfd); if (client_fd[start_index] > maxfd) maxfd = client_fd[start_index]; } maxfd = maxfd + 1; return 0; 다음페이지계속

<84> <CDP: Socket Programming> select(maxfd, &readfd, NULL, NULL,NULL); /* 해당소켓기술자에변화가생겼는지검사 */ if (FD_ISSET(server_socket, &readfd)) { addrsize = sizeof(struct sockaddr_in); client_socket = Accept(server_socket, (struct sockaddr*)&server_addr, &addrsize); FD_SET(client_socket, &readfd); client_fd[client_index] = client_socket; client_index++; if (client_index == 5) break; } /* 해당소켓기술자에변화가생겼는지검사서버에접속된모든클라이언트의소켓기술자검사 */ for (start_index = 0; start_index < client_index; start_index++) { if (FD_ISSET(client_fd[start_index], &readfd)) { msgsize = read(client_fd[start_index], BUFF, sizeof(buff)); if (msgsize <= 0) continue; printf("client Message>>%s", BUFF); msgsize = strlen(buff); write(client_fd[start_index], BUFF, msgsize); } }

<85> <CDP: Socket Programming> ( 예 ) 다중 Client socket 생성및수행 /* 서버로의소켓접속 */ Connect(connect_fd, (struct sockaddr*)&connect_addr, sizeof(connect_addr)); /*fd_set 데이타필드초기화 */ FD_ZERO(&readfd); while(1) { } /*fd_set 를해당소켓기술자로설정 */ FD_SET(0, &readfd); FD_SET(connect_fd, &readfd); select (connect_fd+1, &readfd, NULL, NULL, NULL); /* 해당소켓기술자에변화가생겼는지검사 */ if (FD_ISSET(connect_fd, &readfd)) { msgsize = read(connect_fd, msg, sizeof(msg)); if (msgsize <= 0) continue; printf("server Message>>%s", msg); } /* 해당입력기술자에변화가생겼는지검사 */ if (FD_ISSET(0, &readfd)) { memset(msg, '\0', sizeof(msg)); fgets(msg, 1024, stdin); msgsize = strlen(msg); write(connect_fd, msg, msgsize); }

<86> <CDP: Socket Programming> 5.3 비연결형클라이언트 / 서버의작성 1. 단순비연결형클라이언트 / 서버 1) 서버와클라이언트의소켓생성 2) 서버는 BIND 작업후대기 3) 서버와클라이언트간의데이터송수신 4) 서버는단순히클라이언트로데이터전송 5) 서버종료작업 6) 서버소켓닫음 6) 클라이언트소켓닫음 * 양쪽모두상대방의주소를알고있어야지속적인데이터송수신이가능함을기억

<87> <CDP: Socket Programming> ( 예 ) 단순비연결형서버 /*1. 서버소켓생성 */ server_socket = Socket(AF_INET, SOCK_DGRAM, 0); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(server_port); server_addr.sin_addr.s_addr = htonl(inaddr_any); memset(&(server_addr.sin_zero), 0, 8); bind(server_socket, (struct sockaddr*)&server_addr, sizeof(struct sockaddr)); addrsize = sizeof(struct sockaddr_in); while(1) { memset(buff, '\0', sizeof(buff)); msgsize = recvfrom(server_socket, BUFF, sizeof(buff), 0, (struct sockaddr*)&client_addr, &addrsize); if (msgsize <= 0) continue; } printf("client Message>>%s", BUFF); msgsize = strlen(buff); sendto(server_socket, BUFF, msgsize, 0, (struct sockaddr*)&client_addr, addrsize);

<88> <CDP: Socket Programming> ( 예 ) 단순비연결형클라이언트 memset(msg, '\0', sizeof(msg)); fgets(msg, 1024, stdin); msgsize = strlen(msg); /* 사용자입력데이타에대한처리. 서버전송 * sendto 함수이용 */ msgsize = sendto(connect_fd, msg, msgsize, 0, (struct sockaddr*)&connect_addr, addrsize); printf("message Send>>%s", msg); memset(temp_buff, '\0', sizeof(temp_buff)); /* 서버에서의송신데이타에대한처리 recvfrom함수이용 */ recvfrom((int)sockfd, temp_buff, sizeof(temp_buff), 0, (struct sockaddr*)&server_addr, &temp_addrsize); printf("message Receive>>%s", temp_buff);

<89> <CDP: Socket Programming> 5.3 비연결형클라이언트 / 서버의작성 2. 동시처리비연결형클라이언트 / 서버 1) 서버와클라이언트의소켓생성 2) 서버는 BIND 작업후대기 3) 클라이언트가서버로접속데이터송신 4) 서버는클라이언트의접속시마다클라이언트처리용스레드생성 5) 이후의클라이언트와의통신은각각의스레드가담당 6) 서버종료작업 7) 종료시스레드를통한클라이언트종료 8) 서버와클라이언트소켓닫음 (CLOSE)

<90> <CDP: Socket Programming> ( 예 ) 다중처리용비연결형서버 while(1) { memset(buff, '\0', sizeof(buff)); /* 접속클라이언트에대한수신데이타처리 */ msgsize = recvfrom(server_socket, BUFF, sizeof(buff), 0, (struct sockaddr*)&client_addr, &addrsize); if (msgsize <= 0) continue; memcpy(&curr_addr, &client_addr, sizeof(struct sockaddr_in)); memset(curr_buff, '\0', sizeof(curr_buff)); memcpy(curr_buff, BUFF, strlen(buff)); /* 수신에대한데이타처리는 Thread로처리. 현재의예제에서는실용성이많지않으나실제에서는수신데이타에대한처리는많은작업이있을수있음 */ pthread_create(&thread, NULL, thread_process, (void *)server_socket); } void* thread_process(void * server_socket) { memset(temp_buff, '\0', sizeof(temp_buff)); memcpy(temp_buff, CURR_BUFF, strlen(curr_buff)); printf("client Message>>%s", temp_buff); /*Thread로처리되는클라이언트데이터송신*/ sendto((int)server_socket, temp_buff, strlen(temp_buff), 0, (struct sockaddr*)&temp_addr, sizeof(struct sockaddr)); }

<91> <CDP: Socket Programming> ( 예 ) 다중처리용비연결형클라이언트 /* 데이타수신에대한 Thread 생성 */ pthread_create(&thread, NULL, thread_process, (void*)connect_fd); while(1) { memset(msg, '\0', sizeof(msg)); fgets(msg, 1024, stdin); msgsize = strlen(msg); /* 사용자입력데이타에대한처리. 서버전송 * sendto 함수이용 */ msgsize = sendto(connect_fd, msg, msgsize, 0, (struct sockaddr*)&connect_addr, addrsize); printf("message Send>>%s", msg); } void* thread_process(void * sockfd) { while(1) { memset(temp_buff, '\0', sizeof(temp_buff)); /* 서버에서의송신데이타에대한처리 recvfrom 함수이용 */ recvfrom((int)sockfd, temp_buff, sizeof(temp_buff), 0, (struct sockaddr*)&server_addr, &temp_addrsize); printf("message Receive>>%s", temp_buff); } }

<92> <CDP: Socket Programming> 6. 채팅을위한클라이언트 / 서버프로그램작성 1. 채팅프로그램구조 2. 채팅서버프로그램개요및구조 3. 채팅 Client 프로그램개요및구조

<93> <CDP: Socket Programming> 6.1 채팅프로그램구조 채팅서버와클라이언트와의연결관계

<94> <CDP: Socket Programming> 6.2 채팅서버프로그램개요및구조 (1) 서버프로그램구조 1) 서버에서사용하는구조체초기화 2) 서버소켓생성및클라이언트대기 3) select 를이용한접속상황관리 - 클라이언트가접속하면소켓기술자의상태가변화하여접속여부확인 4) 접속처리 - 접속한클라이언트가넘겨주는정보로서버의각구조체를업데이트함 5) 데이터송수신 - 클라이언트로받은데이터는검색하여같은채팅방안에접속한각각의다른 클라이언트에게전송 - 데이터수정작업필요 ( 이름첨가등 ) 6) 서버소켓닫기 - 종료하지않는다면 3) 으로복귀 7) 프로그램종료

<95> <CDP: Socket Programming> 6.2 채팅서버구조

<96> <CDP: Socket Programming> /* 채팅에서의방을 3 개로설정 */ struct room_node roomlist[3]; 서버 : 채팅방설정 /* 각방에대한방이름초기화 */ strcpy(roomlist[0].room_name,"room1"); strcpy(roomlist[2].room_name,"room3"); strcpy(roomlist[1].room_name,"room2"); /* 각방의접속사용사수를초기화 */ roomlist[0].user_count = 0; roomlist[1].user_count = 0; roomlist[2].user_count = 0; /* 서버소켓생성 */ server_socket = socket(af_inet, SOCK_STREAM, 0); /* 서버 IP 및포트설정 */ server_addr.sin_family = AF_INET; server_addr.sin_port = htons(server_port); server_addr.sin_addr.s_addr = htonl(inaddr_any); memset(&(server_addr.sin_zero), 0, 8); bind(server_socket, (struct sockaddr*)&server_addr, sizeof(struct sockaddr)); listen(server_socket, 0); FD_ZERO(&readfd);

<97> <CDP: Socket Programming> 서버 : 서버에접속한클라이언트소켓기술자확인 /* 서버에접속한클라이언트소켓기술자 [ 각방의유저구조체포함 ] 를 fd_set 에설정 */ FD_SET(server_socket, &readfd); for (room_index = 0; room_index < 3; room_index++) { for (user_index = 0; user_index < roomlist[room_index].user_count; user_index++) { tempsockfd = roomlist[room_index].user_list[user_index].user_sockfd; FD_SET(tempsockfd, &readfd); } } maxfd = maxfd + 1; if (tempsockfd > maxfd) maxfd = tempsockfd;

<98> <CDP: Socket Programming> 서버 : 클라이언트접속처리 select(maxfd, &readfd, NULL, NULL,NULL); /* 서버로의접속이있는클라이언트에대한처리 */ if (FD_ISSET(server_socket, &readfd)) { addrsize = sizeof(struct sockaddr_in); client_socket = accept(server_socket, (struct sockaddr*)&server_addr, &addrsize); memset(buff, '\0', sizeof(buff)); msgsize = read(client_socket, BUFF, sizeof(buff)); } if (msgsize <=0) { printf("enter user Error\n"); continue; }

<99> <CDP: Socket Programming> 서버 : 각방별로참가자확인및확약 printf("receive Message:%s\n", BUFF); /* 각방이 5 명으로제한되어있으므로해당유저인원체크 */ if (BUFF[0] == '1') { printf("login Room1 Count:%d\n", roomlist[0].user_count); if (roomlist[0].user_count == 5) { strcpy(buff, "User Count Overflow Error"); write(client_socket, BUFF, strlen(buff)); close(client_socket); continue; /* 인원초과 */ } roomlist[0].user_list[roomlist[0].user_count].user_sockfd = client_socket; roomlist[0].user_count++; strcpy(buff, "ConnectOK"); write(client_socket, BUFF, strlen(buff)); }

<100> <CDP: Socket Programming> 서버 : 참가자에게수신정보전달 for (room_index = 0; room_index < 3; room_index++) { for (user_index = 0; user_index < roomlist[room_index].user_count; user_index++) { if (FD_ISSET(roomlist[room_index].user_list[user_index].user_sockfd,&readfd)){ memset(buff, '\0', sizeof(buff)); tempsockfd = roomlist[room_index].user_list[user_index].user_sockfd; msgsize = read(tempsockfd, BUFF,sizeof(BUFF)); if (msgsize <= 0) { if (user_index == roomlist[room_index].user_count) { close(roomlist[room_index].user_list[user_index].user_sockfd); roomlist[room_index].user_count--; } else if (user_index < roomlist[room_index].user_count) { close(roomlist[room_index].user_list[user_index].user_sockfd); for (temp_user_count = user_index; temp_user_count < roomlist[room_index].user_count; temp_user_count++) { roomlist[room_index].user_list[temp_user_count] = roomlist[room_index].user_list[temp_user_count+1]; roomlist[room_index].user_count--; } } else { printf("receive Message=>%s\n", BUFF, msgsize); for (temp_user_count = 0; temp_user_count < roomlist[room_index].user_count; temp_user_count++) { msgsize = strlen(buff); write(roomlist[room_index].user_list[temp_user_count].user_sockfd, BUFF,msgsize); } } } } }

<101> <CDP: Socket Programming> 6.2 채팅 Client 프로그램개요및구조 (2) 클라이언트프로그램구조 1) 서버에전달할기본데이터입력 - 사용자의대화명및방번호 2) 서버접속을위한구조체설정 - 서버주소및포트정보입력 3) 소켓생성 4) 서버로접속시도및확인 - Connect 함수이용하여접속 - 접속처리결과를서버로부터받음 5) 데이터수신 - 수신데이터는수정하지않고바로화면에출력함 - 서버에서분류되어전송되었으므로클라이언트는따로처리할필요없음 6) 데이터송신 - 자신의대화명추가후서버로송신 7) 클라이언트프로그램소켓닫기 - 종료하지않는다면 5) 으로복귀 8) 프로그램종료

<102> <CDP: Socket Programming> 클라이언트 : 채팅방요구준비 /* 사용자대화명입력처리 */ fgets(name,30, stdin); name[strlen(name)-1] = '\0'; while(1) { /* 접속방번호입력 */ printf("#enter Room Number(ex=>1 or 2 or 3)=>"); room_number = (char)fgetc(stdin); fgetc(stdin); if (room_number!= '1' && room_number!='2' && room_number!= '3') { printf("incorrect Room Number\n"); continue; } else break; } memset(msg, '\0', sizeof(msg)); msg[0] = room_number; for (temp_index = 0; temp_index < strlen(name); temp_index++) { msg[temp_index+1] = name[temp_index]; }

<103> <CDP: Socket Programming> 클라이언트 : 채팅방요구 connect_fd = socket(af_inet, SOCK_STREAM, 0); connect_addr.sin_family = AF_INET; connect_addr.sin_port = htons(atoi(argv[2])); connect_addr.sin_addr.s_addr = inet_addr(argv[1]); memset(&(connect_addr.sin_zero), 0, 8); /* 서버접속 */ connect(connect_fd, (struct sockaddr*)&connect_addr, sizeof(connect_addr)); msgsize = strlen(msg); write(connect_fd, msg, msgsize); memset(msg, '\0', sizeof(msg)); /* 채팅서버에대한접속결과확인 */ read(connect_fd, msg, sizeof(msg)); if (!strcmp(msg, "ConnectOK")) { printf("*******server Connection Success********\n"); printf("*******start Chatting Program ********\n"); } if (!strcmp(msg, "User Count Overflow Error")) { printf("%s\n", msg); exit(1); }

<104> <CDP: Socket Programming> 클라이언트 : 채팅 FD_ZERO(&readfd); while(1) { FD_SET(0, &readfd); FD_SET(connect_fd, &readfd); select (connect_fd+1, &readfd, NULL, NULL, NULL); } if (FD_ISSET(connect_fd, &readfd)) { memset(msg, '\0', sizeof(msg)); msgsize = read(connect_fd, msg, sizeof(msg)); if (msgsize <= 0) continue; printf("*from=>%s\n", msg); } if (FD_ISSET(0, &readfd)) { memset(msg, '\0', sizeof(msg)); fgets(msg, 1024, stdin); msg[strlen(msg)-1] = '['; strcat(msg, name); msg[strlen(msg)] = ']'; msgsize = strlen(msg); write(connect_fd, msg, msgsize); }

<105> <CDP: Socket Programming> 정리및질의응답