Linux网络编程应用 文件传输:利用TCP、base64、C语言实现电脑与电脑、电脑与开发板之间进行文件传输(可传输文档图片视频任意文件)

准备工作

1、base64的加密与解密的方法有很多种,可以直接使用Linux自带的base64命令,也可以使用一些base64库,或者base64源代码等等。

2、这里我使用的是在Gethub官网上下载的一个评价最高的base64包,先下载一下:

我先说明一下,这个包代码结构比较复杂,编译也需要更改一些东西,如果是大神建议直接下载第一个,可自行编译得到所需库文件,小白建议直接下载我编译好的两个库文件,也就是第二、三个。

(一)源base64包:
链接:https://pan.baidu.com/s/16cC4qOVCiascjvwuEbHlpg
提取码:lgi0

(二)64位系统下下载:
链接:https://pan.baidu.com/s/1mbTFmoPZsBEylw2I9M4uEA
提取码:zbxn

(三)32位arm开发板下载:
链接:https://pan.baidu.com/s/13Qop78nCKk-RHFLrLBeLMA
提取码:a6ch

电脑与电脑之间的传输

一、首先确定两台电脑是否处于同一局域网内

1、可以在教室或者工作室插上处于同一局域网的网线
2、可以利用一根网线实现电脑与电脑直连

二、下载好第二个base64包

你将会得到这样两个文件

在这里插入图片描述
使用它时只需要包含 libbase64.h 头文件,编译时链接静态库即可

三、编写测试代码

测试这个base64包是否能够编码与解码

#include <stdio.h>
#include <libbase64.h>
#include <string.h>

int main(int argc,const char **argv)
{
    char buf[] = "12345";
    char base_buf[100];

    //base64加密
    size_t len;
    bzero(base_buf,strlen(base_buf));
    base64_encode(buf,strlen(buf),base_buf,&len,0);
    printf("base_buf:%s \n",base_buf);

    
    //base64解码
    bzero(buf,strlen(buf));
    base64_decode(base_buf,strlen(base_buf),buf,&len,0);
    printf("解码后:%s\n",buf);

    return 0;
}

编译命令:gcc main.c -o main -L. lbase64
运行:
在这里插入图片描述

三、编写代码
代码需要依赖:libbase64.a、libbase64.h下载第二个文件包即可。
需要两个代码,一个是发送文件,一个是接收文件

接收方:
recv.c

/*TCP客户端*/
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include <fcntl.h>
#include <libbase64.h>

#define SERV_PORT 6666

void sys_err(const char *str)
{
	perror(str);
	exit(1);
}

int main(int argc, char *argv[])
{
	if(argc != 2)
	{
		printf("input error:try './recv 192.168.18.66'\n");
		exit(0);
	}
    int cfd;
    int conter = 10;
    char buf[BUFSIZ];
    
    struct sockaddr_in serv_addr;          //服务器地址结构

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERV_PORT);
    //inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr.s_addr);
    inet_pton(AF_INET, argv[1], &serv_addr.sin_addr);

    cfd = socket(AF_INET, SOCK_STREAM, 0);
    if (cfd == -1)
        sys_err("socket error");

    int ret = connect(cfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
    if (ret != 0)
        sys_err("connect err");

    struct stat sta;
    char name[64];
    read(cfd,name,sizeof(name));
    printf("文件名:%s\n",name);
    read(cfd,&sta.st_size,sizeof(sta.st_size));
    printf("文件大小:%ld\n",sta.st_size);

    //准备文件
    int fd = open(name,O_WRONLY|O_CREAT|O_APPEND|O_TRUNC,0666);

    char *file_buf = (char *)malloc(sta.st_size+100);
    char *decode_file_buf = (char *)malloc(sta.st_size*3/4+100);

    //read(cfd,file_buf,sta.st_size);
    int n_read;
    unsigned long total=0;
    while(1)
    {
        
        if(sta.st_size-total>=10*1024)
        {
            n_read = read(cfd,file_buf+total,10*1024);
            total += n_read;
            printf("读出%d字节:\n",n_read);
        }else if(sta.st_size-total<10*1024)
        {
            n_read = read(cfd,file_buf+total,sta.st_size-total);
            total += n_read;
            
            printf("读完了:一共%ld字节\n",total);
            break;
        }
        if(n_read < 0)
        {
            printf("读取出错\n");
            exit(0);
        }
    }
    //解码
    long len;
    base64_decode(file_buf,sta.st_size,decode_file_buf,&len,0);
    printf("解码后文件大小:%ld字节\n",len);sleep(1);
    //开始写入文件
    write(fd,decode_file_buf,len);
   

    close(fd);
    close(cfd);


    close(cfd);

	return 0;
}


