Linux下利用TCP完成简单的文件传输(单个文件或内容均为单个文件的单个文件夹)

实现在Linux下利用TCP完成简单的文件传输,

但传输内容仅支持:

  1. 单个文件
  2. 内容均为单个文件的单个文件夹

在Linux下,设置2个文件夹,其中一个放server.c,作为服务器端,另一个放client.c,作为客户端。

先打开服务器端server.c,再打开客户端client.c。

客户端发送文件,文件接收到服务器根目录。

在传输文件里的各个单个文件时,想使用itoa函数atoi函数先传输文件的大小,客户端将文件大小转换为字符串形式发送给服务器端,服务器端接受该字符串信息后在转换为数字,获取待接收文件的大小。但Linux下没有itoa函数atoi函数,需要自己实现,于是参考了其他人的现成的代码,如有侵权,请告知我删除!:

atoi()函数:https://blog.csdn.net/yue_jijun/article/details/81530906

itoa()函数:https://blog.csdn.net/knowledgeaaa/article/details/38400355

客户端client.c代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <dirent.h>
#define PORT 12345
#define IP "127.0.0.1"
#define BUFFSIZE 1024
void my_itoa(unsigned long val, char *buf, unsigned radix)
{
	char   *p;                 /*   pointer   to   traverse   string   */
	char   *firstdig;          /*   pointer   to   first   digit   */
	char   temp;                             /*   temp   char   */
	unsigned   digval;         /*   value   of   digit   */
	p = buf;
	firstdig = p;              /*   save   pointer   to   first   digit   */
	do
	{
		digval = (unsigned)(val % radix);
		val   /=   radix;               /*   get   next   digit   */

		/*   convert   to   ascii   and   store   */
		if (digval > 9)
			*p++ = (char)(digval - 10 + 'a');     /*   a   letter   */
		else
			*p++ = (char)(digval + '0');                 /*   a   digit   */
	}
	while (val > 0);
	/*   We   now   have   the   digit   of   the   number   in   the   buffer,   but   in   reverse
	      order.     Thus   we   reverse   them   now.   */
	*p-- = '\0';     /*   terminate   string;   p   points   to   last   digit   */
	do
	{
		temp = *p;
		*p = *firstdig;
		*firstdig = temp;      /*   swap   *p   and   *firstdig   */
		--p;
		++firstdig;                   /*   advance   to   next   two   digits   */
	}
	while (firstdig < p);       /*   repeat   until   halfway   */
}
int main()
{
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    inet_pton(AF_INET, IP, &(addr.sin_addr.s_addr));
    char filename[100];
    char foldername[100];
    char buffer[BUFFSIZE];

    int fileType;//0:Single file;1:folder
    char fileTypeBuffer[1];

    if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
    {
        printf("error\n");
    }
    else
    {
        printf("connect success\n");

        //选择传输文件的类型:
        printf("Please select the file type to transfer!\n");
        printf("0:Single file , 1:folder\n");
        scanf("%d",&fileType);
        if(fileType == 0)//Single file
        {
            fileTypeBuffer[0]='0';
            //输入要传送的文件名,文件确保在根目录下
            printf("input filename:\n");
            scanf("%s", filename);
            FILE* fp = fopen(filename, "r");
            if (fp == NULL)
            {
                printf("file not exist\n");
            }
            else
            {
                printf("transport start\n");
                send(fd,fileTypeBuffer,1,0);//传送文件类型
                //先传送文件名,后传送文件内容
                send(fd, filename, sizeof(filename), 0);
                int t;
                while ((t = fread(buffer, sizeof(char), BUFFSIZE, fp)) > 0)
                {
                    send(fd, buffer, t, 0);
                }
                printf("transport finish\n");
            }
            fclose(fp);
        }
        else if(fileType == 1) //folder
        {
            fileTypeBuffer[0]='1';
            send(fd,fileTypeBuffer,1,0);//传送文件类型
            printf("input foldername:\n");
            scanf("%s", foldername);
            DIR * dp;
            struct dirent *fp;
            FILE* fp_fire;
            dp = opendir(foldername);
            if (!dp)
            {
                fprintf(stderr,"open directory error\n");
                return 0;
            }
            send(fd, foldername, sizeof(foldername), 0);//传送文件夹名
            char is_have_file[1];
            is_have_file[0] = 'T';
            while (fp = readdir(dp))
            {
                printf("filename:%-10s\td_info:%ld\t d_reclen:%us\n",
                       fp->d_name,fp->d_ino,fp->d_reclen);
                if(fp->d_name[0] == '.' && fp->d_name[1] == 0){
                    continue;
                }
                else if(fp->d_name[0] == '.' && fp->d_name[1] == '.' && fp->d_name[2] == 0){
                    continue;
                }
                is_have_file[0] = 'T';
                send(fd,is_have_file,1,0);//传送“还有其他文件”的信息
                printf("send: is_have_file: \"%s\"\n",is_have_file);
                send(fd,fp->d_name, 100,0);//传送文件名称
                printf("send:fp->d_name: \"%s\"\n",fp->d_name);
                char path[100]="./";
                strcat(path, foldername);
                strcat(path, "/");
                strcat(path, fp->d_name);
                printf("path: \"%s\"\n",path);
                fp_fire = fopen(path, "r");
                int t;
                char file_len[100];
                t = fread(buffer, sizeof(char), BUFFSIZE, fp_fire);
                my_itoa(t,file_len,10);
                printf("t = %d , file_len = \"%s\"\n",t,file_len);
                send(fd, file_len, 100, 0);
                send(fd, buffer, t, 0);
                fclose(fp_fire);
            }
            is_have_file[0] = 'F';
            send(fd,is_have_file,1,0);//传送“没有其他文件”的信息
            closedir(dp);
        }
        else
        {
            printf("invalid input!\n");
            return 0;
        }
    }
    close(fd);
    return 0;
}

