项目:基于TCP的文件传输系统

项目介绍:
模拟FTP原理:客户端连接服务器后,向服务器发送一个文件。文件名可以通过参数指定,服务器端接收客户端传来的文件(文件名随意),如果文件不存在自动创建文件,如果文件存在,那么清空文件然后写入。
项目技术点:
TCP客户端和服务器的搭建
目录IO获取路径下的文件名用于展示
标准IO或文件IO的打开,读取以及写入操作文件
TCP协议需要考虑如何防止粘包的发生(建议发送和接收的大小一致)
参考内容:
(1)client.c
cpp 复制代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/un.h>
typedef struct sockaddr_in addr_in_t;
typedef struct sockaddr addr_t;
typedef struct sockaddr_un addr_un_t;

int main(int argc, const char* argv[])
 {
   //1.socket
   int sockfd = socket(AF_INET,SOCK_STREAM,0);
   if(sockfd < 0)
   {
    perror("socket is error:");
    return -1;
   }
   //绑定套接字
   struct sockaddr_in saddr,caddr;
   saddr.sin_family = AF_INET;
   saddr.sin_port = htons(atoi(argv[2]));
   saddr.sin_addr.s_addr = inet_addr(argv[1]);
   
   char buf[128];
   if(connect(sockfd,(struct sockaddr *)&saddr,sizeof(saddr)) < 0)
   {
    perror("connect is error:");
    return -1;
   }
   while(1)
   {
    //选择功能
      printf("功能1--------list--------\n");
      printf("功能2--------put--------\n");
      printf("功能3--------get--------\n");
      printf("功能4--------quit-------\n");

      printf("请选择功能:\n");
      int num;
      scanf("%d",&num);
      //显示该目录下的所有文件
      if(num == 1)
      {
        send(sockfd,&num,4,0);
        while(1)
        {
          char stu[128];
          int flag = 1;
          send(sockfd,&flag,4,0);
          int res = recv(sockfd,stu,sizeof(stu),0);
          printf("%s\n",stu);
          if(stu[0] == 0)
          {
            break;
          }
        }
      }
      //上传文件
      else if(num  == 2)
      {
        printf("请输入要上传的文件名\n");
        send(sockfd,&num,4,0);
        char stu[512];
        scanf("%s",stu);
        //以只读形式打开已有文件
        int fd = open(stu,O_RDONLY);
        //判断文件是否存在
        if(access(stu,F_OK) == -1)
        {
            printf("输入文件不存在,请重新输入:\n");
            break;
        }       
        while(1)
        {
          char s[512];
          int flag = 0;
          int res = read(fd,s,sizeof(s));
          if(res == 0){break;}
          send(sockfd,s,sizeof(s),0);
          recv(sockfd,&flag,4,0);
        }
         printf("上传成功\n");
      }
      //下载文件
      else if(num == 3)
      {
        send(sockfd,&num,4,0);
        printf("请输入要下载的文件\n");
        char c[32];
        scanf("%s",c);
        if(c[strlen(c)-1] == '\n')
           c[strlen(c)-1] = '\0';   
        send(sockfd,c,32,0); 
        //创建新的文件并打开 
        int fd = open(c,O_WRONLY | O_TRUNC | O_CREAT,0666);
        char ct[256]="";  
        while(1)
        {
          int flag = 1;
          int res = recv(sockfd,ct,sizeof(ct)-1,0);
          if(strlen(ct)==0)
		  {
			  break;
		  }
          //写入新的文件内,下载成功
          write(fd,ct,strlen(ct));
        }
         printf("下载成功\n");
         //关闭文件
         close(fd);
      }
      //退出(仅客户端),服务端仍然等待其他客户端连接
      else if(num == 4)
      {
        send(sockfd,&num,4,0);  
      }
      else
      {
        printf("抱歉,您输入的数字有误,请重新输入\n");
      }
   }
   close(sockfd);   
    return 0;
}
(2)server.c
cpp 复制代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/un.h>
#include <dirent.h>

typedef struct sockaddr_in addr_in_t;
typedef struct sockaddr addr_t;
typedef struct sockaddr_un addr_un_t;

