使用TCP协议写的关于ftp_tcp上传文件下载文件显示文件的小项目(一对一)

server.c服务器端,

#include<stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <linux/in.h>  //sockaddr_in
#include <stdlib.h>
#include<string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define N 64
void  server_list(int acceptfd);
void  server_put(int  acceptfd,char *filename);
void  server_get(int acceptfd,char *filename);
int main(int argc, const char *argv[])
{
	//1) socket(),创建套接字文件,用于连接
    int sockfd,acceptfd;
    ssize_t  id;
	pid_t pids;
    if(argc<2)
	{
		printf("input a date %d,<端口号><IP>",argc);
		exit(-1);
	}
	sockfd = socket(AF_INET,SOCK_STREAM,0);
	if(sockfd < 0)
	{
		perror("socket failed.");
		exit(-1);
	}
	printf("socket ok.\n");

	//填充结构体sockaddr_in 
	struct sockaddr_in serveraddr;
	bzero(&serveraddr,sizeof(serveraddr));
	serveraddr.sin_family = AF_INET;            //填充协议 IPv4
	serveraddr.sin_port = htons(atoi(argv[1]));                 // 端口号 
	serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);  //IP任意的客户端都可以连接的服务器

	socklen_t addrlen = sizeof(serveraddr);

	//2) bind(),绑定,把socket()函数返回的文件描述符和IP、端口号进行绑定;
	if(bind(sockfd,(struct sockaddr *)&serveraddr,addrlen) < 0)
	{
		perror("bind failed.");
		exit(-1);
	}
	printf("bind ok.\n");
	
	//3) listen(), (监听)将socket()返回的文件描述符的属æ§,由主动变为被动;
	if(listen(sockfd,8) < 0)
	{
		perror("bind failed.");
		exit(-1);
	}
	printf("listen ok.\n");

	//4) accept(), 阻塞函数,阻塞等待å¢户端的连接请求,如果有客户端连接,
	//则accept()函数返回的文件描述符和数返回,返回一个用于通信的套接字文件;	
	acceptfd = accept(sockfd,NULL,NULL);
	printf("acceptfd ok.\n");

	char buf[N] = {0};
	char I;
	while(1)
	{
        
		    recv(acceptfd,buf,sizeof(buf),0);
			switch(buf[0])
			{
              case 'l':server_list(acceptfd);break;
              case 'p':server_put(acceptfd,buf+2);break;
			  case 'g':server_get(acceptfd,buf+2);break;
			  case 'q':exit(-1);break;
			  default:break;

			}
	}
    return 0;
}

//读取目录的内容
void   server_list(int acceptfd)
{
      char buf1[N]={0};
	  DIR *dir;
	  struct dirent *dp;
	  struct stat *p;
      dir=opendir(".");
	  while((dp=readdir(dir))!=NULL)//读取目录流
	  {
           if(strncmp(dp->d_name,".",1)==0)//屏蔽隐藏的文件 
           continue;
		   stat(dp->d_name,p);//获取文件的属性
           if(S_ISDIR(p->st_mode))
		   continue;
		   strcpy(buf1,dp->d_name);
           send(acceptfd,buf1 ,sizeof(buf1),0);//将读取文件的名字发送给客户端

	  }
	   strncpy(buf1,"quit",4);
       send(acceptfd,buf1,sizeof(buf1),0);
	   printf("server_ok\n");
}

//接受客户端上次的文件
void server_put(int acceptfd,char *filename)
{
    char buf1[N]={0};
	int fd;
	int ss;
    fd=open(filename,O_WRONLY|O_CREAT|O_TRUNC, 0666);//创建的文件名字
	while(1)
    {
       ss=recv(acceptfd,buf1,sizeof(buf1),0);//接受客户端发来的数据
	   if(strncmp(buf1,"quit\n",4)==0)
        break;
	  
	   write(fd,buf1,ss);
   }
   printf("server_ok\n");

}


