42
유유유 유유유 유유유유유 유유 유유유유유 유유

소켓 프로그래밍 기초

  • Upload
    clove

  • View
    152

  • Download
    8

Embed Size (px)

DESCRIPTION

11. 소켓 프로그래밍 기초. 학습목표. TCP/IP 프로토콜의 기본 개념을 이해한다 . IP 주소와 포트번호의 개념을 이해한다 . 소켓 관련 구조체와 함수를 이해한다 . 소켓을 이용한 통신 프로그램을 작성할 수 있다. 목차. TCP/IP 개요 IP 주소와 호스트명 포트번호 소켓 프로그래밍 기초 소켓 인터페이스 함수 유닉스 도메인 소켓 예제 인터넷 소켓 예제. TCP/IP 인터넷의 표준 프로토콜 5 계층 (4 계층 ) 으로 구성 TCP 와 UDP 의 차이. - PowerPoint PPT Presentation

Citation preview

Page 1: 소켓 프로그래밍 기초

유닉스 시스템 프로그래밍

소켓 프로그래밍 기초

Page 2: 소켓 프로그래밍 기초

2/42

학습목표

TCP/IP 프로토콜의 기본 개념을 이해한다 . IP 주소와 포트번호의 개념을 이해한다 . 소켓 관련 구조체와 함수를 이해한다 . 소켓을 이용한 통신 프로그램을 작성할 수 있다 .

Page 3: 소켓 프로그래밍 기초

3/42

목차

TCP/IP 개요

IP 주소와 호스트명

포트번호

소켓 프로그래밍 기초

소켓 인터페이스 함수

유닉스 도메인 소켓 예제

인터넷 소켓 예제

Page 4: 소켓 프로그래밍 기초

4/42

TCP/IP 개요 (1) TCP/IP

인터넷의 표준 프로토콜 5 계층 (4 계층 ) 으로 구성

TCP 와 UDP 의 차이전화 vs. 라디오방송

Page 5: 소켓 프로그래밍 기초

5/42

TCP/IP 개요 (2) IP 주소

TCP/IP 프로토콜을 이용하여 데이터를 송수신할 때에 통신 상대방을 식별하기 위해 주소 (address) 를 사용

IP 계층에서 주소 관련 프로토콜 작업 수행 IPv4 주소 : 점 (.) 으로 구분된 4 바이트• 예 - 192.168.100.1• IPv6 주소 : 6 바이트 사용

서비스 포트 (Service Port) 하나의 호스트에서 수신된 패킷을 처리할 서비스 프로세스를 식별 2 바이트 정수 : 0~65535• 0~1023 : well-known port• FTP: 21, SSH: 22, Telnet:23, SMTP:25, HTTP: 80 등• 1024~65535 : user port

TCP/IP 패킷의 수신자 주소는 “ IP 주소 +

포트번호” 로 이루어진다 .

Page 6: 소켓 프로그래밍 기초

6/42

TCP/IP 개요 (3) 소켓 인터페이스 (Socket Interface)

응용 계층에서 전송 계층의 기능을 사용할 수 있도록 제공하는 응용 프로그래밍 인터페이스• 네트워크 계층이나 전송 계층의 기능은 복잡하여 직접 사용하여 데이터 전송

프로그램을 작성하기 어려움 . • 하부의 내부 구조나 인터페이스 방식을 세부적으로 알 필요없이 용이하게 네트워크

프로그램을 작성할 수 있도록 쉬운 인터페이스를 제공

Ethernet

IP

TCP/UDP

Ethernet

IP

TCP/UDP

Internet라우터 라우터

Page 7: 소켓 프로그래밍 기초

7/42

IP 주소와 호스트명 (1) IP 주소와 호스트명

IP 주소 : 인터넷을 이용할 때 사용하는 주소로 점 (.) 으로 구분된 32 비트 숫자

호스트명 (Host Name): 시스템에 부여된 이름 도메인명 (Domain Name): 호스트명 + 네트워크명 DNS(Domain Name Service)• 호스트명 ( 도메인명 ) 과 IP 주소를 관리하는 서비스

호스트명과 IP 주소 변환 /etc/hosts 파일 또는 DNS, NIS 등 /etc/nsswitch.conf 파일에 주소변환을 누가 할 것인지 지정hosts: files dns

/etc/hosts 파일에서 먼저 찾고 없으면 DNS

