Linux Socket Programming - Connection-Oriented Protocols for Clients – S/W System Lab. 장 재 필 한남대학교 컴퓨터공학과 컴퓨터 네트워크 실험실
목 차 통신수단의 재 검토 인터넷 서비스 /etc/protocols 파일의 고찰 TCP/IP 클라이언트 프로그램 작성 SOCK_DGRAM 소켓의 활용
통신수단의 재 검토 비연결형 프로토콜 비연결 데이터 패킷을 만들고 목적지 IP헤더를 붙여 전송 순서가 보장되지 않음 응답 패킷을 기다림 (일정시간 미수신시 재전송) UDP/IP(DNS Protocol, 인터넷 방송), 데이터그램 소켓
통신수단의 재 검토 - 계속 연결형 프로토콜 서로의 연결이 선행(서로간의 주소 재지정 불필요) 전송은 보낸 순서대로 이루어 진다 에러검출, 데이터 손실, 플로우등에 대처 신뢰성 있는 전송 보장 TCP/IP(FTP, SMTP, NNTP, HTTP), X.25, 스트림소켓 Telephone Network
통신수단의 재 검토 TCP/IP의 손실 패킷 제어 TCP/IP의 중복 패킷 제어 TCP/IP의 Sequencing 관리
통신수단의 재 검토 - 계속 TCP/IP의 세그먼트 구조 8 16 24 Source Port Destination Port 8 16 24 Source Port Destination Port Sequence Number Acknowledgment HLEN 예약 Control Flag Window Checksum Urgent Pointer Option Padding Data
통신수단의 재 검토 – 계속 Sequence Number : 송신 데이터 스트림의 바이트 번호 Acknowledgment Number : 다음에 수신할 데이터 스트림 의 번호 HLEN : 세그먼트의 총길이 Reserved : 예약, 모두 0으로 Setting Control Flag : 세그먼트의 종류 (목적과 내용 등) 를 표시 Window : 수신측에서의 현재 자신의 가용 버퍼 크기 Checksum : IP 헤더 일부 및 세그먼트의 무결성 검사 Urgent Pointer : 긴급 데이타의 범위(종료위치)를 표시 padding : 헤더를 32비트 배수 크기로 만들기 위해 붙인다
통신수단의 재 검토 – 계속 Control Flag의 종류 URG - Urgent Pointer 필드가 유효함을 표시 ACK - Acknowledgement 필드가 유효함을 표시 PSH 데이터 스트림 Push 요구(세그먼트를 만들지 않고 처리) 인터럽트 신호의 송신 등에 사용 RST - 연결의 비정상적인 종료 요구 SYN - 처음 연결 설정 요구 FIN - 연결 해제 요구
인터넷 서비스 the /etc/services File 검토 서비스의 이름 서비스 포트 번호 사용되는 프로토콜 Alias정보
인터넷 서비스 # # @(#)services 1.16 90/01/03 SMI # Network services, Internet style # This file is never consulted when the NIS are running tcpmux 1/tcp # rfc-1078 Echo 7/tcp echo 7/udp ... ftp-data 20/tcp ftp 21/tcp telnet 23/tcp login 513/tcp
인터넷 서비스 - 계속 Using Function getservent(3) /etc/services File에서 참조 Service-name, Port-Number, Protocol, alias를 검색 Error발생시 Null값 반환 Synopsis #include <netdb.h> Struct servent *getservent(void);
alias가 있다면 모두 출력(내부 loop) 인터넷 서비스 - 계속 예제 7.2 초기화 Yes Entry = end-of-file No 종료 Getservent(3) 호출 서비스 이름, 포트, 프로토콜 출력 alias가 있다면 모두 출력(내부 loop)
인터넷 서비스 - 계속 초기화 Loop int x; struct servent *sp; errno = 0; if ( !(sp = getservent()) ) break;
인터넷 서비스 - 계속 출력 printf("%s:\n" "\tPort: %d\n" "\tProtocol: %s\n" "\tAliases: ", sp->s_name, ntohs(sp->s_port), sp->s_proto);
인터넷 서비스 - 계속 Aliases 출력 종료 for ( x=0; sp->s_aliases[x] != NULL; ++x ) printf("%s ",sp->s_aliases[x]); 종료 if ( errno != 0 && errno != ENOENT ) /* For RH-6.0 */ fprintf(stderr, "%s: getservent(3) %d\n", strerror(errno),errno);
인터넷 서비스 - 계속 Using Function setservent(3) Function /etc/services File에서 참조 Service-name, Port-Number, Protocol, alias를 재설정 Synopsis #include <netdb.h> void setservent (int stayopen);
인터넷 서비스 - 계속 Using the endservent(3) Function /etc/services File 종료 Getservent(3)함수 종료 Synopsis #include <netdb.h> void endservent (void);
인터넷 서비스 - 계속 Looking Up a Service by Name and Protocol getservbyname(3)함수 현재 사용하는 인터넷 서비스를 이름과 프로토콜로 알수있다. Synopsis #include <netdb.h> struct servent *getservbyname(const char *name, const char *proto);
인터넷 서비스 - 계속 Looking Up a Service by Port and Protocol getservbyport(3)함수 Synopsis #include <netdb.h> struct servent *getservbyport(int port, const char *proto);
/etc/protocols파일의 참고 getprotoent(3) /etc/protocols 파일의 엔트리 반환 Synopsis #include <netdb.h> struct protoent *getprotoent(void);
/etc/protocols파일의 참고-계속 예제 7.5 초기화 Yes Entry = end-of-file No 종료 Getprotoent(3) 호출 프로토콜 이름, 프로토콜 번호 출력 alias가 있다면 모두 출력(내부 loop)
/etc/protocols파일의 참고-계속 초기화 int x; struct protoent *pp; errno = 0; Loop if ( !(pp = getprotoent()) ) break;
/etc/protocols파일의 참고-계속 출력 printf("%s:\n" "\tProtocol: %d\n" "\tAliases: ", pp->p_name, pp-p_proto);
/etc/protocols파일의 참고-계속 Aliases 출력 for ( x=0; pp->p_aliases[x] != NULL; ++x ) printf("%s ",pp->p_aliases[x]); 종료 if ( errno != 0 && errno != ENOENT ) /* For RH-6.0 */ fprintf(stderr, "%s: getprotoent(3) %d\n", strerror(errno),errno);
/etc/protocols파일의 참고-계속 Using the setprotoent(3) Function Getprotoent(3)함수를 되돌린다. Synopsis #include <netdb.h> void setprotoent(int stayopen);
/etc/protocols파일의 참고-계속 Using the endprotoent(3) Function /etc/protocols파일의 종료 Synopsis #include <netdb.h> void setprotoent(int stayopen);
/etc/protocols파일의 참고-계속 Looking Up a Protocol by Name Getprotobyname(3)함수 Synopsis #include <netdb.h> struct protoent *getprotobyname(const char *name)
/etc/protocols파일의 참고-계속 Looking Up a Protocol by Number Getprotobynnumber(3)함수 Synopsis #include <netdb.h> struct protoent *getprotobynumber(int proto)
TCP/IP 클라이언트 프로그램 작성 소켓생성 선택적 소켓 바인딩 리모트 소켓으로 접속 읽기와 쓰기를 통한 통신 소켓 끄기와 닫기
TCP/IP 클라이언트 프로그램 작성-계속 Introducing the connect(2) Function 접속을 위한 connect(2)함수 호출 #include <sys/types.h> #include <sys/socket.h> Connet(2) 함수의 3가지 변수 Sockfd – connect()호출시 반환되는 소켓파일 작성자 Serv_addr – 접속할 서버의 주소 Addrlen – 주소 바이트의 길이
TCP/IP 클라이언트 프로그램 작성-계속 Preparing to Write the Client Program grep daytime /etc/services daytime 13/tcp daytime 13/udp telnet 127.0.0.1 13 Trying 127.0.0.1 . . . Connected to 127.0.0.1. Escape character is ‘^]’. Tue Aug 17 17:59:30 1999
TCP/IP 클라이언트 프로그램 작성-계속 telnet 127.0.0.1 13 Trying 127.0.0.1 . . . telnet: Unable to connect to remote host: Connection refused Grep day time /etc/inetd.conf # Echo, discard, daytime, and chargen are used #daytime stream tcp nowait root internal #daytime dgram udp wait root internal $
TCP/IP 클라이언트 프로그램 작성-계속 tcp가 포함되어있는 daytime 엔트리를 위한 #character를 지움 Grep day time /etc/inetd.conf # Echo, discard, daytime, and chargen are used daytime stream tcp nowait root internal #daytime dgram udp wait root internal $
TCP/IP 클라이언트 프로그램 작성-계속 $ Su – Password: #ps ax | grep inetd 313 ? S 0:00 inetd 828 pts/1 S 0:00 grep inetd #kill –1 313 # /etc/inetd.conf파일을 바꾸고 난 뒤 inetd 데몬에게 다시 읽기와 바뀐 파일의 재실행
TCP/IP 클라이언트 프로그램 작성-계속 예제 7.2 초기화 주소 지정 Tcp 프로토콜에 daytime 확인 소켓생성과 접속 서버의 날짜, 시간을 자신의 소켓으로 전송 터미널 세션에 날짜, 시간을 보고 소켓 종료
TCP/IP 클라이언트 프로그램 작성-계속 초기화 int main(int argc,char **argv) { int z; char *srvr_addr = NULL; struct sockaddr_in adr_srvr;/* AF_INET */ int len_inet; /* length */ int s; /* Socket */ struct servent *sp; /* Service entry */ char dtbuf[128]; /* Date/Time info */
TCP/IP 클라이언트 프로그램 작성-계속 주소지정 if ( argc >= 2 ) { /* Addr on cmdline: */ srvr_addr = argv[1]; } else { /* Use default address: */ srvr_addr = "127.0.0.1"; }
TCP/IP 클라이언트 프로그램 작성-계속 Tcp프로토콜에 daytime확인 sp = getservbyname("daytime","tcp"); if ( !sp ) { fputs("Unknown service: daytime tcp\n", stderr); exit(1); }
TCP/IP 클라이언트 프로그램 작성-계속 소켓생성과 접속 s = socket(PF_INET,SOCK_STREAM,0); if ( s == -1 ) bail("socket()"); z = connect(s,&adr_srvr,len_inet); if ( z == -1 ) bail("connect(2)");
TCP/IP 클라이언트 프로그램 작성-계속 자신의 소켓으로 전송 s = socket(PF_INET,SOCK_STREAM,0); if ( s == -1 ) bail("socket()"); z = read(s,&dtbuf,sizeof dtbuf-1); if ( z == -1 ) bail("read(2)");
TCP/IP 클라이언트 프로그램 작성-계속 날짜와 시간 보고 dtbuf[z] = 0; /* null terminate string */ printf("Date & Time is: %s\n",dtbuf);
Using connect(2) on SOCK_DGRAM Sockets 함수의 생성 시기 장점 bind(2) 함수 호출 후 소켓이 데이터그램을 읽거나 쓰기 이전 장점 한곳의 서버에서 다량의 정보를 받을때 Read()와 write()함수 호출로 프로그램 간단화
요약