來(lái)源:Lstri 發(fā)布時(shí)間:2018-11-21 15:26:27 閱讀量:1229
原來(lái)的程序沒(méi)有注釋?zhuān)罱@段時(shí)間在學(xué)習(xí)網(wǎng)絡(luò)編程這塊,就在網(wǎng)上找了個(gè)程序來(lái)學(xué)習(xí),第一次找的程序下載下來(lái)后,編譯沒(méi)通過(guò),剛接觸網(wǎng)絡(luò),哪可能去排錯(cuò)誤,況且代碼那么長(zhǎng),一下讓我退了下來(lái),還是等以后有了基礎(chǔ),再回過(guò)頭看它!
然后就找到了這個(gè)程序,拿下來(lái)運(yùn)行了下,然后讀了讀,自己加上了注釋?zhuān)M芙o跟我一樣的新手一點(diǎn)幫助吧,里面有不恰當(dāng)?shù)牡胤秸?qǐng)指出哈。
//client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <fcntl.h>
#define N 256
typedef struct sockaddr SA;
void commd_help();
void commd_exit();
void commd_ls(struct sockaddr_in, char *);
void commd_get(struct sockaddr_in , char *);
void commd_put(struct sockaddr_in , char *);
int main(int argc, char *argv[])
{
char commd[N];
struct sockaddr_in addr;
int len;
bzero(&addr, sizeof(addr)); //將&addr中的前sizeof(addr)字節(jié)置為0,包括'\0'
addr.sin_family = AF_INET; //AF_INET代表TCP/IP協(xié)議
addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //將點(diǎn)間隔地址轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)順序
addr.sin_port = htons(8989); //轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)順序
len = sizeof(addr);
while(1)
{
printf("ftp>");
bzero(commd,N);
//fgets函數(shù)從stdin流中讀取N-1個(gè)字符放入commd中
if(fgets(commd,N,stdin) == NULL)
{
printf("Fgets Error!\n");
return -1;
}
commd[strlen(commd)-1]='\0'; //fgets函數(shù)讀取的最后一個(gè)字符為換行符,此處將其替換為'\0'
printf("Input Command Is [ %s ]\n",commd);
if(strncmp(commd,"help",4) == 0) //比較兩個(gè)字符串前4個(gè)字節(jié),若相等則返回0
{
commd_help();
}else if(strncmp(commd, "exit",4) == 0)
{
commd_exit();
exit(0); //結(jié)束進(jìn)程
}else if(strncmp(commd, "ls" , 2) == 0)
{
commd_ls(addr, commd);
}else if(strncmp(commd, "get" , 3) == 0)
{
commd_get(addr, commd);
}else if(strncmp(commd, "put", 3) ==0 )
{
commd_put(addr, commd);
}else
{
printf("Command Is Error!Please Try Again!\n");
}
}
return 0;
}
void commd_help()
{
printf("\n=------------------- Welcome to Use the Ftp ----------------=\n");
printf("| |\n");
printf("| help : Display All Command for the Server |\n");
printf("| |\n");
printf("| exit: Quit The Sever |\n");
printf("| |\n");
printf("| ls : Display All file On the Ftp Server |\n");
printf("| |\n");
printf("| get <file>: Download FIle from the Ftp Server |\n");
printf("| |\n");
printf("| put <file>: Upload FIle to the Ftp Server |\n");
printf("| |\n");
printf("=-----------------------------------------------------------=\n");
return ;
}
void commd_exit()
{
printf("Byte!\n");
}
void commd_ls(struct sockaddr_in addr, char *commd)
{
int sockfd;
//創(chuàng)建套接字
if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("Socket Error!\n");
exit(1);
}
if(connect(sockfd, (SA *)&addr, sizeof(addr)) < 0)
{
printf("Connect Error!\n");
exit(1);
}
//將commd指向的內(nèi)容寫(xiě)入到sockfd所指的文件中,此處即指套接字
if(write(sockfd, commd, N) < 0)
{
printf("Write Error!\n");
exit(1);
}
while(read(sockfd, commd, N) > 0) //從sockfd中讀取N字節(jié)內(nèi)容放入commd中,
{ //返回值為讀取的字節(jié)數(shù)
printf(" %s ",commd);
}
printf("\n");
close(sockfd);
return ;
}
/**************************************************/
/*函數(shù)功能:實(shí)現(xiàn)文件的下載 */
/**************************************************/
void commd_get(struct sockaddr_in addr, char *commd)
{
int fd;
int sockfd;
char buffer[N];
int nbytes;
//創(chuàng)建套接字,并進(jìn)行錯(cuò)誤檢測(cè)
if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("Socket Error!\n");
exit(1);
}
//connect函數(shù)用于實(shí)現(xiàn)客戶端與服務(wù)端的連接,此處還進(jìn)行了錯(cuò)誤檢測(cè)
if(connect(sockfd, (SA *)&addr, sizeof(addr)) < 0)
{
printf("Connect Error!\n");
exit(1);
}
//通過(guò)write函數(shù)向服務(wù)端發(fā)送數(shù)據(jù)
if(write(sockfd, commd, N) < 0)
{
printf("Write Error!At commd_get 1\n");
exit(1);
}
//利用read函數(shù)來(lái)接受服務(wù)器發(fā)來(lái)的數(shù)據(jù)
if(read(sockfd, buffer, N) < 0)
{
printf("Read Error!At commd_get 1\n");
exit(1);
}
//用于檢測(cè)服務(wù)器端文件是否打開(kāi)成功
if(buffer[0] =='N')
{
close(sockfd);
printf("Can't Open The File!\n");
return ;
}
//open函數(shù)創(chuàng)建一個(gè)文件,文件地址為(commd+4),該地址從命令行輸入獲取
if((fd=open(commd+4, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0)
{
printf("Open Error!\n");
exit(1);
}
//read函數(shù)從套接字中獲取N字節(jié)數(shù)據(jù)放入buffer中,返回值為讀取的字節(jié)數(shù)
while((nbytes=read(sockfd, buffer, N)) > 0)
{
//write函數(shù)將buffer中的內(nèi)容讀取出來(lái)寫(xiě)入fd所指向的文件,返回值為實(shí)際寫(xiě)入的字節(jié)數(shù)
if(write(fd, buffer, nbytes) < 0)
{
printf("Write Error!At commd_get 2");
}
}
close(fd);
close(sockfd);
return ;
}
/**************************************************/
/*函數(shù)功能:實(shí)現(xiàn)文件的上傳 */
/**************************************************/
void commd_put(struct sockaddr_in addr, char *commd)
{
int fd;
int sockfd;
char buffer[N];
int nbytes;
//創(chuàng)建套接字
if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("Socket Error!\n");
exit(1);
}
//客戶端與服務(wù)端連接
if(connect(sockfd, (SA *)&addr, sizeof(addr)) < 0)
{
printf("Connect Error!\n");
exit(1);
}
//從commd中讀取N字節(jié)數(shù)據(jù),寫(xiě)入套接字中
if(write(sockfd, commd, N)<0)
{
printf("Wrtie Error!At commd_put 1\n");
exit(1);
}
//open函數(shù)從(commd+4)中,讀取文件路徑,以只讀的方式打開(kāi)
if((fd=open(commd+4, O_RDONLY)) < 0)
{
printf("Open Error!\n");
exit(1);
}
//從fd指向的文件中讀取N個(gè)字節(jié)數(shù)據(jù)
while((nbytes=read(fd, buffer, N)) > 0)
{
//從buffer中讀取nbytes字節(jié)數(shù)據(jù),寫(xiě)入套接字中
if(write(sockfd, buffer, nbytes) < 0)
{
printf("Write Error!At commd_put 2");
}
}
close(fd);
close(sockfd);
return ;
}
下面server.c中后面有些注釋沒(méi)加,感覺(jué)功能上跟client相似,就沒(méi)加,可以參看前面的
//server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <dirent.h>
#include <fcntl.h>
#define N 256
typedef struct sockaddr SA;
void commd_ls(int);
void commd_get(int, char *);
void commd_put(int, char *);
int main(int arg, char *argv[])
{
int ser_sockfd,cli_sockfd;
struct sockaddr_in ser_addr,cli_addr;
int ser_len, cli_len;
char commd [N];
bzero(commd,N);//將commd所指向的字符串的前N個(gè)字節(jié)置為0,包括'\0'
if((ser_sockfd=socket(AF_INET, SOCK_STREAM, 0) ) < 0)
{
printf("Sokcet Error!\n");
return -1;
}
bzero(&ser_addr,sizeof(ser_addr));
ser_addr.sin_family = AF_INET;
ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);//在TCP連接中,此處類(lèi)似于自動(dòng)獲取ip地址
//在綁定ip時(shí),自動(dòng)選擇ip地址
ser_addr.sin_port = htons ( 8989 );
ser_len = sizeof(ser_addr);
//將ip地址與套接字綁定
if((bind(ser_sockfd, (SA *)&ser_addr, ser_len)) < 0)
{
printf("Bind Error!\n");
return -1;
}
//服務(wù)器端監(jiān)聽(tīng)
if(listen(ser_sockfd, 5) < 0)
{
printf("Linsten Error!\n");
return -1;
}
bzero(&cli_addr, sizeof(cli_addr));
ser_len = sizeof(cli_addr);
while(1)
{
printf("server_ftp>");
//服務(wù)器端接受來(lái)自客戶端的連接,返回一個(gè)套接字,此套接字為新建的一個(gè),并將客戶端的地址等信息存入cli_addr中
//原來(lái)的套接字仍處于監(jiān)聽(tīng)中
if((cli_sockfd=accept(ser_sockfd, (SA *)&cli_addr, &cli_len)) < 0)
{
printf("Accept Error!\n");
exit(1);
}
//由套接字接收數(shù)據(jù)時(shí),套接字把接收的數(shù)據(jù)放在套接字緩沖區(qū),再由用戶程序把它們復(fù)制到用戶緩沖區(qū),然后由read函數(shù)讀取
//write函數(shù)同理
if(read(cli_sockfd, commd, N) < 0) //read函數(shù)從cli_sockfd中讀取N個(gè)字節(jié)數(shù)據(jù)放入commd中
{
printf("Read Error!\n");
exit(1);
}
printf("recvd [ %s ]\n",commd);
if(strncmp(commd,"ls",2) == 0)
{
commd_ls(cli_sockfd);
}else if(strncmp(commd,"get", 3) == 0 )
{
commd_get(cli_sockfd, commd+4);
}else if(strncmp(commd, "put", 3) == 0)
{
commd_put(cli_sockfd, commd+4);
}else
{
printf("Error!Command Error!\n");
}
}
return 0;
}
void commd_ls(int sockfd)
{
DIR * mydir =NULL;
struct dirent *myitem = NULL;
char commd[N] ;
bzero(commd, N);
//opendir為目錄操作函數(shù),類(lèi)似于open函數(shù)
//mydir中存有相關(guān)目錄的信息(有待學(xué)習(xí))
if((mydir=opendir(".")) == NULL)
{
printf("OpenDir Error!\n");
exit(1);
}
while((myitem = readdir(mydir)) != NULL)
{
if(sprintf(commd, myitem->d_name, N) < 0)
{
printf("Sprintf Error!\n");
exit(1);
}
if(write(sockfd, commd, N) < 0 )
{
printf("Write Error!\n");
exit(1);
}
}
closedir(mydir);
close(sockfd);
return ;
}
void commd_get(int sockfd, char *filename)
{
int fd, nbytes;
char buffer[N];
bzero(buffer, N);
printf("get filename : [ %s ]\n",filename);
if((fd=open(filename, O_RDONLY)) < 0)
{
printf("Open file Error!\n");
buffer[0]='N';
if(write(sockfd, buffer, N) <0)
{
printf("Write Error!At commd_get 1\n");
exit(1);
}
return ;
}
buffer[0] = 'Y'; //此處標(biāo)示出文件讀取成功
if(write(sockfd, buffer, N) <0)
{
printf("Write Error! At commd_get 2!\n");
close(fd);
exit(1);
}
while((nbytes=read(fd, buffer, N)) > 0)
{
if(write(sockfd, buffer, nbytes) < 0)
{
printf("Write Error! At commd_get 3!\n");
close(fd);
exit(1);
}
}
close(fd);
close(sockfd);
return ;
}
void commd_put(int sockfd, char *filename)
{
int fd, nbytes;
char buffer[N];
bzero(buffer, N);
printf("get filename : [ %s ]\n",filename);
if((fd=open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0)
{
printf("Open file Error!\n");
return ;
}
while((nbytes=read(sockfd, buffer, N)) > 0)
{
if(write(fd, buffer, nbytes) < 0)
{
printf("Write Error! At commd_put 1!\n");
close(fd);
exit(1);
}
}
close(fd);
close(sockfd);
return ;
}
---------------------
在線
客服
服務(wù)時(shí)間:周一至周日 08:30-18:00
選擇下列產(chǎn)品馬上在線溝通:
客服
熱線
7*24小時(shí)客服服務(wù)熱線
關(guān)注
微信
關(guān)注官方微信