download

Matakuliah : H0483 – Network Programming
Tahun
: 2008
Versi
: 2.0
KASUS
MERANCANG
Program Transfer File (PTF)
PTFServer dan PTFClient
1
Learning Outcomes
Pada akhir pertemuan ini, diharapkan mahasiswa
akan mampu :
• Mendemonstrasikan program aplikasi
Client Server untuk mentransfer file
2
Outline Materi
•
•
•
•
•
Merancang Flow Control
Merancang Protokol
Membuat Program Server
Membuat Program Client
Compilasi & Testing
3
Rancangan
4
Rancangan
5
Implementasi Server
#define SERVER_PORT_ID 6081
#define CLIENT_PORT_ID 6086
#define SERVER_HOST_ADDR "192.168.90.15"
#define MAXSIZE 512
#define ACK
2
#define NACK
3
#define REQUESTFILE
100
#define COMMANDNOTSUPPORTED 150
#define COMMANDSUPPORTED
160
#define BADFILENAME
200
#define FILENAMEOK
400
#define STARTTRANSFER
500
6
Implementasi Server
#include
#include
#include
#include
#include
#include
#include
<stdio.h>
<sys/types.h>
<sys/socket.h>
<netinet/in.h>
<arpa/inet.h>
<time.h>
<errno.h>
#define MY_PORT_ID 6081
#define MAXLINE 256
#define MAXSIZE 512
#define
#define
#define
#define
#define
#define
#define
ACK
NACK
REQUESTFILE
COMMANDNOTSUPPORTED
COMMANDSUPPORTED
BADFILENAME
FILENAMEOK
2
3
100
150
160
200
400
7
Implementasi Server
int writen(int sd,char *ptr,int size);
int readn(int sd,char *ptr,int size);
int len;
main()
{
int sockid, newsd, pid, clilen;
struct sockaddr_in my_addr, client_addr;
printf("server: creating socket\n");
sockid = socket(AF_INET,SOCK_STREAM,0);
if(sockid < 0){
printf("socket error: %d\n", errno);
exit(0);
}
8
Implementasi Server
printf("binding my local socket\n");
bzero((char *) &my_addr,sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(MY_PORT_ID);
my_addr.sin_addr.s_addr=htons(INADDR_ANY);
if(bind(sockid ,(struct sockaddr *)
&my_addr,sizeof(my_addr)) < 0){
printf("bind error:%d\n", errno);
exit(0);
}
printf("server: starting listen \n");
if(listen(sockid,5) < 0){
printf("listen error :%d\n",errno);
exit(0);
}
9
Implementasi Server
while(1){
printf("server: starting accept\n");
if((newsd=accept(sockid,(struct sockaddr*)
&client_addr,&clilen))<0){
printf("accept error:%d\n", errno);
exit(0);
}
doftp(newsd);
}
}
10
Implementasi Server
doftp(int newsd){
int i,fsize,fd,msg_ok,fail;
int fail1,req,c,ack;
int no_read ,num_blks;
int num_blks1,num_last_blk;
int num_last_blk1,tmp;
char fname[MAXLINE];
char out_buf[MAXSIZE];
FILE *fp;
no_read = 0;
num_blks = 0;
num_last_blk = 0;
11
Implementasi Server
req = 0;
if((readn(newsd,(char *)&req,sizeof(req))) < 0){
printf("read error %d\n",errno);exit(0);
}
req = ntohs(req);
printf("client request code is: %d\n",req);
if(req!=REQUESTFILE){
printf("unsupported operation. goodbye\n");
msg_ok = COMMANDNOTSUPPORTED;
msg_ok = htons(msg_ok);
if((writen(newsd,(char
*)&msg_ok,sizeof(msg_ok)))<0){
printf("write error :%d\n",errno);
exit(0);
}
exit(0);
}
12
Implementasi Server
msg_ok = COMMANDSUPPORTED;
msg_ok = htons(msg_ok);
if((writen(newsd,(char *)
&msg_ok,sizeof(msg_ok))) < 0){
printf("write error :%d\n",errno);
exit(0);
}
fail = FILENAMEOK;
if((len=read(newsd,fname,MAXLINE)) < 0) {
printf("filename read error :%d\n",errno);
fail = BADFILENAME ;
}
fname[len]='\0';
13
Implementasi Server
if((fp=fopen(fname,"r"))==NULL)fail= BADFILENAME;
tmp = htons(fail);
if((writen(newsd,(char *)&tmp,sizeof(tmp))) < 0){
printf("write error :%d\n",errno);exit(0);
}
if(fail==BADFILENAME){
printf("server cant open file\n");
close(newsd); exit(0);
}
printf("filename is %s\n",fname);
req = 0;
if((readn(newsd,(char *)&req,sizeof(req)))<0){
printf("read error :%d\n",errno);exit(0);
}
printf("start transfer,%d, received\n",ntohs(req));
14
Implementasi Server
printf("starting transfer\n");
fsize = 0;ack = 0;
while((c=getc(fp))!=EOF) fsize++;
num_blks = fsize / MAXSIZE;
num_blks1 = htons(num_blks);
num_last_blk = fsize % MAXSIZE;
num_last_blk1 = htons(num_last_blk);
if((writen(newsd,(char *)&num_blks1,
sizeof(num_blks1)))< 0){
printf("write error :%d\n",errno);
exit(0);
}
printf("told client there are %d blocks\n",
num_blks);
15
Implementasi Server
if((readn(newsd,(char *)&ack,sizeof(ack))) < 0){
printf("ack read error :%d\n",errno);
exit(0);
}
if(ntohs(ack) != ACK){
printf("ACK not received on file size\n");
exit(0);
}
if((writen(newsd,(char *)&num_last_blk1,
sizeof(num_last_blk1))) < 0){
printf("write error :%d\n",errno);exit(0);
}
printf("told client %d bytes in last block\n",
num_last_blk);
if((readn(newsd,(char *)&ack,sizeof(ack))) < 0){
printf("ack read error :%d\n",errno);exit(0);
}
16
Implementasi Server
if(ntohs(ack) != ACK){
printf("ACK not received on
file size\n");
exit(0);
}
rewind(fp);
17
Implementasi Server
for(i= 0; i < num_blks; i ++){
no_read = fread(out_buf,sizeof(char),MAXSIZE,fp);
if (no_read == 0){
printf("file read error\n"); exit(0);
}
if (no_read != MAXSIZE){
printf("file read error\n"); exit(0);
}
if((writen(newsd,out_buf,MAXSIZE)) < 0){
printf("error sending block:%d\n",errno);exit(0);
}
if((readn(newsd,(char *)&ack,sizeof(ack))) < 0){
printf("ack read error :%d\n",errno);exit(0);
}
if (ntohs(ack) != ACK){
printf("ACK not received for block %d\n",i);
exit(0);
}
printf("%d\r",i);
}
18
Implementasi Server
if(num_last_blk > 0){
printf("%d\n",num_blks);
no_read = fread(out_buf,sizeof(char),num_last_blk,fp);
if (no_read == 0){
printf("server: file read error\n"); exit(0);
}
if (no_read != num_last_blk){
printf("file read error : no_read is less 2\n");exit(0);
}
if((writen(newsd,out_buf,num_last_blk)) < 0){
printf("server: file transfer error %d\n",errno);exit(0);
}
if((readn(newsd,(char *)&ack,sizeof(ack))) < 0){
printf("server: ack read error %d\n",errno);exit(0);
}
if(ntohs(ack) != ACK) {
printf("server: ACK not received last block\n");
exit(0);
}
}
else printf("\n");
19
Implementasi Server
/* FILE TRANSFER ENDS */
printf("FILE TRANSFER COMPLETE
on socket %d\n",newsd);
fclose(fp);
close(newsd);
}
20
Implementasi Client
#include
#include
#include
#include
#include
#include
#include
#define
#define
#define
#define
<stdio.h>
<sys/types.h>
<sys/socket.h>
<netinet/in.h>
<arpa/inet.h>
<time.h>
<errno.h>
SERVER_PORT_ID 6081
CLIENT_PORT_ID 6086
SERVER_HOST_ADDR "192.168.90.15"
MAXSIZE 512
21
Implementasi Client
#define
#define
#define
#define
#define
#define
#define
#define
ACK
NACK
REQUESTFILE
COMMANDNOTSUPPORTED
COMMANDSUPPORTED
BADFILENAME
FILENAMEOK
STARTTRANSFER
2
3
100
150
160
200
400
500
int readn(int sd,char *ptr,int size);
int writen(int sd,char *ptr,int size);
22
Implementasi Client
main(int argc,char *argv[])
{
int sockid, newsockid, i, getfile;
int ack, msg, msg_2, c, len;
int no_writen,start_xfer, num_blks,num_last_blk;
struct sockaddr_in my_addr, server_addr;
FILE *fp;
char in_buf[MAXSIZE];
if(argc != 2){
printf("error: usage : ftp filename\n");
exit(0);
}
23
Implementasi Client
no_writen = 0;
num_blks = 0;
num_last_blk = 0;
len = strlen(argv[1]);
printf("client: creating socket\n");
if((sockid=socket(AF_INET,SOCK_STREAM,0))< 0){
printf("client: socket error : %d\n", errno);
exit(0);
}
24
Implementasi Client
printf("client: binding my local socket\n");
bzero((char *) &my_addr,sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
my_addr.sin_port = htons(CLIENT_PORT_ID);
if(bind(sockid ,(struct sockaddr *) &my_addr,
sizeof(my_addr)) < 0){
printf("client: bind error :%d\n", errno);
exit(0);
}
25
Implementasi Client
printf("client: starting connect\n");
bzero((char *)&server_addr,sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr=inet_addr(SERVER_HOST_ADDR);
server_addr.sin_port = htons(SERVER_PORT_ID);
if(connect(sockid ,(struct sockaddr *) &server_addr,
sizeof(server_addr)) < 0){
printf("client: connect error :%d\n", errno);
exit(0);
}
26
Implementasi Client
getfile = htons(REQUESTFILE);
printf("sending command request to ftp server\n");
if((writen(sockid,(char *)&getfile,
sizeof(getfile))) < 0){
printf("write error:%d\n", errno); exit(0);
}
msg = 0;
if((readn(sockid,(char *)&msg,sizeof(msg)))< 0){
printf("read error:%d\n", errno); exit(0);
}
msg = ntohs(msg);
if(msg==COMMANDNOTSUPPORTED){
printf("server refused command\n"); exit(0);
}
else printf("server replied %d, command
supported\n",msg);
27
Implementasi Client
/* send file name to server */
printf("client: sending filename\n");
if((writen(sockid,argv[1],len))< 0){
printf("write error:%d\n", errno); xit(0);
}
msg_2 = 0;
if((readn(sockid,(char *)&msg_2,
sizeof(msg_2)))< 0){
printf("read error:%d\n", errno); exit(0);
}
msg_2 = ntohs(msg_2);
if(msg_2 == BADFILENAME){
printf("server reported bad file name\n");
exit(0);
}
else printf("server replied filename OK\n");
28
Implementasi Client
printf("sending start transfer command\n");
start_xfer = STARTTRANSFER;
start_xfer = htons(start_xfer);
if((writen(sockid,(char *)&start_xfer,m
sizeof(start_xfer)))< 0){
printf("write error:%d\n", errno); exit(0);
}
if((fp = fopen(argv[1],"w")) == NULL){
printf("local open file error\n");exit(0);
}
29
Implementasi Client
if((readn(sockid,(char *)&num_blks,
sizeof(num_blks))) < 0){
printf("read error on nblocks :%d\n",errno);
exit(0);
}
num_blks = ntohs(num_blks);
printf("server responded: %d blocks in
file\n",num_blks);
ack = ACK;
ack = htons(ack);
if((writen(sockid,(char*)&ack,sizeof(ack)))<0){
printf("ack write error :%d\n",errno);
exit(0);
}
30
Implementasi Client
if((readn(sockid,(char *)&num_last_blk,
sizeof(num_last_blk))) < 0){
printf("read error:%d on nbytes\n",errno);
exit(0);
}
num_last_blk = ntohs(num_last_blk);
printf("server responded: %d bytes last blk\n",
num_last_blk);
if((writen(sockid,(char *)&ack,sizeof(ack)))<0){
printf("write error:%d\n",errno);
exit(0);
}
31
Implementasi Client
printf("client: starting to get file contents\n");
for(i= 0; i < num_blks; i ++) {
if((readn(sockid,in_buf,MAXSIZE)) < 0){
printf("block error read: %d\n",errno);
exit(0);
}
no_writen=fwrite(in_buf,sizeof(char),MAXSIZE,fp);
if(no_writen == 0){
printf("file write error\n");exit(0);
}
if (no_writen != MAXSIZE){
printf("write error: no_writen is less\n");
exit(0);
}
if((writen(sockid,(char *)&ack,sizeof(ack))) < 0){
printf("ack write error :%d\n",errno);exit(0);
}
printf(" %d...",i);
}
32
Implementasi Client
if(num_last_blk > 0){
printf("%d\n",num_blks);
if((readn(sockid,in_buf,num_last_blk)) < 0){
printf("last block error read :%d\n",errno);
exit(0);
}
no_writen=fwrite(in_buf,sizeof(char),num_last_blk,fp);
if(no_writen == 0){
printf("last block file write err :%d\n",errno);
exit(0);
}
if(no_writen != num_last_blk){
printf("file write error : no_writen is less 2\n");
exit(0);
}
if((writen(sockid,(char *)&ack,sizeof(ack))) < 0){
printf("ack write error:%d\n",errno); exit(0);
}
}
else printf("\n");
33
Implementasi Client
fclose(fp);
printf("FILE TRANSFER COMPLETE\n");
close(sockid);
}
34
Fungsi readn()
int readn(int sd,char *ptr,int size)
{
int no_left,no_read;
no_left = size;
while (no_left > 0){
no_read = read(sd,ptr,no_left);
if(no_read <0) return(no_read);
if (no_read == 0) break;
no_left -= no_read;
ptr += no_read;
}
return(size - no_left);
}
35
Fungsi writen()
int writen(int sd, char *ptr,int size)
{
int no_left, no_written;
no_left = size;
while(no_left > 0){
no_written=write(sd, ptr,no_left);
if(no_written <=0)return(no_written);
no_left -= no_written;
ptr += no_written;
}
return(size - no_left);
}
36
TUGAS
•
•
Contoh kasus diatas, servernya tidak
bisa melayani lebih dari satu client.
Modifikasi program PTFServer diatas
agar bisa melayani banyak client dengan
menggunakan :
1. multi proses ( system call fork() ), satu proses
melayani satu client
2. Multi threading ( satu thread melayani satu
client ).
37