服务器端server.c代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/stat.h>
#define PORT 12345
#define LISTENQ 10
#define BUFFSIZE 1024
int my_atoi(const char *str)
{
	int flag = 1;
	int result = 0;

	if(str == NULL)
		return 0;
	while(*str == ' ' || *str == '\t')
		str++;

	if(*str == '-')
	{
		flag = -1;
		str++;
	}

	while(*str != '\0')
	{
		if(*str >= 0 && *str <= '9')
			result = result*10 + (*str - '0');

		else
		{
			break;
		}

		str++;
	}

	return result * flag;
}
int passiveTCP()  //封装 tcp 的建立
{
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    addr.sin_addr.s_addr = INADDR_ANY;
    bind(fd, (struct sockaddr*)&addr, sizeof(addr));
    listen(fd, LISTENQ);
    return fd;
}
int main()
{
    int fd = passiveTCP();
    char filename[100];
    char foldername[100];
    char buffer[BUFFSIZE];

    int fileType;//0:Single file;1:folder
    char fileTypeBuffer[1];

    while (1)
    {
    //将文件接收到服务器根目录
        int fd_;
        struct sockaddr_in addr_;
        int len = sizeof(addr_);
        if ((fd_ = accept(fd, (struct sockaddr*)&addr_, &len)) < 0)
        {
            printf("error\n");
        }
        else
        {
            printf("connect success\n");
            recv(fd_, fileTypeBuffer,1, 0);//接收文件类型
            if(fileTypeBuffer[0] == '0') //Single file
            {
                recv(fd_, filename, sizeof(filename), 0);//接收文件名
                FILE *fp = fopen(filename, "w");//创建文件
                printf("transport start\n");
                int t;
                while ((t = recv(fd_, buffer, BUFFSIZE, 0)) > 0)
                {
                    printf("--in_while--\n");
                    fwrite(buffer, sizeof(char), t, fp);//After test,this execute only onces
                }
                printf("transport finish\n");
                fclose(fp);
            }
            else if(fileTypeBuffer[0] == '1') //folder
            {
                printf("transport folder start\n");
                recv(fd_, foldername, sizeof(foldername), 0);//接收文件夹名
                printf("recv: foldername: \"%s\"\n",foldername);
                mkdir(foldername,0777);//创建文件夹
                char is_have_file[1];
                while(1){
                    printf("----while(1)----\n");//test
                    recv(fd_, is_have_file, 1, 0);//接收"还有没有文件"的信息
                    printf("is_have_file = \"%c\"\n",is_have_file[0]);//test
                    if(is_have_file[0] != 'T'){
                        break;
                    }
                    recv(fd_, filename, 100, 0);//接收文件名//XXX:sizeof(filename)???
                    printf("in while_1 : filename : \"%s\"\n",filename);
                    if(filename[0] == '.' && filename[1] == 0){
                        continue;
                    }
                    else if(filename[0] == '.' && filename[1] == '.' && filename[2] == 0){
                        continue;
                    }
                    char path[100]="./";
                    strcat(path, foldername);
                    strcat(path, "/");
                    strcat(path, filename);
                    printf("path: \"%s\"\n",path);//After test,this path is OK!
                    FILE *fp = fopen(path, "w");//创建文件
                    int t;
                    char file_len[100];
                    recv(fd_, file_len, 100, 0);
                    printf("file_len = \"%s\"\n",file_len);
                    int f_len = my_atoi(file_len);
                    printf("f_len = %d\n",f_len);
                    t = recv(fd_, buffer, f_len, 0);
                    printf("t = %d\n",t);
                    fwrite(buffer, sizeof(char), t, fp);
                    fclose(fp);
                }
                printf("transport folder finish\n");
            }
            else{
                printf("Error:fileTypeBuffer ERROR!");
            }
        }
        close(fd_);
    }
    close(fd);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值