项目:基于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;
}
相关推荐
王二端茶倒水14 小时前
商业 WiFi 不是免费上网,而是门店数字化的入口
网络协议
两个人的幸福1 天前
Windows 桌面应用自研 PHP 队列(下):完整代码与六大工程化优化
php
BingoGo4 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
JaguarJack4 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
用户3074596982074 天前
PHP 扩展——从入门到理解
php
鹏仔先生5 天前
拷贝漫画APP下载页PHP程序,后台带免费AI写作
php
云水一下5 天前
从零开始学 PHP 系列(一):PHP 的前世今生与开发环境搭建
开发语言·php
treesforest5 天前
AI安全系统如何识别异常访问?IP风险识别正在成为关键能力
网络·人工智能·tcp/ip·安全·web安全
xingpanvip5 天前
星盘接口开发文档:本命盘接口指南
android·开发语言·css·php·lua
程序员mine5 天前
HTTPS-TLS加密与证书完全指南(中)
网络协议·https·ssl