서비스를 이용함 .

Page 8: 소켓 프로그래밍 기초

8/42

IP 주소와 호스트명 (2) 호스트명과 주소 읽어오기 : gethostent(3), sethostent(3),

endhostent(3)

gethostent : 호스트명과 IP 주소를 읽오 hostent 구조체에 저장 sethostent : 데이터베이스의 읽기 위치를 시작위치로 재설정 endhostent : 데이터베이스를 닫는다

hostent 구조체struct hostent { char *h_name; char **h_aliases; int h_addrtype; int h_length; char **h_addr_list;}

#include <netdb.h>struct hostent *gethostent(void);int sethostent(int stayopen);int endhostent(void);

Page 9: 소켓 프로그래밍 기초

9/42

[ 예제 11-1] 호스트명 읽어오기

01 #include <netdb.h>02 #include <stdio.h>03 04 int main(void) {05 struct hostent *hent;06 07 sethostent(0);08 09 while ((hent = gethostent()) != NULL)10 printf("Name=%s\n", hent->h_name);11 12 endhostent();13 14 return 0;15 }

처음 위치로 이동

DB 의 내용을 차례로 읽어오기

ex11_1.c

DB 닫기

# gcc ex11_1.c정의되지 않음 첫번째 참조된기호 파일 :endhostent /var/tmp//ccwQu9hN.ogethostent /var/tmp//ccwQu9hN.osethostent /var/tmp//ccwQu9hN.old: 치명적 : 기호 참조 오류 . a.out 에 출력이 기록되지 않음collect2: ld returned 1 exit status

왜 실행파일이 생성되지 않을까 ?

Page 10: 소켓 프로그래밍 기초

10/42

[ 예제 11-1] 실행결과 네트워크 관련 라이브러리 사용하기

표준 C 라이브러리에 없는 함수들이기 때문에 endhostent, gethostent, sethostent 표준 C 라이브러리 함수가 아니고 nsl 라이브러리 함수임 libnsl.so 라이브러리를 링크해여야 함 (/usr/lib 디렉토리에 위치 )

/etc/host 파일의 내용이 다음과 같을 때

실행결과

# gcc -o ex11_1.out ex11_1.c -lnsl

# cat /etc/hosts## Internet host table#127.0.0.1 localhost218.237.65.4 www.hanb.co.kr192.168.162.133 hanbit

# ex11_1.outName=localhostName=www.hanb.co.krName=hanbit

Page 11: 소켓 프로그래밍 기초

11/42

IP 주소와 호스트명 (3) 호스트명으로 정보 검색 : gethostbyname(3)

IP 주소로 정보 검색 : gethostbyaddr(3)

type( 주소 형식 ) 에 지정할 수 있는 값

#include <netdb.h>struct hostent *gethostbyname(const char *name);

#include <netdb.h>struct hostent *gethostbyaddr(const char *addr, int len, int type);

// Defined in <sys/socket.h>AF_UNSPEC 0 /* 미지정 */AF_UNIX 1 /* 호스트 내부 통신 */AF_INET 2 /* 인터네트워크 통신 : UDP, TCP 등 */AF_IMPLINK 3 /* Arpanet 의 IMP 주소 */AF_PUP 4 /* PUP 프로토콜 : BSP 등 */AF_CHAOS 5 /* MIT 의 CHAOS 프로토콜 */AF_NS 6 /* XEROX 의 NS 프로토콜 */AF_NBS 7 /* NBS 프로토콜 */…

Page 12: 소켓 프로그래밍 기초

12/42

포트 번호 (1) 포트 번호 (Port Number)

호스트에서 동작하고 있는 서비스를 구분하는 번호 2 바이트 정수로 0~65535 까지 사용가능 잘 알려진 포트 : 이미 정해져 있고 자주 사용하는 포트• 텔넷 (23), HTTP(80), FTP(21)

관련 파일 : /etc/services

포트 정보 읽어오기 : getservent(3), setservent(3), endservent(3)

getservent : 포트 정보를 servent 구조체로 반환 setservent : 읽기 위치를 시작으로 재설정 endservent : 데이터베이스 닫기

#include <netdb.h>struct servent *getservent(void);int setservent(int stayopen);int endservent(void);

struct servent { char *s_name; char **s_aliases; int s_port; char **s_proto;}

Page 13: 소켓 프로그래밍 기초