发送方:
send.c

/*TCP服务器*/
#include <stdio.h>
#include <ctype.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>


#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include <fcntl.h>
#include <libbase64.h>

#define SERV_PORT 6666

void sys_err(const char *str)
{
    perror(str);
    exit(1);
}

int main(int argc, char *argv[])
{
    if(argc != 2)
    {
        printf("输入:./main a.txt\n");
        exit(1);
    }
    int lfd = 0, cfd = 0;
    int ret, i;
    char buf[BUFSIZ], client_IP[BUFSIZ];

    struct sockaddr_in serv_addr, clit_addr;  
    socklen_t clit_addr_len;				  

    serv_addr.sin_family = AF_INET;				
    serv_addr.sin_port = htons(SERV_PORT);		
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);	

    lfd = socket(AF_INET, SOCK_STREAM, 0);		
    if (lfd == -1) {
        sys_err("socket error");
    }
    int on = 1;
    setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

    bind(lfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));

    listen(lfd, 128);


    clit_addr_len = sizeof(clit_addr);		
    cfd = accept(lfd, (struct sockaddr *)&clit_addr, &clit_addr_len);	
    if (cfd == -1)
        sys_err("accept error");

    printf("client ip:%s port:%d\n", 
            inet_ntop(AF_INET, &clit_addr.sin_addr.s_addr, client_IP, sizeof(client_IP)), 
            ntohs(clit_addr.sin_port));		

    int fd = open(argv[1],O_RDONLY,0666);
    if(fd == -1){
        perror("open failed");
        exit(0);
    }

    struct stat sta;
    if(stat(argv[1],&sta)==-1){
        perror("stat failed");
        exit(0);
    }

    printf("文件:%s\n",argv[1]);
    printf("大小:%ld\n",sta.st_size);
    
    char *file_buf = (char *)malloc(sta.st_size+100);
    char *encode_file_buf = (char *)malloc(sta.st_size*4/3+100);
    //read(fd,file_buf,sta.st_size);
    int n_read;
    unsigned long total=0;
    while(1)
    {
        lseek(fd,total,SEEK_SET);
        n_read = read(fd,file_buf+total,10*1024);
        total += n_read;
        if(n_read > 0)
        {
            printf("读出%d字节:\n",n_read);
        }else if(n_read == 0)
        {
            printf("读完了:一共%ld字节\n",total);
            break;
        }else if(n_read < 0)
        {
            printf("读取出错\n");
            exit(0);
        }
    }
    //编码
    long len;
    base64_encode(file_buf,sta.st_size,encode_file_buf,&len,0);
    //告诉对方文件名
    write(cfd,argv[1],strlen(argv[1]));
    usleep(10000);
    //告诉对方要发多少字节过来
    write(cfd,&len,sizeof(len));
    usleep(10000);
    printf("编码后文件大小:%ld字节\n",len);
    //开始发送文件
    //write(cfd,encode_file_buf,len);
    int n_write;
    unsigned long w_total=0;
    while(1)
    { 
        //sleep(1);
        if(len-w_total>=10*1024)
        {
            n_write = write(cfd,encode_file_buf+w_total,10*1024);
            w_total += n_write;
            printf("发送%d字节:\n",n_write);
        }
        else if(len-w_total<10*1024)
        {
            n_write = write(cfd,encode_file_buf+w_total,len-w_total);
            w_total += n_write;
            printf("发完了:一共%ld字节\n",w_total);
            break;
        }
        if(n_write < 0)
        {
            printf("发送出错\n");
            exit(0);
        }
    }

    close(lfd);
    close(cfd);

    return 0;
}


运行:
由于只有一台电脑,就直接连接本地回环地址127.0.0.1,发送到本地。
两台电脑也做过实验,发送成功。
(注意看下面文件位置与执行命令格式)
在这里插入图片描述
可以看到文件已经发送过去了
在这里插入图片描述

文件也是正常的,没有丝毫损坏。
在这里插入图片描述

电脑与开发板之间的传输

不多说了,这个代码耗费博主半条命研究出来的,直接分享给大家,记得点赞支持。

百度网盘链接:https://pan.baidu.com/s/1R0iVbMEDxACbsPxXCE3QCA
提取码:p1t6

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

化作尘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值