Linux Socket Programming - Introducing Sockets –

Slides:



Advertisements
Similar presentations
Format String Attack! 포맷 스트링 공격 경일대학교 사이버보안학과 학년 남주호.
Advertisements

Java Socket 통신 이개혁 정대준.
한남대학교 컴퓨터공학과 소프트웨어공학실험실 최 용 준
Network Lab. Byoung-Son, Choi
Understanding of Socket and File I/O
Database Laboratory, Hong Ik University
인공지능실험실 석사 2학기 이희재 TCP/IP Socket Programming… 제 11장 프로세스간 통신 인공지능실험실 석사 2학기 이희재
Network Lab. Young-Chul Hwang
TCP Client/Server Program
Department of Computer Science and Engineering
소켓 모델 주소 지정 in_addr_t inet_addr(const char *ip_address) 연결 지향 모델 (TCP)
08. 디바이스 드라이버의 읽기와 쓰기 김진홍
TCP Client/Server Program
Network Lab. Seoung Hyeon, Lee
Department of Computer Science and Engineering
6장 비연결형 지향 프로토콜 Database Lab 강 우 석.
제 14장 Multicast & Broadcast
네트워킹 CHAPTER 13 Section 1 네트워킹의 개요와 java.net 패키지 Section 2 인터넷 주소와 URL
Using Standard I/O on Sockets
Department of Computer Engineering
한남대학교 컴퓨터공학과 컴퓨터 네트워크 실험실
Department of Computer Engineering
인공지능실험실 석사 2학기 이희재 TCP/IP Socket Programming… 제 7장 소켓 연결의 우아한 종료 인공지능실험실 석사 2학기 이희재
Linux서버를 이용한 채팅프로그램 지도 교수님 : 이형원 교수님 이 름 : 이 은 영 학 번 :
양방향 파이프의 활용 양방향 통신 파이프는 기본적으로 단방향이므로 양방향 통신을 위해서는 파이프를 2개 생성한다.
12장 파이프.
07. 디바이스 드라이버의 초기화와 종료 김진홍
Department of Computer Engineering
11장. 포인터 01_ 포인터의 기본 02_ 포인터와 Const.
Signal & Inter-Process Communication
SqlParameter 클래스 선문 비트 18기 발표자 : 박성한.
Homework 6… 12월 2일(금) 11:59pm까지 자신의 이름과 학번을 출력해 주는 유닉스/리눅스 네트워크 소켓 서버 프로그램 과 클라이언트 프로그램 을 작성해 보세요 참고 (실습1) Hello 프로그램 helloserver.c helloclient.c 컴파일.
Chapter 06. UDP 서버/클라이언트.
인공지능실험실 박사 1학기 장성만 TCP/IP Socket Programming… 9장 소켓의 다양한 옵션 인공지능실험실 박사 1학기 장성만
TCP/IP 응용 프로그램에 적용 가능한 다양한 소켓 옵션을 이해하고 활용한다.
파일 기술자 파일 기술자 현재 열려있는 파일을 구분하는 정수값 저수준 파일 입출력에서 열린 파일을 참조하는데 사용
메시지 큐[5] – test1.c 메시지 제어: msgctl(2) #include <sys/msg.h>
프로젝트 발표 순서 12/7(수), 팀 별 15분 발표순서 PPT (팀 별 이름, 구현 내용, 결과-그래프 포함) 각 기법당
Department of Computer Science and Engineering
13장 고급 입출력 함수 박사 4학기 최 성자.
TCP/IP Socket Programming…
Socket Address Structure and Byte Ordering Functions
Socket Address Structure and Byte Ordering Functions
Department of Computer Engineering
13. 포인터와 배열! 함께 이해하기 IT응용시스템공학과 김 형 진 교수.
TCP/IP 응용 프로그램에 적용 가능한 다양한 소켓 옵션을 이해하고 활용한다.
HTTP 프로토콜의 요청과 응답 동작을 이해한다. 서블릿 및 JSP 를 알아보고 역할을 이해한다.
24장. 파일 입출력.
네트워크 프로그래밍의 이해 School of Electronics and Information.
Chapter6 : JVM과 메모리 6.1 JVM의 구조와 메모리 모델 6.2 프로그램 실행과 메모리 6.3 객체생성과 메모리
School of Electronics and Information. Kyung Hee University.
컴퓨터 프로그래밍 기초 - 10th : 포인터 및 구조체 -
Department of Computer Engineering
Department of Computer Engineering
Signal & Inter-Process Communication
네트워크 환경 구축과 이미지 전송 호스트/타겟 통신 직렬 통신을 이용한 이미지 전송 수퍼 데몬 BOOTP 환경 구축
01. 개요 네트워크에 있는 컴퓨터와 그룹에 대한 NetBIOS 이름에 대응되는 IP 주소를 찾아주는 서비스
Chapter 04. TCP 서버/클라이언트.
Chapter 02. 윈도우 소켓 시작하기.
MIDP 네트워크 프로그래밍 ps lab 김윤경.
구조체(struct)와 공용체(union)
인공지능실험실 박사 1학기 장성만 TCP/IP Socket Programming… 제 8장 도메인 이름과 인터네 주소 인공지능실험실 박사 1학기 장성만
바이트 순서 변환 함수 주소 변환 함수 바이트 조작 함수 원격지 호스트 정보를 얻는 함수
9 파이프.
Department of Computer Engineering
06. 디바이스의 등록과 해제 김진홍
제 29 강 스트링(string) 다루기 s a i s . s T i h t g r i n.
Network Lab. Young-Chul Hwang
13. 포인터와 배열! 함께 이해하기.
Signal & Inter-Process Communication
Presentation transcript:

Linux Socket Programming - Introducing Sockets – Network Lab. 이 성 현 한남대학교 컴퓨터공학과 컴퓨터 네트워크 실험실

목 차 소켓의 역사 소켓의 본질 리눅스 커널과 응용 프로그램의 소켓 참조 소켓 C 프로그램 예제

간단한 역사 소개 1957. 10. 04 - Sputnik 발사 성공 1958. 01. 07 - ARPA(Advanced Research Projects Agency) 출범 1962 - J.C.R Licklider : 서로 다른 컴퓨터 간의 통신을 위 한 아이디어 창출 1969 - ARPA & UNIX 1982 - 4.1BSD와 4.2BSD에 TCP/IP를 포함한 UCB 배포 1991. 10. 05 – Linux 0.02 발표

그림 1.1: ARPA으로부터 24년 후에 BSD 소켓 발달 간단한 역사 소개(계속) October 4, 1957 Sputnik January 1, 1958 ARPA 1962 J.C.R Licklider ARPANET 1969 UNIX 1979 DARPA funds UCB 1982 4.1BSD and 4.2BSD Sockets October 5, 1991 Linux 0.02 그림 1.1: ARPA으로부터 24년 후에 BSD 소켓 발달

소켓의 이해 소켓의 정의 – 전화 네트워크와의 비교 리눅스의 소켓은 전화와 유사 소켓은 통신라인의 종점을 표시 소켓의 이해 소켓의 정의 – 전화 네트워크와의 비교 리눅스의 소켓은 전화와 유사 소켓은 통신라인의 종점을 표시 전화 : 전화번호 – 소켓 : 네트워크 주소 소켓은 통신의 종점이기 때문에 종료 가능

소켓의 이해(계속) 전화 네트워크 Telephone Network 그림 1.2 전화 네트워크

소켓에 대한 이해(계속) 소켓의 정의 소켓은 소프트웨어로 작성된 통신 접속점 소켓은 서버와 서로 특정한 규약을 사용하여 데이터를 전송하는 방식 네트워크 응용 프로그램은 소켓을 통해 데이터 송수신 소켓 인터페이스 - 응용 프로그램에서 TCP/IP를 이용하는 창구 역할을 하는 인터페이스

소켓의 이해(계속) (OSI 계층) 그림 1.3: 소켓 인터페이스 위치 5-7 소켓 인터페이스 4 3 2 1 네트워크 응용 1 응용 2 응용 3 소켓 인터페이스 소켓 1 소켓 2 소켓 3 4 TCP/IP 3 2 네트워크 드라이버 1 네트워크 그림 1.3: 소켓 인터페이스 위치