13/42

[ 예제 11-2] getservent 함수로 포트 정보 읽어오기 ex11_2.c

01 #include <netdb.h>02 #include <stdio.h>03 04 int main(void) {05 struct servent *port;06 int n;07 08 setservent(0);09 10 for (n = 0; n < 5; n++) {11 port = getservent();12 printf("Name=%s, Port=%d\n", port->s_name, port->s_port);13 }14 15 endservent();16 17 return 0;18 }

처음 위치로 이동

DB 의 내용을 차례로 5 개만 읽어오기

DB닫기

# ex11_2.outName=tcpmux, Port=256Name=echo, Port=1792Name=echo, Port=1792Name=discard, Port=2304Name=discard, Port=2304

socket 라이브러리를 지정해서 컴파일해야 한다 .# gcc –o ex11_2.out ex11_2.c -lsocket

Page 14: 소켓 프로그래밍 기초

14/42

포트 번호 (2) 서비스명으로 정보 검색 : getservbyname(3)

name : 검색할 포트명 proto : tcp 또는 udp 또는 NULL

포트 번호로 정보 검색 : getservbyport(3)

proto : tcp 또는 udp 또는 NULL

#include <netdb.h>struct servent *getservbyname(const char *name, const char *proto);

#include <netdb.h>struct servent *getservbyport(int port, const char *proto);

Page 15: 소켓 프로그래밍 기초

15/42

소켓 프로그래밍 기초 (1) 소켓의 종류

AF_UNIX : 유닉스 도메인 소켓 ( 시스템 내부 프로세스간 통신 ) AF_INET : 인터넷 소켓 ( 네트워크를 이용한 통신 ) <sys/socket.h> 에 주소 패밀리명이 정의되어 있음

소켓의 통신 방식 – 사용하는 전송 프로토콜에 따라 구분 SOCK_STREAM : TCP 사용 SOCK_DGRAM : UDP 사용

AF_UNIX

AF_UNIX

AF_INET

AF_INET

SOCK_STREAM

SOCK_DGRAM

SOCK_STREAM

SOCK_DGRAM

소켓의 종류 및 전송방식에 따른 통신 유형 :

Page 16: 소켓 프로그래밍 기초

16/42

소켓 프로그래밍 기초 (2) 소켓 주소 구조체

유닉스 도메인 소켓의 주소 구조체

인터넷 소켓의 주소 구조체

struct sockaddr_un { sa_family_t sun_famyly; char sun_path[108]};

• sun_family : AF_UNIX• sun_path : 통신에 사용할 파일의 경로명

struct sockaddr_in { sa_family_t sin_family; in_port_t sin_port; struct in_addr sin_addr;};

struct in_addr { in_addr_t s_addr;};

Page 17: 소켓 프로그래밍 기초

17/42

소켓 프로그래밍 기초 (3) 바이트 순서 (Byte Ordering) 함수

컴퓨터에서 정수를 저장하는 방식 빅엔디안 (Big-endian)• 메모리의 낮은 주소에 정수의 첫 바이트를 위치 • 모토로라 , 썬

리틀엔디안 (Little-endian)• 메모리의 높은 주소에 정수의 첫 바이트를 위치• 인텔 , ARM Core

TCP/IP 네트워크에서 바이트 순서 표준 : 빅엔디안• 송수신하는 호스트 간에 바이트 순서가 다를 수 있어 TCP/IP 프로토콜을 이용하여

전송하는 데이터의 바이트 순서는 빅엔디안으로 통일하도록 함 . 호스트 바이트 순서 (HBO) : 시스템에서 사용하는 바이트 순서 네트워크 바이트 순서 (NBO) : 네트워크에서 사용하는 바이트 순서

0x1234

12 34100 101

34 12100 101

Page 18: 소켓 프로그래밍 기초

18/42

소켓 프로그래밍 기초 (4) 바이트 순서 함수

htonl :32 비트 HBO 를 32 비트 NBO 로 변환 htons : 16 비트 HBO 를 16 비트 NBO 로 변환 ntohl : 32 비트 NBO 를 32 비트 HBO 로 변환 ntohs : 16 비트 NBO 를 16 비트 HBO 로 변환

#include <sys/types.h>#include <netinet/in.h>#include <inttypes.h>uint32_t htonl(unit32_t hostlong);uint16_t htons(unit16_t hostshort);uint32_t ntohl(unit32_t netlong);uint16_t ntohs(unit16_t netshort);

