参考链接:http://blog.csdn.net/yanghaoran321/article/details/7882760
程序功能:
客户端能够通过命令显示文件服务器上的文件,能够上传、下载文件等等功能;
在浏览原博主的代码后,作出一下修改:
- 将迭代服务器修改为 并发服务器
- 接受 服务器文件夹 文件列表 的缓冲区 增大,避免缓冲区溢出 stack smashing detected
- 传参简化
- 设置套接字地址重用选项
程序如下:
server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define BACKLOG 10
struct message
{
char cmd[10];
char filename[20];
};
void list_file(int ,struct message *);
void get_file(int ,struct message *);
void put_file(int ,struct message *);
void process_cli(int ,struct sockaddr_in );
int main(int argc,char *argv[])
{
int listen_fd,socket_fd;
struct sockaddr_in server_addr,client_addr;
socklen_t client_addrlen;
pid_t pid;
if(argc <3)
{
fprintf(stderr,"Usage : %s ip port\n",argv[0]);
exit(1);
}
if((listen_fd=socket(AF_INET,SOCK_STREAM,0)) <0)
{
perror("failed to create socket");
exit(1);
}
int opt=SO_REUSEADDR;
setsockopt(listen_fd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(atoi(argv[2]));
server_addr.sin_addr.s_addr=inet_addr(argv[1]);
//inet.pton(AF_INET,argv[1],&server_addr.sin_addr);
client_addrlen=sizeof(struct sockaddr);
if(bind(listen_fd,(struct sockaddr *)&server_addr,sizeof(server_addr)) < 0)
{
perror("failed to bind");
exit(1);
}
listen(listen_fd,BACKLOG);
while(1)
{
if((socket_fd=accept(listen_fd,(struct sockaddr *)&client_addr,&client_addrlen)) < 0)
{
perror("failed to accept");
exit(1);
}
if((pid=fork()) >0)
{
close(socket_fd);
continue;
}
else if(pid == 0)
{
close(listen_fd);
process_cli(socket_fd,client_addr);
exit(0);
}
else
{
perror("failed to fork");
exit(1);
}
}
close(listen_fd);
return 0;
}
void process_cli(int socket_fd,struct sockaddr_in client_addr)
{
struct message msg;
memset(&msg,0,sizeof(msg));
recv(socket_fd,&msg,sizeof(msg),0);
printf("cmd : %s\n",msg.cmd);
if(strcmp(msg.cmd,"list") == 0)
list_file(socket_fd,&msg);
else if(strcmp(msg.cmd,"get") == 0 )
get_file(socket_fd,&msg);
else if(strcmp(msg.cmd,"put") == 0)
put_file(socket_fd,&msg);
close(socket_fd);
return ;
}
void list_file(int socket_fd, struct message *msg)
{
DIR *dp;
struct dirent *dirp;
char buf[500];
if((dp =opendir(".")) < 0)
{
perror("failed to open dir");
exit(1);
}
memset(buf,0,sizeof(buf));
while((dirp = readdir(dp)) != NULL)
{
if(strcmp(dirp->d_name,".") == 0 || strcmp(dirp->d_name,"..") == 0)
continue;
strcat(buf,dirp->d_name);
strcat(buf," ");
}
send(socket_fd,buf,strlen(buf) ,0);
closedir(dp);
return ;
}
void get_file(int socket_fd, struct message *msg)
{
int fd;
char buf[1024];
int num=0;
if((fd=open(msg->filename,O_RDONLY)) <0)
{
perror("failed to open file");
exit(1);
}
memset(buf,0,sizeof(buf));
while((num=read(fd,buf,sizeof(buf))) >0)
{
usleep(500);
if(send(socket_fd,buf,num,0) < 0)
{
perror("failed to send date");
exit(1);
}
}
if( num < 0)
{
perror("failed to read ");
exit(1);
}
close(fd);
return ;
}
void put_file(int socket_fd,struct message *msg)
{
int fd;
char buf[1024];
int num=0;
if((fd=open(msg->filename,O_WRONLY | O_CREAT | O_TRUNC ,0666)) < 0 )
{
perror("failed to create file");
exit(1);
}
memset(buf,0,sizeof(buf));
while((num=recv(socket_fd,buf,sizeof(buf),0)) >0)
if( write(fd,buf,num) != num)
{
perror("failed to write");
exit(1);
}
if(num < 0)
{
perror("failed to recv date");
exit(1);
}
close(fd);
return ;
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <dirent.h>
#include <fcntl.h>
struct message
{
char cmd[10];
char filename[20];
};
void list_file(struct message ,struct sockaddr_in);
void get_file(struct message ,struct sockaddr_in);
void put_file(struct message ,struct sockaddr_in);
int main(int argc , char *argv[])
{
struct sockaddr_in server_addr;
struct message msg;
char buf[100];
char *arg[10];
int i=0;
if(argc < 3)
{
fprintf(stderr,"Usage : %s ip port\n",argv[0]);
exit(1);
}
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(atoi(argv[2]));
server_addr.sin_addr.s_addr=inet_addr(argv[1]);
while(1)
{
memset(buf,0,sizeof(buf));
memset(&msg,0,sizeof(msg));
i=0;
printf("###################################\n");
printf("function:\n");
printf("Input \"list\" can list the file server's files\n");
printf("Input \"get filename\" can download file from server\n");
printf("Input \"put filename\" can upload file to file server\n");
printf("Input \"quit\" can quit the client\n");
printf("####################################\n");
printf(">");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf) - 1 ]=0;
arg[i] = strtok(buf," ");
while(arg[i] != NULL)
arg[++i]= strtok(NULL," ");
strcpy(msg.cmd,arg[0]);
if(strncmp(buf,"quit",4) ==0)
break;
if(strcmp(arg[0],"list") == 0)
{
list_file(msg,server_addr);
}
else if(strcmp(arg[0],"get") == 0)
{
strcpy(msg.filename,arg[1]);
get_file(msg,server_addr);
}
else if(strcmp(arg[0],"put") == 0)
{
strcpy(msg.filename,arg[1]);
put_file(msg,server_addr);
}
}
return 0;
}
void list_file(struct message msg , struct sockaddr_in server_addr)
{
int client_fd;
char buf[500];
if((client_fd=socket(AF_INET,SOCK_STREAM,0)) < 0)
{
perror("failed to Create socket ");
exit(1);
}
if(connect(client_fd,(struct sockaddr *)&server_addr,sizeof(server_addr)) < 0)
{
perror("failed to connect");
exit(1);
}
if(send(client_fd,&msg,sizeof(msg),0) < 0)
{
perror("failed to send msg");
exit(1);
}
usleep(500);
memset(buf,0,sizeof(buf));
if(recv(client_fd,buf,sizeof(buf),0) < 0 )
{
perror("failed to recv msg");
exit(1);
}
printf("%s\n",buf);
close(client_fd);
return ;
}
void get_file(struct message msg, struct sockaddr_in server_addr)
{
int fd,client_fd;
char buf[1024];
int num=0;
if((client_fd=socket(AF_INET,SOCK_STREAM,0)) < 0)
{
perror("failed to Create socket ");
exit(1);
}
if(connect(client_fd,(struct sockaddr *)&server_addr,sizeof(server_addr)) < 0)
{
perror("failed to connect");
exit(1);
}
if((fd=open(msg.filename,O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0)
{
perror("failed to Create file");
exit(1);
}
if(send(client_fd,&msg,sizeof(msg),0) <0 )
{
perror("failed to send msg");
exit(1);
}
memset(buf,0,sizeof(buf));
while((num=recv(client_fd,buf,sizeof(buf),0)) >0)
{
usleep(500);
if(write(fd,buf,num) != num)
{
perror("failed to write");
exit(1);
}
}
if(num <0)
{
perror("failed to recv");
exit(1);
}
printf("Download OK!\n");
close(fd);
close(client_fd);
return ;
}
void put_file(struct message msg, struct sockaddr_in server_addr )
{
int fd,client_fd;
int num=0;
char buf[1024];
if((client_fd=socket(AF_INET,SOCK_STREAM,0)) < 0)
{
perror("failed to Create socket ");
exit(1);
}
if(connect(client_fd,(struct sockaddr *)&server_addr,sizeof(server_addr)) < 0)
{
perror("failed to connect");
exit(1);
}
if(send(client_fd,&msg,sizeof(msg),0) < 0 )
{
perror("failed to send msg");
exit(1);
}
usleep(500);
if((fd=open(msg.filename,O_RDONLY)) < 0)
{
perror("failed to open file");
exit(1);
}
memset(buf,0,sizeof(buf));
while((num=read(fd,buf,sizeof(buf))) > 0)
if(send(client_fd,buf,num,0) <0)
{
perror("failed to send date");
exit(1);
}
if(num <0)
{
perror("failed to read");
exit(1);
}
printf("UpLoad OK!\n");
close(fd);
close(client_fd);
return ;
}