linux 网络编程 Tcp文件服务器

参考链接:http://blog.csdn.net/yanghaoran321/article/details/7882760

程序功能:

     客户端能够通过命令显示文件服务器上的文件,能够上传、下载文件等等功能;

在浏览原博主的代码后,作出一下修改:

  1.  将迭代服务器修改为 并发服务器
  2.  接受 服务器文件夹 文件列表 的缓冲区 增大,避免缓冲区溢出 stack smashing  detected
  3.  传参简化
  4.  设置套接字地址重用选项

  程序如下:

    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 ;
}



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值