Page 19: 소켓 프로그래밍 기초

19/42

[ 예제 11-3] NBO 를 HBO 로 변환하기

01 #include <netdb.h>02 #include <stdio.h>03 04 int main(void) {05 struct servent *port;06 int n;07 08 setservent(0);09 10 for (n = 0; n < 5; n++) {11 port = getservent();12 printf("Name=%s, Port=%d\n", port->s_name, ntohs(port->s_port));13 }14 15 endservent();16 17 return 0;18 }

# ex11_3.outName=tcpmux, Port=1Name=echo, Port=7Name=echo, Port=7Name=discard, Port=9Name=discard, Port=9

NBO 를 HBO 로 변환하기 위한 함수 호출

ex11_3.c

Page 20: 소켓 프로그래밍 기초

20/42

[ 예제 11-4] HBO 를 NBO 로 변환하기 ex11_4.c01 #include <netdb.h>02 #include <stdio.h>03 04 int main(void) {05 struct servent *port;06 07 port = getservbyname("telnet", "tcp");08 printf("Name=%s, Port=%d\n", port->s_name, ntohs(port->s_port));09 10 port = getservbyport(htons(21), "tcp");11 printf("Name=%s, Port=%d\n", port->s_name, ntohs(port->s_port));12 13 return 0;14 }

# ex11_4.outName=telnet, Port=23Name=ftp, Port=21

이름으로 서비스 포트번호 검색

HBO 를 NBO 로 변환하여 포트번호 검색

Page 21: 소켓 프로그래밍 기초

21/42

IP 주소 변환 함수 IP 주소의 형태

192.168.10.1 과 같이 점 (.) 으로 구분된 형태 시스템 내부 저장 방법 : 이진값으로 바꿔서 저장 외부적 사용 형태 : 문자열로 사용

문자열 행태의 IP 주소를 숫자형태로 변환 : inet_addr(3)

구조체 형태의 IP 주소를 문자열 형태로 변환 : inet_ntoa(3)

#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>in_addr_t inet_addr(const char *cp);

#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>char *inet_ntoa(const struct in_addr in);

Page 22: 소켓 프로그래밍 기초

22/42

[ 예제 11-5] IP 주소 변환하기...09 int main(void) {10 in_addr_t addr;11 struct hostent *hp;12 struct in_addr in;13 14 if ((addr = inet_addr("218.237.65.4")) == (in_addr_t)-1) {15 printf("Error : inet_addr(218.237.65.4\n");16 exit(1);17 }18 19 hp = gethostbyaddr((char *)&addr, 4, AF_INET);20 if (hp == NULL) {21 (void) printf("Host information not found\n");22 exit(2);23 }24 25 printf("Name=%s\n", hp->h_name);26 27 (void) memcpy(&in.s_addr, *hp->h_addr_list, sizeof (in.s_addr)); 0;28 printf("IP=%s\n", inet_ntoa(in));29 30 return 0;31 }

ex11_5.c

문자열 행태를 이진형태로 변환

주소로 호스트명 검색

구조체 형태에서 문자열로 변환하여 출력

# gcc -o ex11_5.out ex11_5.c -lsocket -lnsl# ex11_5.outName=www.hanb.co.krIP=218.237.65.4

Page 23: 소켓 프로그래밍 기초

23/42

소켓 인터페이스 함수 (1) 소켓 (Socket)

소켓 인터페이스를 지원하는 특수 파일 소켓을 생성하고 소켓 인터페이스 함수를 이용하여 다양한 데이터 통신을 구현 소켓을 통한 데이터 통신은 서버 - 클라이언트 방식으로 전송• 데이터 통신에 참여하는 소켓은 하나는 서버 소켓 , 그리고 다른 것은 클라이언트 소켓이

되어 데이터를 송수신 소켓 인터페이스 함수

socket : 소켓 파일기술자 생성 bind : 소켓 파일기술자를 지정된 IP 주소 /포트번호와 결합 (bind) listen : 클라이언트의 접속 요청 대기 accept : 클라이언트의 접속 허용 connect : 클라이언트가 서버에 접속 요청 recv : 데이터 수신 (SOCK_STREAM) send : 데이터 송신 (SOCK_STREAM) recvfrom : 데이터 수신 (SOCK_DGRAM) sendto : 데이터 송신 (SOCK_DGRAM) close : 소켓 파일기술자 종료

