인터넷프로토콜 5 장 데이터송수신 (3) 1
파일전송메시지구성예제 ( 고정크기메시지 ) 전송방식 : 고정크기 ( 바이너리전송 ) 필요한전송정보 파일이름 ( 최대 255 자 => 255byte 의메모리공간필요 ) 파일크기 (4byte 의경우최대 4GB 크기의파일처리가능 ) 파일내용 ( 가변길이, 0~4GB 크기 ) 메시지구성 FileName (255bytes) FileSize (4bytes) Filecontents (0~4GB) 메시지헤더 메시지데이터 2 struct msghdr { char filename[255]; unsigned int filesize;
파일전송메시지구성예제 ( 문자열메시지 ) 전송방식 : 가변길이 ( 문자열전송방식 ) 필요한전송정보 구분자 (!$ : 임의로결정, 단파일이름이나길이에나오지않아야함 ) 파일이름 ( 크기제한없음, 필드의크기는파일이름에따라가변 ) 파일크기 ( 크기제한없음, 필드의크기는파일크기에따라가변 ) 파일내용 ( 가변길이, 0~4GB 크기 ) 메시지구성 (255bytes 의 helloworld.c 를전송할경우 ) Helloworld.c!$255!$ Filecontents (0~4GB) 메시지헤더 메시지데이터 3
파일내용의전송 파일크기가소켓버퍼의크기보다크므로아래와같이순차적전송 #define BUFSIZE 1024 char filebuf[bufsize]; fp = fopen( test.txt", "r"); if(fp == NULL) DieWithError ("File open error"); while(1){ len=fread(filebuf, sizeof(char), BUFSIZE, fp); send(sock, filebuf, len, 0); if(feof(fp)) break; 4
파일내용의수신 #define BUFSIZE 1024 char filebuf[bufsize]; recvfilesize=0; fp = fopen( test.txt", w"); if(fp == NULL) DieWithError ("File open error"); while(origfilesize>recvfilesize) { if ((recvmsgsize = recv(clntsock,filebuf,bufsize, 0)) < 0) DieWithError("recv() failed"); recvfilesize+=recvmsgsize; fwrite(filebuf, sizeof(char), BUFSIZE, fp); 5
응용과제 2 기존에코프로그램을수정하여다음의기능을가지는프로그램을작성하라 클라이언트 : 클라이언트명령어의두번째인자를에코문자열대신파일이름으로받아들여파일을서버에전송하라 Ex) FileClient lily.mmu.ac.kr test.txt 5000 서버 : 해당파일은서버의실행파일이존재하는디렉토리에동일한이름으로저장되도록한다. 6
좀더복잡한메시지구성 7
파일전송의예 메시지구성 char FileName[256]; int FileSize; char FileBuffer[1024]; Server FileName FileSize File Contents Client recv(clntsock, FileName, 256, 0) recv(clntsock, FileSize, 4, 0) while(notrecvfullfile()) { recv(sock, FileBuffer, 1024,0) send(sock, FileName, 256, 0) send(sock, FileSize, 4, 0) while(feof(fd)) { Send(sock, FileBuffer, 1024,0) 8
에코와파일전송을모두지원하는 상황 예 프로토콜 클라이언트는서버에게 string 혹은파일을업로드할수있다. 서버는 string 을받을경우 echo 를해주고파일을받을경우, 디스크에저장을한후잘받았다는메시지를 (acknowledge) 회신한다 클라이언트는 echo 메시지를수신한경우,echo 메시지를출력하고, file ack 를받을경우 file ack 를출력한다 client lily.mmu.ac.kr upload test.txt 5000 // 파일전송 client lily.mmu.ac.kr echo hello 5000 // 에코메시지 9
메시지 ( 프로토콜 ) 설계 서버와클라이언트는동일프로그램으로두개의다른상황을모두만족해야함 EchoString Server File Upload string Echostring Client FileName FileSize File Contents Server Client 서버의입장에서클라이언트의서비스요청이에코요청인지파일업로드인지구분할수있는방법은? 서비스타입 ( 에코요청, 파일업로드 ) 필드를준비하고클라이언트를이를통해서버에게서비스종류를알림 10
바이너리프로토콜설계 EchoString /* Message Type */ #define EchoReq 01 #define FileUpReq 02 #define EchoRep 11 #define FileAck 12 char ; Server string Echostring Client File Upload FileName FileSize File Contents Server Client 11
클라이언트핵심코드 ( 바이너리프로토콜 ) /* Message Type */ #define EchoReq 01 #define FileUpReq 02 #define EchoRep 11 #define FileAck 12 char ; char * operation; //client 203.252.164.144 upload test.txt 5000 operation=argv[2] If (!strcmp(operation, upload )) =FileUpReq send(sock, &, 1,0) else if (!strcmp(operation, echo )) =EchoReq send(sock, &,1,0) else { FileName FileSize File Contents string fprintf(stderr, "Usage: %s <Server IP> <operation><operand> <Echo Port>\n", argv[0]); exit(1); 12
/* Message Type */ #define EchoReq 01 #define FileUpReq 02 #define EchoRep 11 #define FileAck 12 char ; recv(clntsock, &,1,0) 서버핵심코드 ( 바이너리프로토콜 ) if (==FileUpReq) { recv(clntsock, FileName, =FileAck; send(clntsock, &, 1,0); else if(==echoreq) { recv(clntsock, EchoString, =EchoRep; send(clntsock, EchoString,); else fprintf(stderr, Bad request ) FileName FileSize File Contents string 13
문자열프로토콜설계 /* Message Type */ #define EchoReq #define FileUpReq #define EchoRep #define FileAck char [10]; EchoReq FileUpReq EchoRep FileAck Server string Echostring Client FileName FileSize File Contents Server Client 14
/* Message Type */ #define EchoReq EchoReq #define FileUpReq FileUpReq #define EchoRep EchoRep #define FileAck FileAck #define Delimeter 클라이언트핵심코드 ( 문자열프로토콜 ) char msgtype[10]; char * operation; //client 203.252.164.144 upload test.txt 5000 operation=argv[2] If (!strcmp(operation, upload )) strcpy(msgtype, FileUpReq); send(sock, msgtype, strlen(msgtype),0) else if (!strcmp(operation, echo )) strcpy(msgtype, EchoReq); send(sock, msgtype,strlen(msgtype,0) else { fprintf(stderr, "Usage: %s <Server IP> <operation><operand> <Echo Port>\n", argv[0]); exit(1); FileName FileSize File Contents string 15
/* Message Type */ #define EchoReq EchoReq #define FileUpReq FileUpReq #define EchoRep EchoRep #define FileAck FileAck #define Delimeter 서버핵심코드 ( 문자열프로토콜 ) char msgtype[10], recvchar; int i=0; while(i<10) { recvchar=recv(clntsock, msgtype[i],sizeof(char),0); if (msgtype[i]==delimeter) break; ++i; if (!(strcmp(msgtype,filereq)) { recv(clntsock, FileName, strcpy(msgtype,fileack); send(clntsock, msgtype, strlen(msgtype),0); else if(!(strcmp(msgtype, EchoReq)) { recv(clntsock, EchoString, strcpy(msgtype,echorep);; send(clntsock, msgtype, strlen(msgtytpe),0); else fprintf(stderr, Bad request ) FileName FileSize File Contents string 16
응용과제 3 에코와파일전송을모두지원하는프로토콜을정의하고, 서버와클라이언트를작성하여동작을확인하시오. 전송프로토콜 (tcp/udp) - 학번끝자리 ( 짝수 / 홀수 ) 인코딩 / 디코딩 (text / binary) - 학번끝에서 2 번째자리 ( 짝수 / 홀수 ) TCP 의경우 length 프레이밍이용 17
응용과제 4 파일전송 / 수신클라이언트 - 서버구현 기능 : get ( 파일가져오기 ) put ( 파일보내기 ) ls ( 서버측파일보여주기 ) cd ( 서버측디렉토리변경 ) quit( 종료 ) 2 학년 UNIX 프로그래밍참고 18