소켓의 이해(계속) 소켓 사용 open(2) 함수를 사용하여 파일을 열 때, 파일 기술자를 리턴하면 성공 read(2), write(2), lseek(2), close(2)를 사용하여 파일을 열 수 있다.

소켓의 이해(계속) 소켓과 파이프의 차이점 소켓은 lseek(2)할 수 없다. 소켓은 위치 주소를 가지지만, 파일과 파이프는 네트워크 주소를 가질 수 없다. 소켓은 서로 다른 옵션을 사용할 수 있으며, 소켓에 대한 질문과 ioctl(2)를 사용할 수 있다. 소켓은 입/출력을 위해 올바른 상태를 가져야 하지만, 오픈된 파일은 어떠한 때라도 읽거나 쓸 수 있다.

소켓의 이해(계속) 소켓 참조 open(2) 함수를 호출하여 새로운 파일을 열었을 때, 파일 기술자를 리눅스 커널에서 리턴 파일 기술자를 호출하여, 파일이 열려질 때 0 또는 양의 정수 값을 이용

소켓의 이해(계속) 파일 기술자가 커널에 위치하는 과정 파일을 열기 위해서 open(2) 함수 호출 파일 기술자 3이 열려진 파일을 참조하기위해서 리턴된다. 새로운 소켓이 적당한 함수를 호출하여 생성된다. 파일 기술자 4는 새로운 소켓을 참조하기 위해서 리턴된다. 다른 파일이 open(2)를 호출하여 열린다. 파일 기술자 5는 새로 오픈된 파일을 참조하기 위해서 리턴된다.

소켓의 이해(계속) 서버 클라이언트 연결요청 데이터 데이터 종료 그림 1.4: 소켓 연결 개요 socket() socket() bind() listen() 연결요청 connect() accept() 데이터 write() read() write() 데이터 read() 종료 close() 그림 1.4: 소켓 연결 개요

소켓의 이해(계속) 소켓 함수의 예 socket() : 사용하고자 하는 통신 프로토콜을 지정 int socket(int domain, int type, int protocol); socketpair() : 소켓 연결의 한 쌍을 지정 int socketpair(int domain, int type, int protocol, int sv[2]); bind() : 소켓에 이름을 결합 int bind(int sockfd, sockaddr * myaddr, int addrlen);

소켓의 이해(계속) 소켓 함수의 예 connect() : 클라이언트가 서버에 연결을 요청하기 위해 호출 int connect(int socfd, struct sockaddr *servaddr, int addrlen); listen() : 서버 프로세스가 통신할 연결기반 소켓 설정 int listen(int sockfd, int size); accept() : 서버 프로세스에서 클라이언트 소켓과 연결을 설정 하기 위해 호출 int accept(int sockfd, struct sockaddr *peer, int *addrlen);

소켓의 이해(계속) 소켓 함수의 예 write() : 다른 소켓에 메시지 전송 read() : 다른 소켓에서 메시지 수신 ssize_t write(int fd, const void *buf, size_t count); read() : 다른 소켓에서 메시지 수신 ssize_t read(int fd, void *buf, size_t count); close() : 소켓의 연결을 종료 int close(int fd);

소켓과 파이프의 비교 pipe pipe(2) 함수 호출이 성공이면, 두개의 파일 기술자가 리턴된다. filedes[0] : 파이프의 끝까지 읽기 위해서 파일 기술자를 담는다. filedes[1] : 파이프의 끝까지 쓰기 위해서 파일 기술자를 받는다. 오직 하나의 직접적인 통신 라인 생성

소켓과 파이프의 비교(계속) 소켓 직접적인 통신 프로세스만 허용 프로세스는 소켓을 열기 위해 파일 기술자 3 사용 지역 프로세스가 파일 기술자 3으로부터 정보를 받아 통신이 이루어지는 원격 프로세스에 보낼 수 있다.