Only server socket

Only client socket

Page 24: 소켓 프로그래밍 기초

24/42

소켓 인터페이스 함수 (2) 소켓 생성하기 : socket(2)

domain : 소켓 종류 (AF_UNIX, AF_INET) type : 통신방식 (TCP:SOCK_STREAM, UDP:SOCK_DGRAM) protocol : 소켓에 이용할 프로토콜

#include <sys/types.h>#include <sys/socket.h>

int socket(int domain, int type, int protocol);

int sd;sd = socket(AF_INET, SOCK_STREAM, 0);

Page 25: 소켓 프로그래밍 기초

25/42

소켓 인터페이스 함수 (3) 소켓에 이름 지정하기 ( 주소 바인딩 ): bind(3)

name : 소켓의 이름을 표현하는 구조체

#include <sys/types.h>#include <sys/socket.h>

int bind(int s, const struct sockaddr *name, int namelen);

int sd;struct sockaddr_in sin;

memset((char *)&sin, '\0', sizeof(sin));sin.sin_family = AF_INET;sin.sin_port = htons(9000);sin.sin_addr.s_addr = inet_addr("192.168.100.1");memset(&(sin.sin_zero), 0, 8);

bind(sd, (struct sockaddr *)&sin, sizeof(struct sockaddr));

Page 26: 소켓 프로그래밍 기초

26/42

소켓 인터페이스 함수 (4) 클라이언트 연결 기다리기 : listen(3)

backlog : 최대 허용 클라이언트 수

소켓 s 에서 클라이언트의 연결 요청을 받을 준비가 되었음을 알림 SOCK_STREAM 방식으로 통신할 때만 필요

예 :

#include <sys/types.h>#include <sys/socket.h>

int listen(int s, int backlog);

listen(sd, 10);

Page 27: 소켓 프로그래밍 기초

27/42

소켓 인터페이스 함수 (5) 연결 요청 수락하기 : accept(3)

addr: 접속을 요청한 클라이언트의 IP 정보

서버가 클라이언트의 연결 요청을 수락함 .• 클라이언트 요청이 들어올 때까지 대기함 (blocked)

클라이언트 요청이 들어오면 새로운 소켓 기술자를 생성하여 반환• 기존 소켓 기술자 s 는 클라이언트의 추가 연결 요청을 대기함

#include <sys/types.h>#include <sys/socket.h>

int accept(int s, struct sockaddr *addr, socklen_t *addrlen);

int sd, new_sd;struct sockaddr_in sin, clisin;new_sd = accept(sd, &clisin, &sizeof(struct sockaddr_in));

Page 28: 소켓 프로그래밍 기초

28/42

소켓 인터페이스 함수 (6) 서버와 연결하기 : connect(3)

name : 접속하려는 서버의 IP 정보

클라이언트가 서버에 연결을 요청할 때에 사용 SOCK_STREAM 통신 방식에서만 사용

#include <sys/types.h>#include <sys/socket.h>

int connect(int s, const struct sockaddr *name, int namelen);

int sd;struct sockaddr_in sin;

memset((char *)&sin, '\0', sizeof(sin));sin.sin_family = AF_INET;sin.sin_port = htons(9000);sin.sin_addr.s_addr = inet_addr("192.168.100.1");memset(&(sin.sin_zero), 0, 8);

connect(sd, (struct sockaddr *)&sin, sizeof(struct sockaddr));

Page 29: 소켓 프로그래밍 기초

29/42

소켓 인터페이스 함수 (7) 데이터 보내기 : send(3)

소켓 s 를 통해 길이가 len 인 메시지 msg 를 flag 가 지정하는 방법으로 전송 flags 값• MSG_OOB : 영역 밖의 데이터 (Out-Of-Band Data) 지정• MSG_DONTROUTE : 데이터 라우팅 설정을 해제

#include <sys/types.h>#include <sys/socket.h>

ssize_t send(int s, const void *msg, size_t len, int flags);

char *msg = "Send Test\n";int len = strlen(msg) + 1;if (send(sd, msg, len, 0) == -1) { perror("send"); exit(1);}

Page 30: 소켓 프로그래밍 기초

30/42

소켓 인터페이스 함수 (8) 데이터 받기 : recv(3)

