10. 소켓개요 TCP 클라이언트 / 서버프로그래밍절차 오드로이드 I/O 소켓프로그램예 순천향대학교컴퓨터공학과이상정 1 소켓 (Socket) 운영체제복습 소켓 (socket) 은통신의극점 (endpoint) 을정의 소켓은 IP 주소와포트번호두가지를접합 (concatenate) 해서구별 두프로세스의네트워크통신에각각하나씩두개의소켓이필요 순천향대학교컴퓨터공학과 2
소켓 (Socket) 네트워크복습 프로세스는소켓 (socket) 을통해네트워크로메시지를송수신 소켓은호스트의애플리케이션계층과트랜스포트계층간의인터페이스 프로세스는집 (house), 소켓은출입구 (door) 에비유 송신프로세스는출입구 ( 소켓 ) 바깥네트워크로메시지를밀어냄 소켓은애플리케이션과네트워크사이의 API(Application Programming Interface) 순천향대학교컴퓨터공학과 3 소켓개요 순천향대학교컴퓨터공학과이상정 4
소켓의정의 소켓 (socket) 은 TCP/IP 를이용하는 API 1982년 BSD(Berkeley Software Distribution) 유닉스 4.1에서처음소개 윈도우소켓 ( 윈속 ), 자바소켓 BSD 소켓과호환성 프로그램코드의호환성이아니라서로통신을할수있는통신프로토콜의호환성 소켓은소프트웨어로작성된통신접속점 응용프로그램은소켓을통하여통신망으로 IP 패킷을송수신 순천향대학교컴퓨터공학과이상정 5 소켓인터페이스위치 순천향대학교컴퓨터공학과이상정 6
소켓번호 리눅스파일기술자 (file descriptor) 파일을새로열면 (open) int 타입의파일기술자를리턴 프로그램에서이파일을액세스할때해당파일기술자를사용 파일기술자는기술자테이블 (descriptor table) 의 index 번호 소켓기술자 (socket descriptor) 소켓을개설하면파일기술자와똑같은기능을하는소켓기술자가리턴 응용프로그램에서이소켓을통하여목적지호스트와패킷을송수신할때이소켓기술자 ( 소켓번호 ) 를사용 리눅스에서는파일기술자와소켓기술자가같은기술자테이블사용 순천향대학교컴퓨터공학과이상정 7 소켓, 파일기술자테이블 순천향대학교컴퓨터공학과이상정 8
소켓번호, 포트번호, IP 주소의관계 순천향대학교컴퓨터공학과이상정 9 서비스와포트번호 /etc/services 파일에응용서비스와대응되는포트번호가기술 $ more /etc/services 순천향대학교컴퓨터공학과이상정 10
소켓의생성 (1) 소켓을이용하는네트워크프로그램에서상대방세션과 IP 패킷을주고받기위해서는다음정보를기술 1. 통신에사용할프로토콜 (TCP 또는 UDP) 2. 자신의 IP 주소 3. 자신의포트번호 4. 상대방의 IP 주소 5. 상대방의포트번호 순천향대학교컴퓨터공학과이상정 11 소켓의생성 (2) #include <sys/socket.h> int socket( int domain, /* 프로토콜체계 */ int type, /* 서비스타입 */ int protocol /* 소켓에서사용할프로토콜 */ ); domain : PF_INET ( 인터넷프로토콜체계사용 ) PF_INET6 (IPv6 프로토콜체계사용 ) PF_UNIX ( 유닉스방식의프로토콜체계사용 ) PF_NS (XEROX 네트워크시스템의프로토콜체계사용 ) type : SOCK_STREAM (TCP 즉, 스트림방식의소켓생성 ) SOCK_DGRAM (UDP 즉, 데이터그램방식의소켓생성 ) SOCK_RAW (raw 모드의소켓생성 ) protocol은구체적인프로토콜을선택할때사용하는데대부분의응용프로그램에서는 0으로지정 순천향대학교컴퓨터공학과이상정 12
소켓생성예 socket() 시스템호출사용예 두개의소켓과파일을생성 소켓번호와파일기술자를출력 $mkdir~/socket $cdsocket $ gedit open_socket.c c $ cc o open_socket open_socket.c $./open_socket 순천향대학교컴퓨터공학과이상정 13 임베디드 // open_socket.c 소프트웨어 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> /* 소켓시스템호출에필요한상수선언 */ #include <sys/stat.h> /* 파일의상태에대한데이터선언 */ #include <sys/socket.h> /* 소켓시스템호출선언 */ #include <fcntl.h> /* open에필요한 flag 선언 */ #include <unistd.h> int main() { int fd1, fd2, sd1, sd2; /* 파일및소켓번호 */ fd1 = open("/etc/passwd", O_RDONLY, 0); /* 파일열기 */ printf("/etc/passwd's file descriptor = %d n", fd1); sd1 = socket(pf_inet, SOCK_STREAM, STREAM 0); /* 스트림형소켓열기 */ printf("stream socket descriptor = %d n", sd1); sd2 = socket(pf_inet, SOCK_DGRAM, 0); /* 데이터그램형소켓열기 */ printf("datagram socket descriptor = %d n", sd2); fd2 = open("/etc/hosts", O_RDONLY, 0); /* 또다른파일열기 */ printf("/etc/hosts's file descriptor = %d n", fd2); /* 파일및소켓닫기 */ close(fd2); close(fd1); close(sd2); close(sd1); 순천향대학교 컴퓨터공학과이상정 14
헤더파일 네트워크프로그램에서자주사용되는헤더파일 /usr/include stdio.h, string.h, time.h, netdb.h, errno.h, fcntl.h, signal.h C 언어에서기본적으로사용되는헤더파일이있다. /usr/include/sys socket.h, types.h, ipc.h, msg.h, proc.h, sem.h, stats.h 등 시스템과관련된헤더파일 /usr/include/netinet in.h, arp.h, igmp.h, ip.h, tcp.h, udp.h 등 인터넷관련헤더파일 순천향대학교컴퓨터공학과이상정 15 소켓주소구조체 (1) 통신객체 ( 클라이언트또는서버 ) 의구체적인주소를표현하기위해서는다음을지정해야함 주소체계 (address family) IP 주소 포트번호 위의세가지정보를소켓주소 (socket address) 라고하며소켓주소를담을구조체 sockaddr 을다음과같이정의 struct sockaddr { ; ushortsa u_short sa_family; /* 주소체계 */ char sa_data[14]; /* 주소 */ 순천향대학교컴퓨터공학과이상정 16
소켓주소구조체 (2) sockaddr 소켓주소구조체에 IP 주소, 포트번호등을직접쓰거나읽기가불편 인터넷프로그래밍에서는 4바이트의 IP주소와 2바이트의포트번호를구분하여액세스할수있는인터넷전용소켓주소구조체sockaddr_in을주로사용 struct in_addr { u_long s_addr; /* 32비트의 IP 주소를저장할구조체 */ ; struct sockaddr_in { short sin_family; /* 주소체계 */ u_short sin_port; /* 16비트포트번호 */ struct in_addr sin_addr; /* 32비트 IP 주소 */ char sin_zero[8]; /* 전체크기를 16 바이트로맞추기위한 dummy */ ; 순천향대학교컴퓨터공학과이상정 17 소켓주소구조체 (3) 주소체계 (sin_family) 값 sin_family : AF_INET ( 인터넷주소체계 ) AF_UNIX ( 유닉스파일주소체계 ) AF_NS (XEROX 주소체계 ) 소켓을개설할때프로토콜을 PF_INET 즉, 인터넷으로지정한경우에는주소체계로 AF_INET만을사용 두상수 PF_INET 과 AF_INET 의값은모두 2 로같으므로편의상이두표현을혼용 순천향대학교컴퓨터공학과이상정 18
IP 주소변환 #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> const char *inet_ntop(int af, const void *src, char *dst, size_t cnt ); /* IP 주소 (4 바이트정수 ) -> dotted d decimal( 문자열 ) */ int inet_pton(int af, const char *src, void *dst); /* dotted decimal( 문자열 ) -> IP 주소 (4 바이트정수 ) */ 순천향대학교컴퓨터공학과이상정 19 IP 주소변환예 dotted decimal 로표현된주소 ( 예 : 192.203.144.11) 203 144 11) 를명령 행인수로입력 4바이트의 IP 주소 (0xb90cbc0) 로화면에출력 IP 주소를다시 dotted decimal 주소로출력 $cd~/socket $ gedit ascii_ip.c i $ cc o ascii_ip ascii_ip.c $./ascii_ip 192.168.0.12 순천향대학교컴퓨터공학과이상정 20
임베디드 // ascii_ip.c 소프트웨어 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> int main(int argc, char *argv[]) { struct in_addr inaddr; /* 32 비트 IP 주소구조체 */ char buf[20]; if(argc < 2) { printf(" 사용법 : %s IP 주소 (dotted decimal) ", argv[0]); exit(0); printf("* 입력한 dotted decimal IP 주소 : %s n", argv[1]); inet_pton(af_inet, argv[1], &inaddr.s_addr); printf(" inet_pton(%s) = 0x%X n", argv[1], inaddr.s_addr); inet_ntop(af_inet, &inaddr.s_addr, buf, sizeof(buf)); printf(" inet_ntop(0x%x) t = %s n", inaddr.s_addr, buf); return 0; 순천향대학교컴퓨터공학과이상정 21 TCP 클라이언트 / 서버프로그래밍절차 순천향대학교컴퓨터공학과이상정 22
TCP 클라이언트서버프로그램개요 순천향대학교컴퓨터공학과이상정 23 TCP 동작 클라이언트 서버 connect() 호출 SYN(X) ---> ACK(Y+1) -- connect() 리턴 -- listen(), accept() 호출 ACK(X+1), SYN(Y) accept() 리턴 순천향대학교컴퓨터공학과이상정 24
TCP 서버프로그램- 소켓생성 클라이언트 / 서버통신시프로그램이먼저수행되고있어야함 socket() 을호출하여통신에사용할소켓을생성 socket(pf_inet, SOCK_STREAM,0); 순천향대학교컴퓨터공학과이상정 25 TCP 서버프로그램- 소켓과주소연결 소켓번호와자신의소켓주소 ( 자신의 IP 주소 + 자신의포트번호 ) 를 bind() 함수로서로연결 int bind( int s, /* 소켓번호 */ struct sockaddr *addr, /* 서버자신의소켓주소구조체포인터 */ int len); /* *addr 구조체의크기 */ 순천향대학교컴퓨터공학과이상정 26
TCP 서버프로그램- bind() 예 #define SERV_IP_ADDR "121.184.194.107" #define SERV_PORT 3000 /* 소켓생성 */ s = socket(pf_inet, SOCK_STREAM, 0); struct sockaddr_in server_addr; /* 소켓주소구조체내용 */ server_addr.sin_family = AF_INET; inet_pton(af_inet, SERV_IP_ADDR, &server_addr.sin_addr); sin addr); server_addr.sin_port = htons(serv_port); /* 소켓번호와소켓주소를 bind */ bind(s, (struct sockaddr *)&server_addr, sizeof(server_addr)); 순천향대학교컴퓨터공학과이상정 27 TCP 서버프로그램 연결요청대기모드 listen() 함수를호출하여클라이언트로부터의연결요청을 기다림 소켓을단지수동대기모드 ( 수동적소켓 ) 로변환하고즉시리턴 성공시에는 0, 실패시에는 -1 리턴 int listen ( int s, /* 소켓번호 */ int log /* 연결을기다리는클라이언트의최대수 */ ); // 사용예 listen(s, 2); 순천향대학교컴퓨터공학과이상정 28
TCP 서버프로그램 연결요청수락 (1) accept() 함수를호출하여클라이언트로부터의연결요청수락 클라이언트에서 connect() 로연결요청을보내면이를처리하기위해서서버는 accept() 를호출 accept() 의수행이성공하면접속된클라이언트와의통신에사용할새로운소켓이만들어지고이소켓번호가리턴되며, 실패시에는 -1이리턴 서버는이클라이언트와통신하기위하여 accept() 가리턴한소켓번호를사용 int accept ( int s, /* 소켓번호 */ struct sockaddr *addr, /* 연결요청을한클라이언트의소켓주소구조체 */ int *addrlen /* *addr 구조체크기의포인터 */ ); 순천향대학교컴퓨터공학과이상정 29 TCP 서버프로그램 연결요청수락 (2) 순천향대학교컴퓨터공학과이상정 30
TCP 데이터송수신함수 문법 인자 int send(int s, char *buf, int length, int flags) s 소켓번호 buf 전송할데이터가저장된버퍼 length buf 버퍼의크기 flags 보통 0 int write(int s, const void*buf, int length) s 소켓번호 buf 전송할데이터가저장된버퍼 length buf 버퍼의길이 int recv(int s, char *buf, int length, int flags) s 소켓번호 buf 수신데이터를저장할버퍼 length buf 버퍼의길이 flags 보통 0 int read(int s, void *buf, int length) s 소켓번호 buf 수신데이터를저장할버퍼 순천향대학교컴퓨터공학과이상정 31 length buf 버퍼의길이 소켓닫기 close() 는클라이언트나서버중누구나먼저호출할수있음 송신버퍼에남아서아직전송되지않은데이터가모두전달된후 TCP 연결종료 순천향대학교컴퓨터공학과이상정 32
TCP 클라이언트 / 서버프로그램개요 순천향대학교컴퓨터공학과이상정 33 TCP 클라이언트프로그램 socket() 을호출하여통신에사용할소켓을생성 socket(pf_inet, SOCK_STREAM,0); 서버에게연결요청을보내기위하여 connect() 를호출 서버의소켓주소 ( 상대방의 IP 주소 + 상대방의포트번호 ) 구조체를만들어인수로전달 int connect ( int s, /* 서버와연결시킬소켓번호 */ const struct sockaddr *addr, /* 상대방서버의소켓주소구조체 */ int addrlen /* 구조체 *addr의크기 */ ); 클라이언트는 bind() 를사용하여포트번호를특정한값으로지정할필요가없음 클라이언트는보통시스템이자동으로배정하는포트번호를사용 순천향대학교컴퓨터공학과이상정 34
오드로이드 I/O 소켓프로그램예 순천향대학교컴퓨터공학과이상정 35 오드로이드 I/O 소켓프로그램 오드로이드 I/O 서버 실행시서버포트를명령행으로지정 클라이언트로부터제어명령수신 수신된명령에따라보드에연결된 IO 보드제어 IO 보드상태메시지를클라이언트에송신 호스트클라이언트 실행시서버의주소와포트를명령행으로지정 키보드로서버에제어명령입력후송신 서버로부터상태메시지를수신하여출력 제어명령 ledblink getbutton exit 순천향대학교컴퓨터공학과이상정 36 IO 보드의 LED 를 50 번토글 입력버튼의누름상태읽기 서버및클라이언트종료
프로그램실행예 순천향대학교컴퓨터공학과이상정 37 오드로이드 I/O 서버프로그램 서버메인프로그램, io_server.c 서버소켓개설하고연결요청기다리고수락 클라이언트명령수신하여 IO보드제어함수 (io_control()) ()) 호출 제어응답메시지를클라이언트로송신 IO 보드제어프로그램, io_usb.c 명령에따라제어코드를 IO 보드에전송 보드의상태에따른제어응답코드를리턴 헤더파일, io_server.h usbio API 프로그램, hid-libusb.c usbio C 프로그램 Makefile, io_makefile 순천향대학교컴퓨터공학과이상정 38
오드로이드 I/O 서버프로그램컴파일및실행 # cd /root/odroid-usbio-master/usbio/linux #viio_makefile #viio_server.h #viio_server.c # vi io_usb.c #make fio_makefile #./io_server 3000 순천향대학교컴퓨터공학과이상정 39 io_makefile # Makefile for io_server TARGET = io_server SRCS = io_server.c io_usb.c hid-libusb.c OBJS = io_server.o io_usb.o hid-libusb.o CC = gcc FLAGS =-I/usr/include/libusb-1.0/ /i /lib b -lusb-1.0 -lpthread -DDEBUG_PRINTF $(TARGET):$(OBJS) $(CC) -o $@ $(OBJS) $(FLAGS) io_server.o: io_server.h io_server.c io_usb.o: o: io_server.h io_usb.c hid-libusb.o: hid-libusb.c $(CC) -c hid-libusb libusb.c $(FLAGS) 순천향대학교컴퓨터공학과이상정 40
io_server.h #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #define RETBLINK 10 #define RETPRS 20 #define RETUNPRS 30 #define RETERR -1 #define MAXCMD 80 #define MAXMSG 65 // 수신명령크기 // io 보드전송데이터크기 // 오드로이드 usbio 제어함수 int io_control(char *cmd); 순천향대학교컴퓨터공학과이상정 41 io_server.c // io_server.c - target #include "io_server.h h" // 클라이언트에서명령을받아서제어 int recv_and_control(int sd); int main(int argc, char *argv[]) { struct sockaddr_in client_addr, server_addr; int listen_sock, accp_sock; int addrlen; pid_t pid; if (argc!= 2) { printf("usage: %s port n", argv[0]); exit(0); // 서버소켓생성 if((listen_sock=socket(pf_inet, SOCK_STREAM, 0)) <0) { printf("socket fail n"); exit(0); 순천향대학교컴퓨터공학과이상정 42
// 서버의소켓주소구조체 server_addr을 '0' 으로초기화 bzero((char *)&server_addr, sizeof(server_addr)); // server_addr을세팅 server_addr.sin_family sin = AF_INET; server_addr.sin_addr.s_addr = htonl(inaddr_any); // host-to-network 바이트변환 (4 바이트 ) server_addr.sin_port = htons(atoi( argv[1])); // host-to-network 바이트변환 (2 바이트 ) // bind() 호출 if (bind(listen_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0){ printf("bind fail n"); exit(0); printf("server started. nwaiting for client.. n"); listen(listen_sock, 1); // 클라이언트연결요청수락 addrlen = sizeof(client_addr); if ((accp_sock = accept(listen_sock,(structsock (struct sockaddr *)&client_addr, &addrlen)) < 0) { printf("accept fail n"); exit(0); // 클라이언트에서명령을받아서제어 recv_and_control(accp_sock); close(listen_sock); close(accp_sock); 순천향대학교컴퓨터공학과이상정 43 // 클라이언트에서명령을받아서제어 int recv_and_control(int sd) { char buf[maxcmd]; int nbyte,retdata; char *EXIT_STRING = "exit"; while(1) { // 클라이언트에서명령수신 if ((nbyte = read(sd, buf, MAXCMD)) < 0) { printf("read fail n"); close(sd); exit(0); buf[nbyte-1] = 0; // ' n' -> 0 대체 // 화면에수신명령출력 printf("command: %s n", buf); // 종료문자열수신시에코응답후종료 if (strstr(buf, EXIT_STRING)!= NULL ) { // 클라이언트에에코응답 write(sd, buf, strlen(buf)); printf("good Goodbye. n n"); close(sd); exit(0); 순천향대학교컴퓨터공학과이상정 44
// 오드로이드 usbio 제어함수호출 retdata = io_control(buf); ㅣㄴ // 응답메시지클라이언트에송신 if (retdata!= RETERR) { if (retdata == RETBLINK) strcpy(buf, "Led blink OK."); else if (retdata == RETPRS) strcpy(buf, "Button pressed."); else if (retdata == RETUNPRS) strcpy(buf, "Button unpressed."); else strcpy(buf, "IO control error!"); printf("> %s n", buf); // 클라이언트에제어응답메시지전송 write(sd, buf, strlen(buf)); // while return 0; 순천향대학교컴퓨터공학과이상정 45 io_usb.c #include "io_server.h" #include "hidapi.h" // USB 장치오픈 hid_device* dev_open() { hid_device *device; device = hid_open(0x04d8, 0x003F, NULL); if (!device) printf("hid Device open failed n"); return device; // USB 장치닫기 void close_device(hid_device *device) { hid_close(device); // 지정된시간 (ms) 지연 void checkmsec(int msec) { struct timeval ts, te; long tdiff, sec, ms; gettimeofday(&ts, NULL); 순천향대학교컴퓨터공학과이상정 46
while(1) { gettimeofday(&te, NULL); tdiff = (1000000*(te.tv_sec - ts.tv_sec)) + (te.tv_usec - ts.tv_usec); ms = tdiff / 1000; if(ms > msec) break; // 오드로이드 usbio 제어함수 int io_control(char *cmd) { hid_device *device; unsigned char buf[maxmsg]; int i, ret = 0; device = dev_open(); if(!device) return -1; // 오드로이드 usbio 전송버퍼초기화 memset((void*)buf, 0x00, sizeof(buf)); 순천향대학교컴퓨터공학과이상정 47 if (strcmp("ledblink", cmd) == 0) { buf[1] = 0x80; // 0x80이면 LED 토글명령 // LED 50번토글 for (i=0; i < 50; i++) { // io 보드에제어코드전송 if (hid_write(device, buf, sizeof(buf)) == -1) { printf("!! Write error n"); close_device(device); return RETERR; checkmsec(100); // 100ms 지연 ret = RETBLINK; else if (strcmp("getbutton", cmd) == 0) { // 전송데이터의 1번째바이트가 0x81이면 // 버튼상태읽기명령 buf[0] = 0x81; buf[1] = 0x00; // 데이터전송 if (hid_write(device, buf, sizeof(buf)) == -1) { printf("!! Write error n"); ret = RETERR; 순천향대학교컴퓨터공학과이상정 48
else { // 데이터읽기 if (hid_read(device, buf, sizeof(buf)) == -1) { printf("!! Read error n"); ret = RETERR; // 64 바이트중 2 번째데이터가읽은데이터 if (buf[1] == 0) // 버튼누름 ret = RETPRS; else if (buf[1] == 1) // 버튼안누름 ret = RETUNPRS; printf("!! command error n"); ret = RETERR; close_device(device); return ret; 순천향대학교컴퓨터공학과이상정 49 호스트클라이언트프로그램 fork() 시스템호출 사용자의키보드입력처리그리고서버와의통신두가지일을동시에수행하기위해 fork() 시스템호출을사용하여두개의프로세스를생성 fork() 시스템호출 자식프로세스 ( 새프로세스 ) 를생성 현재프로세스의이미지를복사하여동일한프로세스를하나더생성 순천향대학교컴퓨터공학과이상정 50
호스트클라이언트프로그램 fork() 리턴값 fork() 호출하여자식프로세스가생성되면 fork() 는 PID 를다음과같이반환 순천향대학교컴퓨터공학과이상정 51 호스트클라이언트프로그램 fork() 시스템콜을사용하여두개의프로세스를생성 부모프로세스는사용자가입력한명령을읽어서버로전송 input_and_send() 자식프로세스는서버가응답메시지를소켓에서읽어화면에출력 recv_and_print() $cd~/socket $ gedit io_client.c $cc-oio_clientio_client.c $./io_client 192.168.0.10 3000 순천향대학교컴퓨터공학과이상정 52
io_client.c // io_client.c host #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #define MAXLINE 511 char *EXIT_STRING = "exit"; int recv_and_print(int sd); int input_and_send(int sd); // 종료문자 // 상대로부터메시지수신후화면출력 // 키보드입력받고상대에게메시지전달 int main(int argc, char *argv[]) { pid_t pid; int s; struct sockaddr_in server_addr; 순천향대학교컴퓨터공학과이상정 53 // 명령문입력인자처리 if (argc!= 3) { printf("usage: %s server_ip port ", argv[0]); exit(0); // 소켓생성 if ((s = socket(pf_inet, SOCK_STREAM, 0)) < 0) { printf("client: Can't open stream socket."); exit(0); // server_addr 을 '0' 으로초기화 bzero((char *)&server_addr, sizeof(server_addr)); io_client.c // server_addr 세팅 server_addr.sin_family = AF_INET; inet_pton(af_inet, argv[1], &server_addr.sin_addr); server_addr.sin_port = htons(atoi(argv[2])); // 서버에연결요청 if (connect(s,(struct sockaddr *)&server_addr,sizeof(server_addr)) < 0){ printf("client: can't connect to server."); exit(0); if ((pid = fork()) > 0) input_and_send(s); else if (pid == 0) recv_and_print(s); 순천향대학교컴퓨터공학과이상정 54 // 키보드입력받고상대에게메시지전달 // 상대로부터메시지수신후화면출력
close(s); return 0; // 키보드입력받고서버에게명령송신 intinput_and_send(intsd) { char buf[maxline+1]; int nbyte; while(fgets(buf, sizeof(buf), stdin)!= NULL) { //nbyte = strlen(buf); write(sd, buf, strlen(buf)); // 종료문자열입력처리 if (strstr(buf, EXIT_STRING)!= NULL ) { printf("good bye. n"); close(sd); exit(0); return 0; 순천향대학교컴퓨터공학과이상정 55 // 서버로부터응답메시지수신후화면출력 // //// int recv_and_print(int sd) { char buf[maxline+1]; int nbyte; while(1) { if ((nbyte = read(sd, buf, MAXLINE)) < 0) { printf("read fail n"); close(sd); exit(0); buf[nbyte] = 0; // 응답화면출력 printf("> >%s n %s n", buf); // 종료문자열수신시종료 if (strstr(buf, EXIT_STRING)!= NULL ) { close(sd); exit(0); return 0; 순천향대학교컴퓨터공학과이상정 56
과제 앞의오드로이드 I/O 소켓프로그램을수정하여아래와같은클라이언트명령을처리하도록수정 led toggle led를토글 led blink n led를 n번깜빡거림 get button 버튼의누름상태를읽음 순천향대학교컴퓨터공학과이상정 57