int main(int argc, const char* argv[]) 
{
    //1.socket
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd < 0)
    {
        perror("socket is error:");
        return -1;
    }
 //绑定套接字
 struct sockaddr_in saddr,caddr;
 saddr.sin_family = AF_INET;
 saddr.sin_port = htons(atoi(argv[1]));
 saddr.sin_addr.s_addr = inet_addr("0.0.0.0");
 int len = sizeof(caddr);

 char buf[128];
 if(bind(sockfd,(struct sockaddr *)&saddr,sizeof(saddr)) < 0)
 {
    perror("bind is error:");
    return -1;
 }
 if(listen(sockfd,5) < 0)
 {
    perror("listen is error:");
    return -1;
 }
 while(1)
 {
   printf("-------等待客户端连接-----------\n");
   int acceptfd = accept(sockfd,(struct sockaddr *)&caddr,&len);
   if(acceptfd < 0)
   {
      perror("accept is error:");
      return -1;
   }
   printf("-------客户端连接成功------------\n");
   while(1)
   {
      int num;
      printf("请选择功能\n");
      int res = recv(acceptfd,&num,sizeof(num),0);

      if(res < 0)
      {
         perror("recv is error:");
         return -1;
      }
      else if(res == 0)
      {
         printf("recv is exit:\n");
         break;
      }
      else
      {
         if(num == 1)
         {
            struct dirent *file = NULL;
            DIR *dp = opendir("./");
            if (dp == NULL) 
            {
            perror("opendir is error:");
            return -1;
            }
          while((file = readdir(dp)) != NULL) 
               {
                  if(file->d_name[0] == '.' )
                  {
                     continue;
                  }
                  int flag = 0;
                  recv(acceptfd,&flag,4,0);
                  send(acceptfd,file->d_name,128,0);
               }
               int flag = 0;
               recv(acceptfd,&flag,4,0);
               char bb[128] ={0};
               send(acceptfd,bb,128,0);
         }
         else if(num == 2)
         {
            //新建文件并打开
            int fd = open("./3",O_WRONLY | O_TRUNC | O_CREAT,0666);
            while(1)
            {
             char ss[512];
             int flag = 1;
             //接收内容
             int res = recv(acceptfd,ss,sizeof(ss),0);
             if(res == 0){break;}
             //写入
             write(fd,ss,strlen(ss));
             send(acceptfd,&flag,4,0);                         
            }
            //关闭文件
            close(fd);
         }
         else if(num == 3)
         {
            printf("进入功能:\n");
            char c[32] = {0};
            recv(acceptfd,c,32,0);
            printf("%s\n",c);
            int fd = open(c,O_RDONLY);

            while(1)
            {
			  char st[256]="";
			   int flag=1;   
               int res = read(fd,st,sizeof(st)-1);
               //阻塞性接收并传送回文件数据与内容
                if(res == 0)
                {
				    char dt[256]="";  
               	    send(acceptfd,dt,sizeof(dt)-1,0);
				    break;
                }
			    if(flag==1)
			    {
               	    send(acceptfd,st,sizeof(st)-1,0);			
			    }
            }
         }
         else if(num == 4)
         {
            break;
         }
         else
         {
            printf("抱歉,您输入的数字有误,请重新输入\n");
         }   
   }
   }
 }
close(sockfd);
return 0;
}
相关推荐
Ljw...3 小时前
IP协议(网络)
网络·网络协议·tcp/ip·ip协议
网安-轩逸4 小时前
IPv4地址表示法详解
开发语言·php
007php0079 小时前
linux服务器上CentOS的yum和Ubuntu包管理工具apt区别与使用实战
linux·运维·服务器·ubuntu·centos·php·ai编程
我要学编程(ಥ_ಥ)10 小时前
初始JavaEE篇 —— 网络原理---传输层协议:深入理解UDP/TCP
java·网络·tcp/ip·udp·java-ee
百事可乐☆10 小时前
全局webSocket 单个页面进行监听并移除单页面监听
网络·websocket·网络协议
hgdlip11 小时前
IP属地和所在地不一致什么意思?怎么换成另外一个地方的
服务器·网络协议·tcp/ip
忆源11 小时前
Linux高级--2.4.5 靠协议头保证传输的 MAC/IP/TCP/UDP---协议帧格式
网络协议·tcp/ip·udp
搬砖的果果12 小时前
爬虫代理服务要怎么挑选?
网络·爬虫·网络协议·tcp/ip
胡译胡说14 小时前
还记得十几年前 PHP 那个 0x00+2=4 的 Bug 吗
php·debug·编译原理
畅联云平台14 小时前
美畅物联丨如何在视频汇聚平台上添加RTMP主动推流设备?
网络协议·音视频