소켓 s 를 통해 수신되는 데이터를 길이가 len 인 buf 에 저장 flags 값 -sned() 함수와 동일

#include <sys/types.h>#include <sys/socket.h>ssize_t recv(int s, void *buf, size_t len, int flags);

char buf[80];int len, rlen;if ((rlen = recv(sd, buf, len, 0)) == -1) { perror("recv"); exit(1);}

Page 31: 소켓 프로그래밍 기초

31/42

소켓 인터페이스 함수 (9) UDP 데이터 보내기 : sendto(3)

to : 메시지를 받을 호스트의 주소 SOCK_DGRAM 통신 방식을 데이터를 전송할 때에 사용 , 별도 연결 과정이

필요 없음

#include <sys/types.h>#include <sys/socket.h>ssize_t sendto(int s, const void *msg, size_t len, int flags,

const struct sockaddr *to, int tolen);

char *msg = "Send Test\n";int len = strlen(msg) + 1;struct sockaddr_in sin;int size = sizeof(struct sockaddr_in);memset((char *)&sin, '\0', sizeof(sin));sin.sin_family = AF_INET;sin.sin_port = htons(9000);sin.sin_addr.s_addr = inet_addr("192.168.10.1");memset(&(sin.sin_zero), 0, 8);if (sendto(sd, msg, len, 0, (struct sockaddr *)&sin, size) == -1) { perror("sendto"); exit(1);}

Page 32: 소켓 프로그래밍 기초

32/42

소켓 인터페이스 함수 (10) UDP 데이터 받기 : recvfrom(3)

from : 메시지를 보내는 호스트의 주소 SOCK_DGRAM 방식을 송신되는 데이터를 수신할 때에 사용 수신된 데이터와 송신자 주소를 읽어오고 , 수신된 데이터의 수를 반환

#include <sys/types.h>#include <sys/socket.h>ssize_t recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, int *fromlen);

char buf[80];int len, size;struct sockaddr_in sin;if (recvfrom(sd, buf, len, 0, (struct sockaddr *)&sin, &size) == -1) { perror("recvfrom"); exit(1);}

Page 33: 소켓 프로그래밍 기초

33/42

소켓 함수의 호출 순서

Page 34: 소켓 프로그래밍 기초

34/42

[ 예제 11-6] (1) 유닉스 도메인 소켓 ( 서버 ) ex11_6s.c

...08 #define SOCKET_NAME "hbsocket"09 10 int main(void) {11 char buf[256];12 struct sockaddr_un ser, cli;13 int sd, nsd, len, clen;14 15 if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {16 perror("socket");17 exit(1);18 }19 20 memset((char *)&ser, 0, sizeof(struct sockaddr_un));21 ser.sun_family = AF_UNIX;22 strcpy(ser.sun_path, SOCKET_NAME);23 len = sizeof(ser.sun_family) + strlen(ser.sun_path);24

소켓 이름

유닉스 도메인 소켓 생성

소켓구조체에 값 지정

Page 35: 소켓 프로그래밍 기초

35/42

[ 예제 11-6] (1) 유닉스 도메인 소켓 ( 서버 ) ex11_6s.c

25 if (bind(sd, (struct sockaddr *)&ser, len)) {26 perror("bind");27 exit(1);28 }29 30 if (listen(sd, 5) < 0) {31 perror("listen");32 exit(1);33 }34 35 printf("Waiting ...\n");36 if ((nsd = accept(sd, (struct sockaddr *)&cli, &clen)) == -1) {37 perror("accept");38 exit(1);39 }40 41 if (recv(nsd, buf, sizeof(buf), 0) == -1) {42 perror("recv");43 exit(1);44}46 printf("Received Message: %s\n", buf);47 close(nsd);48 close(sd);49 50 return 0;51 }

소켓기술자와 소켓 주소 구조체 연결

클라이언트 접속 대기

클라이언트 접속 수용

클라이언트가 보낸 메시지 읽기

Page 36: 소켓 프로그래밍 기초

36/42

