/* FTP服務的客戶端。動作:
-連接到服務器並請求服務
-向服務器發送樂思的大小信息
-開始從服務器接收文件
-緊密連接
*/
# include & ltstdio.h & gt
# include & ltsys/types . h & gt;
# include & ltsys/socket . h & gt;
# include & ltnetinet/in . h & gt;
# include & ltarpa/inet . h & gt;
# include & lttime.h & gt
# include & lt錯誤號& gt
# define SERVER _ PORT _ ID 6081
#定義客戶端端口ID 6086
#定義服務器_主機_ ADDR " 128.119 . 40 . 186 "
/* gaia.cs.umass.edu */
#定義MAXSIZE 512
#定義確認2
#定義NACK 3
#定義請求文件100
#define命令不支持150
#定義命令支持160
#定義壞文件名200
#定義文件名OK 400
#定義開始轉移500
int readn(int sd,char *ptr,int size);
int writen(int sd,char *ptr,int size);
main(int argc,char *argv[])
{
int sockid,newsockid,I,getfile,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];
如果(argc!= 2) {printf("錯誤:用法:sftp文件名\ n ");退出(0);}
no _ writen = 0;
num _ blks = 0;
num _ last _ blk = 0;
len = strlen(argv[1]);
printf("client:正在創建套接字\ n ");
if ((sockid = socket(AF_INET,SOCK_STREAM,0))& lt;0)
{ printf("client: socket錯誤:%d\n ",errno);退出(0);
}
printf("client:綁定我的本地套接字\ n ");
bzero((char *)& amp;my_addr,sizeof(my _ addr));
我的_地址. sin _家庭= AF _ INET
my _ addr . sin _ addr . s _ addr = htonl(in addr _ ANY);
my _ addr . sin _ PORT = htons(CLIENT _ PORT _ ID);
if (bind(sockid,(struct sockaddr *)& amp;my_addr,sizeof(my _ addr))& lt;0)
{printf("client: bind error :%d\n ",errno);退出(0);
}
printf("client:正在啟動連接\ n ");
bzero((char *)& amp;server_addr,sizeof(server _ addr));
server _ addr . sin _ family = AF _ INET;
SERVER _ addr . sin _ addr . s _ addr = inet _ addr(服務器_主機_ ADDR);
SERVER _ addr . sin _ PORT = htons(SERVER _ PORT _ ID);
if (connect(sockid,(struct sockaddr *)& amp;服務器地址,
sizeof(server _ addr))& lt;0)
{ printf(" client:connect error:% d \ n ",errno);退出(0);
}
/*壹旦我們到達這裏,我們就可以連接到服務器*/
/*告訴服務器我們想要獲取壹個文件*/
getfile = htons(request file);
printf("client:向ftp服務器發送命令請求\ n ");
if((writen(sockid,(char *)& amp;getfile,sizeof(getfile)))& lt;0)
{printf("client:寫錯誤:%d\n ",errno);退出(0);}
/*希望從服務器獲得許可*/
msg = 0;
if((readn(sockid,(char *)& amp;msg,sizeof(msg)))& lt;0)
{printf("client:讀取錯誤:%d\n ",errno);退出(0);}
msg = ntohs(msg);
if (msg==COMMANDNOTSUPPORTED) {
printf("客戶端:服務器拒絕命令。再見\ n”);
退出(0);
}
其他
printf("客戶端:服務器回復了%d,命令支持\n ",msg);
/*將文件名發送到服務器*/
printf("client:發送文件名\ n ");
if ((writen(sockid,argv[1],len))& lt;0)
{printf("client:寫錯誤:%d\n ",errno);退出(0);}
/*查看服務器是否回復文件名正常*/
msg _ 2 = 0;
if ((readn(sockid,(char *)& amp;msg_2,sizeof(msg _ 2)))& lt;0)
{printf("client:讀取錯誤:%d\n ",errno);退出(0);}
msg _ 2 = ntohs(msg _ 2);
if (msg_2 == BADFILENAME) {
printf("客戶端:服務器報告了錯誤的文件名。再見。\ n ");
退出(0);
}
其他
printf("客戶端:服務器回復了%d,文件名OK\n ",msg _ 2);
/*客戶端知道服務器能夠以讀取方式打開文件
模式,並要求繼續*/
/*客戶端現在以寫模式打開文件的副本並發送
服務器的GOAHEAD */
printf("client:發送開始傳輸命令\ n ");
start _ xfer = STARTTRANSFER
start _ xfer = htons(start _ xfer);
if ((writen(sockid,(char *)& amp;start_xfer,sizeof(start _ xfer)))& lt;0)
{printf("client:寫錯誤:%d\n ",errno);退出(0);
}
if ((fp = fopen(argv[1]," w))= = NULL)
{printf(" client:本地打開文件錯誤\ n ");退出(0);}
/*現在客戶端正在從服務器讀取關於有多少
大小為MAXSIZE的完整塊。它也接收號碼
最後壹個部分填充的塊中剩余的字節數,如果有的話*/
if((readn(sockid,(char *)& amp;num_blks,sizeof(num _ blks)))& lt;0)
{ printf(" client:n blocks上的讀取錯誤:%d\n ",errno);退出(0);}
num _ blks = ntohs(num _ blks);
printf("客戶端:服務器響應:文件中有%d個塊\n ",num _ blks);
ack = ACK
ack = htons(ack);
if((writen(sockid,(char *)& amp;ack,sizeof(ack)))& lt;0)
{printf("client: ack寫入錯誤:%d\n ",errno);退出(0);
}
if((readn(sockid,(char *)& amp;num_last_blk,sizeof(num _ last _ blk)))& lt;0)
{printf("client:讀取錯誤:%d on nbytes\n ",errno);退出(0);}
num _ last _ blk = ntohs(num _ last _ blk);
printf("客戶端:服務器響應:%d字節last blk\n ",num _ last _ blk);
if((writen(sockid,(char *)& amp;ack,sizeof(ack)))& lt;0)
{printf("client: ack寫入錯誤:%d\n ",errno);退出(0);
}
/*開始讀取服務器發送的塊*/
printf("client:開始獲取文件內容\ n ");
for(I = 0;我& ltnum _ blksi ++) {
if((readn(sockid,in_buf,MAXSIZE))& lt;0)
{printf("client:塊錯誤讀取:%d\n ",errno);退出(0);}
no_writen = fwrite(in_buf,sizeof(char),MAXSIZE,FP);
if(no _ writen = = 0){ printf(" client:文件寫入錯誤\ n ");退出(0);}
if (no_writen!= MAXSIZE)
{printf("client:文件寫入錯誤:no_writen較小\ n ");退出(0);}
/*發送該塊的ACK */
if((writen(sockid,(char *)& amp;ack,sizeof(ack)))& lt;0)
{printf("client: ack寫入錯誤:%d\n ",errno);退出(0);}
printf(" %d ... ",我);
}
/*如果有最後壹個部分填充的塊,讀取它*/
if(num _ last _ blk & gt;0) {
printf("%d\n ",num _ blks);
if((readn(sockid,in_buf,num _ last _ blk))& lt;0)
{printf("client:讀取的最後壹個塊錯誤:%d\n ",errno);退出(0);}
no_writen = fwrite(in_buf,sizeof(char),num_last_blk,FP);
if (no_writen == 0)
{printf("client:最後壹個塊文件寫入錯誤:%d\n ",errno);退出(0);}
if (no_writen!=編號最後壹個區塊)
{printf("client:文件寫入錯誤:no_writen小於2 \ n ");退出(0);}
if((writen(sockid,(char *)& amp;ack,sizeof(ack)))& lt;0)
{printf("client :ack寫入錯誤:%d\n ",errno);退出(0);}
}
else printf(" \ n ");
/*文件傳輸結束。客戶端在關閉所有文件後終止
和插座*/
fclose(FP);
printf("client:文件傳輸完成\ n ");
close(sockid);
}
/*因為內核中套接字的緩沖區限制可能是
達到時,讀取和寫入可能會返回正值
少於請求的數量。因此我們稱這兩個過程為
以處理此類緊急情況*/
int readn(int sd,char *ptr,int size)
{ int no_left,no _ read
no _ left = size
while(no _ left & gt;0)
{ no_read = read(sd,ptr,no _ left);
if(no _ read & lt;0)返回(no _ read);
if(no _ read = = 0)break;
no _ left-= no _ read;
ptr+= no _ read;
}
return(size-no _ left);
}
int writen(int sd,char *ptr,int size)
{ int no_left,no _ written
no _ left = size
while(no _ left & gt;0)
{ no_written = write(sd,ptr,no _ left);
if(no _ written & lt;=0)返回(no _ written);
no _ left-= no _ written;
ptr+= no _ written;
}
return(size-no _ left);
}
計算機網絡服務器
# include & ltstdio.h & gt
# include & ltsys/types . h & gt;
# include & ltsys/socket . h & gt;
# include & ltnetinet/in . h & gt;
# include & ltarpa/inet . h & gt;
# include & lttime.h & gt
# include & lt錯誤號& gt
#定義我的端口ID 6081
#定義最高限額256
#定義MAXSIZE 512
#定義確認2
#定義NACK 3
#定義請求文件100
#define命令不支持150
#定義命令支持160
#定義壞文件名200
#定義文件名OK 400
int writen(int sd,char *ptr,int size);
int readn(int sd,char *ptr,int size);
main() {
int sockid,newsd,pid,clilen
struct sockaddr_in my_addr,client _ addr
printf("服務器:正在創建套接字\ n ");
if ((sockid = socket(AF_INET,SOCK_STREAM,0))& lt;0)
{printf("服務器:套接字錯誤:%d\n ",errno);退出(0);}
printf("server:綁定我的本地套接字\ n ");
bzero((char *)& amp;my_addr,sizeof(my _ addr));
我的_地址. sin _家庭= AF _ INET
MY _ addr . sin _ PORT = htons(MY _ PORT _ ID);
my _ addr . sin _ addr . s _ addr = htons(in addr _ ANY);
if (bind(sockid,(struct sockaddr *)& amp;my_addr,sizeof(my _ addr))& lt;0)
{printf("服務器:綁定錯誤:%d\n ",errno);退出(0);}
printf("服務器:開始監聽\ n ");
if (listen(sockid,5)& lt;0)
{ printf(" server:listen error:% d \ n ",errno);退出(0);}
while(1==1) {
/*接受連接,然後創建壹個子進程來完成這項工作*/
/*環回並等待另壹個連接*/
printf("服務器:開始接受\ n ");
if ((newsd = accept(sockid,(struct sockaddr *)& amp;客戶端地址,
& ampclilen))& lt;0)
{printf("服務器:接受錯誤:%d\n ",errno);退出(0);}
printf("server:從accept返回,此ftp的套接字:%d\n ",
newsd);
if ( (pid=fork()) == 0) {
/*子過程從這裏開始。它將進行實際的文件傳輸*/
close(sockid);/*孩子不應該接受*/
doftp(newsd);
關閉(newsd);
退出(0);/*孩子全部完成工作*/
}
/*家長在下面繼續*/
關閉(newsd);/*父級全部由客戶端完成,只有子級*/
} /*從現在開始將與該客戶端通信*/
}