//接收客户端的名字下载数据
void server_get(int acceptfd,char *filename)
{
   char buf1[N]={0};
   int   ss;
   int fd;
   fd=open(filename,O_RDONLY);//以只读的方式打开文件
   while(1)
   {  
	   ss=read(fd,buf1,sizeof(buf1));//读取文件的内容
            if(ss==0)
	   {
           break;
	   }
	   send(acceptfd,buf1,ss,0);
	   usleep(1000);//防止沾包,由于的传的太快,可能导致数据重复,所以进行延时
   }
   strcpy(buf1,"quit");
   send(acceptfd,buf1,sizeof(buf1),0);
   printf("server_ok\n");
}

client.c客户端

#include<stdio.h>  
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <stdlib.h>
#include<math.h>
#include <linux/in.h>
#include<string.h>
#include<string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

#define N  64 
void  client_list(int sockfd);
void  client_put(int sockfd,char *filename);
void  client_get(int sockfd,char *filename);
int main(int argc,char *argv[])
{
   //创建的一个socket描述符
   struct  sockaddr_in  addrs;

   int sockfd;
   if(argc<3)
   {
       printf("input a date %d<端口><IP>",argc);
	   exit(-1);
   }
   sockfd=socket(AF_INET,  SOCK_STREAM ,0);
   char buf[N];
   if(socket<0)
   {
	   perror("socket\n");
	   exit(-1);
   }
   //填写sockaddr_in 结构体
   bzero(&addrs,sizeof(addrs));//将结构体初始化为0
   addrs.sin_family=AF_INET;//协议IPV4
   addrs.sin_port=htons(atoi(argv[1]));//端口号将主机字节序到网络字节序
   addrs.sin_addr.s_addr=inet_addr(argv[2]);将32位的IP地址(十进制)转化为二进制的IP地址网络字节
   if(connect(sockfd, (struct sockaddr *)&addrs,sizeof(addrs))<0)
   {
       perror("connect\n");
	   exit(-1);
   }
   while(1)
   {    
	     printf("*******************************\n");
		 printf("************list***************\n");
		 printf("**********put filename*********\n");
		 printf("**********get filename*********\n");
		 printf("************quit***************\n");
         printf("input>>>>:");
	     fgets(buf,sizeof(buf),stdin);
         buf[strlen(buf)-1]='\0'; 
		 switch(buf[0])
		 {
			case 'l':client_list(sockfd);        break;
			case 'p':client_put(sockfd,buf+4);   break;
		    case 'g':client_get(sockfd,buf+4);   break;
			case 'q':exit(-1);     break;
		    default:break;
		}

     
   }
   return 0;
}

//显示目录的文件名字
void client_list(int  sockfd)
{
	 char buf1[N]={0};
	 sprintf(buf1,"l");
	 send(sockfd,buf1,sizeof(buf1),0);
	 while(1)
	 {
		 //接受服务发过来的数据
         recv(sockfd,buf1,sizeof(buf1),0);
	     if(strncmp(buf1,"quit",4)==0)
		     break;
		 printf("%s ",buf1);

	 }
     printf("client_ok\n");
}


//上传文件
void  client_put(int sockfd,char *filename)
{
    char  buf1[N]={0};
	int ss;
	int fd;
	sprintf(buf1,"p %s",filename);
    send(sockfd,buf1,sizeof(buf1),0);//进行数据的发送
    fd=open(filename,O_RDONLY);//以只读的方式进行读取
	while(1)
    {    
	    ss=read(fd,buf1,sizeof(buf1));//读文件里的内容
        if(ss==0)
		{
			break;
		}
        send(sockfd,buf1,ss,0);
		usleep(100000);
    }
	strcpy(buf1,"quit");
	send(sockfd,buf1,sizeof(buf1),0);
	printf("client_ok\n");
}

//下载文档
void  client_get(int sockfd,char *filename)
{
    char buf1[N]={0};
	int fd;
	int ss;
	sprintf(buf1,"g %s",filename);
	send(sockfd,buf1,sizeof(buf1),0);//进行数据的发送
    fd=open(filename,O_WRONLY|O_CREAT|O_TRUNC,0666);//以读写的打开,并且写入数据*/
	while(1)
	{
       ss=recv(sockfd,buf1,sizeof(buf1),0);
	   if(strncmp(buf1,"quit\n",4)==0)
	   {
		   break;
	   }
	   write(fd,buf1,ss);
	}
    printf("client_ok\n");
}
	
	

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值