소켓의 생성 Socketpair(2) 함수 int socketpair(int domain, int type, int protocol, int sv[2]); 소켓의 도메인 소켓의 형태 소켓이 사용하는 프로토콜 소켓을 생성하고 참조하는 파일 기술자를 받기 위한 배열 포인터

소켓의 생성(계속) type 인수 – 소켓의 타입 선언 SOCK_STREAM 스트림 소켓 SOCK_DGRAM 데이터그램 소켓

소켓의 생성(계속) socketpair(2) 리턴 값 success : 0 error : -1, errno 에 에러 발생 이유 출력

소켓의 생성(계속) socketpair(2) 예제 – Listing 1.1 13: int 14: main(int argc,char **argv) { 15: int z; /* Status return code */ 16: int s[2]; /* Pair of sockets */ 16 라인에서 소켓이 생성되고 참조되는 두 개의 새로운 파일 기술자를 s[2]의 배열로 받음

소켓의 생성(계속) socketpair(2) 예제 – Listing 1.1 socketpair(2) 함수 호출 21: z = socketpair(AF_LOCAL,SOCK_STREAM,0,s); socketpair(2) 함수 호출 AF_LOCAL : 도메인 인수 지정 SOCK_STREAM : 소켓 타입 0 : 프로토콜 0으로 지정 s : 파일 기술자를 받기 위한 배열 포인터 지정

소켓의 생성(계속) socketpair(2) 예제 – Listing 1.1 에러 발생 출력 23: if ( z == -1 ) { 24: fprintf(stderr, 25: "%s: socketpair(AF_LOCAL,SOCK_STREAM,0)\n", 26: strerror(errno)); 27: return 1; /* Failed */ 에러 발생 출력

소켓의 생성(계속) socketpair(2) 예제 – Listing 1.1 소켓 s[0]의 파일 기술자 출력 33: printf("s[0] = %d;\n",s[0]); 34: printf("s[1] = %d;\n",s[1]); 소켓 s[0]의 파일 기술자 출력 소켓 s[1]의 파일 기술자 출력

소켓의 생성(계속) socketpair(2) 예제 – Listing 1.1 36: system("netstat --unix -p"); netstat(1) 명령어는 system(3) 함수를 사용 --unix : AF_LOCAL 도메인을 출력 -p : 프로세스의 정보를 출력

소켓의 생성(계속) 실행 결과 1: $ ./01lst01 2: s[0] = 3; 3: s[1] = 4; 4: (Not all processes could be identified, non-owned process info 5: will not be shown, you would have to be root to see it all.) 6: Active UNIX domain sockets (w/o servers) 7: Proto RefCnt Flags Type State I-Node PID/Program name Path 8: unix 1 [ ] STREAM CONNECTED 112354 - @0000022c 9: unix 1 [ ] STREAM CONNECTED 112220 - @0000020e 10: unix 12 [ ] DGRAM 485 - /dev/log 11: unix 1 [ ] STREAM CONNECTED 112286 - @00000218 ……………………… 21: unix 1 [ ] STREAM CONNECTED 288195 28402/01lst01 22: unix 1 [ ] STREAM CONNECTED 288194 28402/01lst01

소켓의 생성(계속) 실행 결과 분석 2-3 라인 : 파일 기술자 3, 4에 의해 열려진 소켓 2-45 라인 : netstat(1) 명령으로 system(3) 함수를 호 출하여 출력 21-22라인 : 소켓의 정보 출력 프로그램 명 : 01lst01 프로세스 ID : 28402

소켓의 입출력 실행 read(2), write(2), close(2) 함수 호출 #include <unistd.h> ssize_t read(int fd, void *buf, size_t count); ssize_t write(int fd, const void *buf, size_t count); int close(int fd); read(2) : 파일 기술자의 이용 가능한 값을 count 바 이트에 정의된 값 만큼 buf 에 할당 리턴값 : 읽은 바이트 숫자

소켓의 입출력 실행(계속) read(2), write(2), close(2) 함수 호출 write(2) : 버퍼 buf를 제공받은 파일 기술자 fd 로부 터 데이터를 작성 리턴 값 : 작성중인 바이트 숫자, 일반적으로 count 인수 값 과 일치 close(2) : 파일 기술자가 성공적으로 종료되었을 때 0을 리턴

소켓의 입출력 실행(계속) 예제 프로그램-Listing 1.2 16: int s[2]; /* Pair of sockets */ …………………. 23: z = socketpair(AF_LOCAL,SOCK_STREAM,0,s); socketpair(2) 함수가 23 라인에서 호출되고, 성공적으로 이루어 졌다면, s[2]배열의 s[0]와 s[1]에 파일 기술자 리턴

소켓의 입출력 실행(계속) 예제 프로그램-Listing 1.2 에러 발생 출력 25: if ( z == -1 ) { 26: fprintf(stderr, 27: "%s: socketpair(AF_LOCAL,SOCK_STREAM," 28: "0)\n", 29: strerror(errno)); 30: return 1; 에러 발생 출력

소켓의 입출력 실행(계속) 예제 프로그램-Listing 1.2 36: z = write(s[1],cp="Hello?",6); “Hello?” 메시지가 소켓s[1]에 작성, write(2) 함수의 count 인수에 6으로 할당된 버퍼 값 때문에 공백 바이트를 작성하지 않는다.

소켓의 입출력 실행(계속) 예제 프로그램-Listing 1.2 에러 발생 출력 37: if ( z < 0 ) { 38: fprintf(stderr, 39: "%s: write(%d,\"%s\",%d)\n", 40: strerror(errno),s[1],cp,strlen(cp)); 41: return 2; /* Failed write */ 에러 발생 출력

소켓의 입출력 실행(계속) 예제 프로그램-Listing 1.2 s[1]의 메시지 출력 44: printf("Wrote message '%s' on s[1]\n",cp); s[1]의 메시지 출력 49: z = read(s[0],buf,sizeof buf); 소켓 s[0]의 메시지를 읽어 버퍼에 저장

소켓의 입출력 실행(계속) 예제 프로그램-Listing 1.2 에러 발생 출력 50: if ( z < 0 ) { 51: fprintf(stderr, 52: "%s: read(%d,buf,%d)\n", 53: strerror(errno),s[0],sizeof buf); 54: return 3; /* Failed read */ 에러 발생 출력

소켓의 입출력 실행(계속) 예제 프로그램-Listing 1.2 소켓이 성공적으로 메시지를 받았다는 것을 출력 60: buf[z] = 0; /* NUL terminate */ 61: printf("Received message '%s' from socket s[0]\n", 62: buf); 소켓이 성공적으로 메시지를 받았다는 것을 출력

소켓의 입출력 실행(계속) 예제 프로그램-Listing 1.2 소켓 s[0]에 “Go away!”메시지를 저장 에러 발생 출력 67: z = write(s[0],cp="Go away!",8); 68: if ( z < 0 ) { 69: fprintf(stderr, 70: "%s: write(%d,\"%s\",%d)\n", 71: strerror(errno),s[0],cp,strlen(cp)); 72: return 4; /* Failed write */ 소켓 s[0]에 “Go away!”메시지를 저장 에러 발생 출력

소켓의 입출력 실행(계속) 예제 프로그램-Listing 1.2 s[0]의 메시지 출력 75: printf("Wrote message '%s' on s[0]\n",cp); s[0]의 메시지 출력

소켓의 입출력 실행(계속) 예제 프로그램-Listing 1.2 소켓 s[1]의 메시지를 읽어 버퍼에 저장 에러 발생 출력 80: z = read(s[1],buf,sizeof buf); 81: if ( z < 0 ) { 82: fprintf(stderr, 83: "%s: read(%d,buf,%d)\n", 84: strerror(errno),s[1],sizeof buf); 85: return 3; /* Failed read */ 소켓 s[1]의 메시지를 읽어 버퍼에 저장 에러 발생 출력

소켓의 입출력 실행(계속) 예제 프로그램-Listing 1.2 메시지의 수신이 성공 소켓 s[1]으로부터 받은 메시지 출력 91: buf[z] = 0; /* NUL terminate */ 92: printf("Received message '%s' from socket s[1]\n", 93: buf); 메시지의 수신이 성공 소켓 s[1]으로부터 받은 메시지 출력

소켓의 입출력 실행(계속) 예제 프로그램-Listing 1.2 소켓 s[0]와 s[1]을 종료 프로그램을 종료 98: close(s[0]); 99: close(s[1]); 소켓 s[0]와 s[1]을 종료 102: return 0; 프로그램을 종료

소켓의 입출력 실행(계속) 실행 결과 $ ./01lst02 Wrote message 'Hello?' on s[1] Received message 'Hello?' from socket s[0] Wrote message 'Go away!' on s[0] Received message 'Go away!' from socket s[1] Done.

소켓의 종료 close(2) 함수 소켓 종료시에 사용 소켓이 종료되면, 원격 소켓으로부터 데이터 받을 수 없음. 소켓이 종료되면, 원격 소켓으로부터 데이터 받을 수 없음. 한 쌍의 소켓에서 하나만 종료된 것을 의미

소켓의 종료(계속) shutdown(2) 함수 shutdown 함수는 두 개의 인수를 요구 리턴값 #include shutdown(int s, int how); shutdown 함수는 두 개의 인수를 요구 명시한 함수를 부분적으로 shutdown 시키기 위한 소켓 기술자 s 소켓을 shutdown 시키는 방법을 가리키는 how 인수 리턴값 함수 호출 성공 : 0 함수 호출 실패 : -1

테이블 1.1: shutdown(2) 함수의 how 인수 허용 값 소켓의 종료(계속) how 인수가 허용하는 값 값 매크로 기술 SHUT_RD 명시한 소켓에서 읽는 것을 허용하지 않는다. 1 SHUT_WR 명시한 소켓에 쓰는 것을 허용하지 않는다. 2 SHUT_RDWR 명시한 소켓에서 읽거나 쓰는 것을 허용하지 않는다. 테이블 1.1: shutdown(2) 함수의 how 인수 허용 값

소켓의 종료(계속) 소켓 쓰기 shutdown 쓰기를 허용하지 않는 예제 int z; int s; /*Socket */ z = shutdown(s, SHUT_WR); if ( z == -1 ) perror("shutdown()");

소켓의 종료(계속) 소켓 쓰기 종료의 문제 해결 커널 네트워킹 소프트웨어에 의해 데이터가 버퍼에 저장된다. EOF 지시자를 원격 소켓에 보낸다. 이것은 원격 일기 프로세스에게 소켓에 더 이상의 데이터가 없음을 알려준다. EOF 지시자 이후에 보내는 메시지를 받기 위해 부분적으로 소켓을 열어 놓는다. EOF 지시자를 보낸 소켓을 종료한다.

소켓의 종료(계속) 중복 소켓 처리 int s; /* Existion socket */ int d; /* Duplicated socket */ d = dup(s); /* duplicate this socket */ close(s); /* nothing happens yet */ close(d); /* last close, so shutdown socket */

소켓의 종료(계속) shutdown() 함수 사용 shutdown() 함수가 소켓 s를 shutdown int s; /* Existing socket */ int d; /* Duplicated socket */ d = dup(s); /* duplicate this socket */ shutdown(s, SHUT_RDWR); /* immediate shutdown */ shutdown() 함수가 소켓 s를 shutdown

소켓의 종료(계속) 소켓 읽기 shutdown 소켓에서 읽어 들이는 것을 종료 수신되지 않은 데이터 무시 원격 소켓이 데이터를 전송하더라도 데이터를 수신하지 않음 에러 발생

테이블 1.2: shutdown(2) 함수의 리턴 에러 소켓의 종료(계속) shutdown(2) 함수 에러 shutdown(2) 함수의 에러 테이블 에러 기술 EBADF 주어진 소켓에 유효한 파일 기술자가 없다. ENOTSOCK 주어진 파일 기술자에 소켓이 없다. ENOTCONN 명시된 소켓이 연결되지 않았다. 테이블 1.2: shutdown(2) 함수의 리턴 에러

그림 1.5: fork(2)와 socketpair(2)의 클라이언트/서버 예 Client/Server 예제 Socket File Unit 3 Parent Process Socket File Unit 4 Kernel Child Process 그림 1.5: fork(2)와 socketpair(2)의 클라이언트/서버 예

Client/Server 예제(계속) fork(2) 함수 그림 1.6: fork(2) 수행 과정 fork() fork()의 부모 프로세스 PID = 135 fork() fork()의 리턴값 = 136 fork()의 리턴값 = 0 부모 프로세스 PID = 135 자식 프로세스 PID = 136 그림 1.6: fork(2) 수행 과정

Client/Server 예제(계속) Client/Server 프로세스 socketpair(2) 함수 호출 fork(2) 함수 호출 부모 프로세스와 자식 프로세스로 분기 부모 프로세스 : 서버 프로그램의 역할을 수행 자식 프로세스 : 클라이언트 프로그램의 역할을 수행

Client/Server 예제(계속) strftime(3) 함수 데이터와 시간을 사용하기 위한 문자열 형식 서버 요청된 현재 데이터와 시간을 획득 클라이언트가 요청한 문자열 포맷을 사용하여 리턴

Client/Server 예제(계속) strftime(3) 함수 buf : 출력 버퍼 지정 max : 버퍼 사이즈 지정 size_t strftime(char *buf, size_t max, const char *format, const struct tm *tm); buf : 출력 버퍼 지정 max : 버퍼 사이즈 지정 format : 데이터와 시간의 문자열 형식 tm : 출력 문자열을 생성하는 구성 요소 공급

Client/Server 예제(계속) Client/Server 예제-Listing 1.3 매크로 상수 값 정의 19: #ifndef SHUT_WR 20: #define SHUT_RD 0 21: #define SHUT_WR 1 22: #define SHUT_RDWR 2 23: #endif 매크로 상수 값 정의

Client/Server 예제(계속) Client/Server 예제-Listing 1.3 40: z = socketpair(AF_LOCAL,SOCK_STREAM,0,s); socketpair(2) 함수를 호출하여 소켓 생성 42: if ( z == -1 ) { 43: fprintf(stderr,"%s: socketpair(2)\n", 44: strerror(errno)); 45: exit(1); 에러 발생 출력

Client/Server 예제(계속) Client/Server 예제-Listing 1.3 51: if ( (chpid = fork()) == (pid_t)-1 ) { …………………………… 56: fprintf(stderr,"%s: fork(2)\n", 57: strerror(errno)); 58: exit(1); fork(2) 함수를 호출하여 프로세스 분기 에러 발생 출력

Client/Server 예제(계속) Client/Server 예제-Listing 1.3 60: } else if ( chpid == 0 ) { 61: 62: /* 63: * This is the child process (client) : ………………………… 125: close(s[1]); /* Close our end now */ 자식 프로세스가 클라이언트 프로그램으로 동작 서버에 요청하고, 응답을 받음

Client/Server 예제(계속) Client/Server 예제-Listing 1.3 127: else { 128: 129: /* 130: * This is the parent process (server) : ………………………………. 189: waitpid(chpid,&status,0); 부모 프로세스가 서버 프로그램으로 동작 클라이언트의 요구 수행

Client/Server 예제(계속) Client/Server 예제-Listing 1.3(Server) 136: printf("Child PID is %ld\n",(long)chpid); 137: fflush(stdout); 자식 프로세스의 PID 출력 139: close(s[1]); /* Client uses s[1] */ 소켓 s[1] 종료

Client/Server 예제(계속) Client/Server 예제-Listing 1.3(Server) 145: z = read(s[0],buf,sizeof buf); 146: 147: if ( z < 0 ) { 148: fprintf(stderr,"%s: read(2)\n", 149: strerror(errno)); 150: exit(1); read(2) 함수 호출하여 소켓 s[0]를 읽음 에러 발생 출력

Client/Server 예제(계속) Client/Server 예제-Listing 1.3(Server) 157: buf[z] = 0; ……………………… 165: strftime(txbuf,sizeof txbuf, /* Buffer */ 166: buf, /* Input format */ 167: localtime(&td)); /* Input time */ 메시지 수신을 종료하면 공백 바이트로 바꿈 버퍼에 저장된 내용을 지정된 포맷으로 변환

Client/Server 예제(계속) Client/Server 예제-Listing 1.3(Server) 현재 시간을 확정 163: time(&td); /* Get current time */ 현재 시간을 확정 172: z = write(s[0],txbuf,strlen(txbuf)); 173: 174: if ( z < 0 ) { 175: fprintf(stderr,"%s: write(2)\n", 176: strerror(errno)); 177: exit(1); write(2) 함수를 호출하여 소켓 s[0]에 메시지 작성 에러 발생 출력

Client/Server 예제(계속) Client/Server 예제-Listing 1.3(Server) 소켓 s[0] 종료 183: close(s[0]); 소켓 s[0] 종료 189: waitpid(chpid,&status,0); 자식 프로세스가 종료할 때까지 부모 프로세스를 종료하지 않기 위해 waitpid(2) 함수 호출

Client/Server 예제(계속) Client/Server 예제-Listing 1.3(Server) 부모 프로세스 종료 192: return 0; 부모 프로세스 종료

Client/Server 예제(계속) Client/Server 예제-Listing 1.3(Client) 67: printf("Parent PID is %ld\n",(long)getppid()); 부모 프로세스 PID 출력 69: close(s[0]); /* Server uses s[1] */ 소켓 s[0] 종료

Client/Server 예제(계속) Client/Server 예제-Listing 1.3(Client) 75: msgp = "%A %d-%b-%Y %l:%M %p"; 76: mlen = strlen(msgp); 서버에 보내는 문자열 형식 지정 msgp : 문자열 형식 지정 mlen : 문자열의 길이 지정

Client/Server 예제(계속) Client/Server 예제-Listing 1.3(Client) 78: printf("Child sending request '%s'\n",msgp); 79: fflush(stdout); 서버에 요청하는 문자열 형식 출력 서버에 문자열 전송

Client/Server 예제(계속) Client/Server 예제-Listing 1.3(Client) 84: z = write(s[1],msgp,mlen); 85: 86: if ( z < 0 ) { 87: fprintf(stderr,"%s: write(2)\n", 88: strerror(errno)); 89: exit(1); write(2)함수를 호출하여 소켓 s[1]에 메시지 작성 에러 발생 출력

Client/Server 예제(계속) Client/Server 예제-Listing 1.3(Client) 에러 발생 출력 97: if ( shutdown(s[1],SHUT_WR) == -1 ) { 98: fprintf(stderr,"%s: shutdown(2)\n", 99: strerror(errno)); 100: exit(1); 에러 발생 출력

Client/Server 예제(계속) Client/Server 예제-Listing 1.3(Client) 106: z = read(s[1],rxbuf,sizeof rxbuf); 107: if ( z < 0 ) { 108: fprintf(stderr,"%s: read(2)\n", 109: strerror(errno)); 110: exit(1); read() 함수를 호출하여 소켓 s[1]의 응답을 기다림 에러 발생 출력

Client/Server 예제(계속) Client/Server 예제-Listing 1.3(Client) 117: rxbuf[z] = 0; …………………………… 122: printf("Server returned '%s'\n",rxbuf); 123: fflush(stdout); 메시지 수신이 종료되면 공백 바이트로 바꿈 응답 메시지 출력

Client/Server 예제(계속) Client/Server 예제-Listing 1.3(Client) 소켓 s[1] 종료 125: close(s[1]); /* Close our end now */ 소켓 s[1] 종료 192: return 0; 클라이언트 프로세스 종료

Client/Server 예제(계속) 실행 결과 $ ./01lst03 Child PID is 28447 Parent PID is 28446 Child sending request '%A %d-%b-%Y %l:%M %p' Server returned 'Tuesday 13-Mar-2001 4:45 PM'

Client/Server 예제(계속) 프로그램 실행 결과-msgp 변경 실행 결과 75: msgp = "%A %d-%b-%Y %l:%M %p"; 75: msgp = "%d-%b-%y"; 실행 결과 15-Jul-99