[ 예제 11-6] (2) 유닉스 도메인 소켓 ( 클라이언트 )...08 #define SOCKET_NAME "hbsocket"09 10 int main(void) {11 int sd, len;12 char buf[256];13 struct sockaddr_un ser;14 15 if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {16 perror("socket");17 exit(1);18 }19 20 memset((char *)&ser, '\0', sizeof(ser));21 ser.sun_family = AF_UNIX;22 strcpy(ser.sun_path, SOCKET_NAME);23 len = sizeof(ser.sun_family) + strlen(ser.sun_path);24 25 if (connect(sd, (struct sockaddr *)&ser, len) < 0) {26 perror("bind");27 exit(1);28 }

소켓 주소 구조체에 값 지정

소켓 생성

서버에 연결 요청

ex11_6c.c

Page 37: 소켓 프로그래밍 기초

37/42

[ 예제 11-6] (2) 유닉스 도메인 소켓 ( 클라이언트 )30 strcpy(buf, "Unix Domain Socket Test Message");31 if (send(sd, buf, sizeof(buf), 0) == -1) {32 perror("send");33 exit(1);34 }35 close(sd);36 37 return 0;38 }

서버에 데이터 전송

# ex11_6s.outWaiting ...Received Message: Unix Domain Socket Test Message

# ex11_6c.out#

서버

클라이언트

ex11_6c.c

Page 38: 소켓 프로그래밍 기초

38/42

[ 예제 11-7] (1) 인터넷 소켓 ( 서버 ) ex11_7s.c

...09 #define PORTNUM 900010 11 int main(void) {12 char buf[256];13 struct sockaddr_in sin, cli;14 int sd, ns, clientlen = sizeof(cli);15 16 if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {17 perror("socket");18 exit(1);19 }20 21 memset((char *)&sin, '\0', sizeof(sin));22 sin.sin_family = AF_INET;23 sin.sin_port = htons(PORTNUM);24 sin.sin_addr.s_addr = inet_addr("192.168.162.133");25 26 if (bind(sd, (struct sockaddr *)&sin, sizeof(sin))) {27 perror("bind");28 exit(1);29 }

포트번호

소켓 생성

소켓 주소 구조체 생성

소켓기술자와 소켓 주소 구조체 연결

Page 39: 소켓 프로그래밍 기초

39/42

[ 예제 11-7] (1) 인터넷 소켓 ( 서버 ) ex11_7s.c

31 if (listen(sd, 5)) {32 perror("listen");33 exit(1);34 }35 36 if ((ns = accept(sd, (struct sockaddr *)&cli, &clientlen))==-1){37 perror("accept");38 exit(1);39 }40 41 sprintf(buf, "Your IP address is %s", inet_ntoa(cli.sin_addr));42 if (send(ns, buf, strlen(buf) + 1, 0) == -1) {43 perror("send");44 exit(1);45 }46 close(ns);47 close(sd);48 49 return 0;50 }

클라이언트와 연결

클라이언트 접속요청 대기

클라이언트로 데이터 보내기

Page 40: 소켓 프로그래밍 기초

40/42

[ 예제 11-7] (2) 인터넷 소켓 ( 클라이언트 ) ex11_7c.c

...09 #define PORTNUM 900010 11 int main(void) {12 int sd;13 char buf[256];14 struct sockaddr_in sin;15 16 if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {17 perror("socket");18 exit(1);19 }20 21 memset((char *)&sin, '\0', sizeof(sin));22 sin.sin_family = AF_INET;23 sin.sin_port = htons(PORTNUM);24 sin.sin_addr.s_addr = inet_addr("192.168.162.133");25

포트번호

소켓 생성

소켓 주소 구조체 생성

Page 41: 소켓 프로그래밍 기초

41/42

[ 예제 11-7] (2) 인터넷 소켓 ( 클라이언트 ) ex11_7c.c

26 if (connect(sd, (struct sockaddr *)&sin, sizeof(sin))) {27 perror("connect");28 exit(1);29 }30 31 if (recv(sd, buf, sizeof(buf), 0) == -1) {32 perror("recv");33 exit(1);34 }35 close(sd);36 printf("From Server : %s\n", buf);37 38 return 0;39 }

서버에 접속 요청

서버가 보낸 데이터 읽기

# gcc -o ex11_7s ex11_7-inet-s.c -lsocket -lnsl# gcc -o ex11_7c ex11_7-inet-c.c -lsocket -lnsl

# ex11_7s.out

# ex11_7c.outFrom Server : Your IP address is 192.168.162.131

서버

클라이언트

Page 42: 소켓 프로그래밍 기초

유닉스 시스템 프로그래밍