0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux开发_文件发送与接收

DS小龙哥-嵌入式技术 2022-09-17 15:23 次阅读

【摘要】 介绍文件发送、文件接收、线处理服务器接收、获取天气预报等知识点。

任务1:网络编程

1.1 练习题说明

1.​实现TCP服务器与TCP客户端之间的基本通信,收发数据 (按照上课的思路流程看函数文档)

2.​实现TCP服务器与TCP客户端之间的文件传输。(单个文件传输)

验证方式: (1) 同一台电脑演示 (2)同桌之间演示

考虑的问题:

(1)​网络的传输环境,考虑应答问题

(2)​数据丢包之后如何处理? 可以重发

(3)​超时处理

(4)​服务器与客户端之间连接断开处理。(客户端和服务器两边都需要重新连接)

文件传输可以在广告机中使用。

(5)​每个数据的单位: 分包发送

(扩展要求): 显示接收进度百分比,显示接收的文件名称,推荐: 定义结构体(使用数据结构)

3.​(扩展)实现TCP服务器与TCP客户端之间的目录传输(一级目录)。

4.​(扩展)实现网络聊天室(模仿QQ群发送消息的效果)

(1)​加入进去的成员都是客户端

(2)​服务器负责给各个客户端转发消

​一般情况下,推荐最大每次传输的字节数不超过1024字节。

(1)文件发送客户端

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

/*
TCP客户端:
1. sockt创建套接字
2. 连接服务器
*/
int socket_cfd; /*保存客户端套接字*/
int main(int argc,char **argv)
{
	if(argc!=4)
	{
		printf("./server <192.168.xx.xx 服务器的IP地址> <服务器端口号> <文件名称>\n");
		exit(-1);
	}
	
	FILE *file=fopen(argv[3],"wb");
	if(file==NULL)
	{
		printf("文件创建失败!");
		exit(0);
	}
	
	int err; //存放返回值状态
	/*1. 创建套接字*/
	socket_cfd=socket(AF_INET,SOCK_STREAM,0);
	if(socket_cfd<0)
	{
		printf("服务器端创建失败!\n");
		exit(-1);
	}
	
	/*2.连接服务器*/
	struct sockaddr_in ServerAddr;
	ServerAddr.sin_family=AF_INET; //IPV4协议
	ServerAddr.sin_port=htons(atoi(argv[2]));      //服务器的端口号 最大值65535
	ServerAddr.sin_addr.s_addr=inet_addr(argv[1]); //IP地址赋值
	
	err=connect(socket_cfd,(const struct sockaddr *)&ServerAddr,sizeof(struct sockaddr));
	if(err!=0)
	{
		printf("服务器连接失败!\n");
		exit(-1);
	}
	
	/*3. 收发数据: 接收服务器发送的数据*/
	char rx_buff[100];
	fd_set readfds; //存放读事件
	int data;
	int ack=666;
	while(1)
	{
		FD_ZERO(&readfds); //清空文件描述符
		FD_SET(socket_cfd,&readfds); //添加需要监控的文件描述符 
		data=select(socket_cfd+1,&readfds,NULL,NULL,NULL);
		if(data>0)
		{
			err=read(socket_cfd,rx_buff,100);
			if(err==0 && data==1)
			{
				printf("服务器已经与客户端断开连接!\n");
				break;
			}
			fwrite(rx_buff,1,err,file);//写入数据
			printf("客户端成功接收%d个字节\n",err);
			
			write(socket_cfd,&ack,4); //发送应答信号。
		}
	}
	close(socket_cfd);
	fclose(file);
	return 0;
}

(2)文件发送客户端

#include 
#include 
#include 
#include 
#include 
#include 

/*
TCP服务器:
1. sockt创建套接字
2. bind绑定端口
3. 设置监听的数量
4. 等待客户端连接
*/
int socket_sfd; /*保存了服务器端的套接字*/
int socket_cfd; /*已经连接成功的客户端套接字*/

/*
服务器是发送端
*/
int main(int argc,char **argv)
{
	if(argc!=4)
	{
		printf("./server <192.168.xx.xx 本地IP地址> <服务器端口号> \n");
		exit(-1);
	}
	
	FILE *file=fopen(argv[3],"rb");
	if(file==NULL)
	{
		printf("文件打开失败!\n");
		exit(0);
	}
	
	int err; //存放返回值状态
	/*1. 创建套接字*/
	socket_sfd=socket(AF_INET,SOCK_STREAM,0);
	if(socket_sfd<0)
	{
		printf("服务器端创建失败!\n");
		exit(-1);
	}
	
	/*2. 绑定端口*/
	struct sockaddr_in ServerAddr;
	ServerAddr.sin_family=AF_INET; //IPV4协议
	ServerAddr.sin_port=htons(atoi(argv[2]));      //服务器的端口号 最大值65535
	ServerAddr.sin_addr.s_addr=inet_addr(argv[1]); //IP地址赋值
	err=bind(socket_sfd,(const struct sockaddr *)&ServerAddr,sizeof(struct sockaddr));
	if(err!=0)
	{
		printf("服务器端 端口绑定失败!\n");
		exit(-1);
	}
	
	/*3. 设置监听的数量*/
	listen(socket_sfd,10);
	
	/*4. 等待客户端连接*/
	struct sockaddr_in ClientAddr; //存放已经连接成功客户端信息
	socklen_t addrlen=sizeof(struct sockaddr);    //客户端的地址长度
	socket_cfd=accept(socket_sfd,(struct sockaddr *)&ClientAddr,&addrlen);
	if(socket_cfd<0)
	{
		printf("服务器端,连接客户端失败!\r\n");
		exit(-1);
	}
	
	/*打印一些客户端的信息*/
	printf("成功连接的客户端端口号:%d\n",ntohs(ClientAddr.sin_port));
	printf("成功连接的客户端IP地址:%s\n",inet_ntoa(ClientAddr.sin_addr));
	
	/*5. 收发数据 :服务器给客户端发送10个字节的数据*/
	char tx_buff[100];
	int len;
	int ack;
	while(1)
	{
		len=fread(tx_buff,1,100,file);
		printf("服务器成功发送:%d 字节\r\n",len);
		err=write(socket_cfd,tx_buff,len);
		while(1)
		{
			err=read(socket_cfd,&ack,4);  //等待客户端的应答
			if(err>0&&ack==666)
			{
				break;
			}
		}	
		if(len!=100)break;
	}
	close(socket_sfd);
	fclose(file);
	return 0;
}

文件名称>

任务2:线程编程

#include

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,

void *(*start_routine) (void *), void *arg);

Compile and link with -pthread.

-lpthread

理解: 一个线程就是一个while(1)。

[root@wbyq linux-share-dir]# gcc app.c

/tmp/cccOs4TK.o: In function `main':

app.c:(.text+0x69): undefined reference to `pthread_create'

app.c:(.text+0x8d): undefined reference to `pthread_create'

collect2: ld 返回 1

[root@wbyq linux-share-dir]# gcc app.c -lpthread

练习:

1.​学习线程的基本使用

2.​实现一个服务器实现多个客户端的连接,实现通信。

思路: 一个客户端就是一个独立的线程。

3.​扩展练习: 实现服务器同时对多个客户端进行文件发送。

(1)​服务器连接上一个客户端就创建一个线程。

(2)​线程的函数需要写几个? 1个

1个函数需要考虑的问题: 函数的可重入性能!

需要考虑到资源抢占! 使用信号量!

1.​CRC16、CRC32校验、

2.​和校验 ”abcd <校验和>” -->和

3.​异或校验。 (1) 文件加密解码

(2) 不添加三个变量,将两个变量的值交换

int a=666; int b=888;

4.​MD5值校验。

客户端:

#include 
#include           /* See NOTES */
#include 
#include    //使用大小端转换函数. find /
#include 
/*服务器端口号定义*/
#define P_host 8080

//  ./app   192.168.18.3
/*TCP客户端代码*/
int main(int argc,char *argv[])
{
	  if(argc!=2)
	  {
	  	  printf("参数错误:./app <服务器IP地址>\n");
	  		return -1;
	  }
	 int clientfd;
	 struct sockaddr_in server_address;     //存放服务器的IP地址信息
	 memset(&server_address,0,sizeof(struct sockaddr_in)); //初始化内存空间
	 server_address.sin_family=AF_INET;            //IPV4协议
	 server_address.sin_port=htons(P_host);        //端口号赋值
	 server_address.sin_addr.s_addr=inet_addr(argv[1]);    //本地IP地址
	 /*1 .创建套接字*/
    clientfd=socket(AF_INET,SOCK_STREAM,0);
   if(clientfd<0)
   	{
   	    printf("客户端网络套接字创建失败!\n");	
   	    return -1;
   	}
   	
   	/*2. 连接服务器*/
   	if(connect(clientfd,(const struct sockaddr *)&server_address,sizeof(struct sockaddr))!=0)
   	{
   		  printf("客户端连接服务器失败!\n");	
   	    return -1; 	
   	}
   	char buff[1024];
   	
   	while(1)
   	{
   	    gets(buff);
   	    write(clientfd,buff,strlen(buff)); 
   	}
		return 0;
}

服务器:

#include 
#include           /* See NOTES */
#include 
#include    //使用大小端转换函数
#include 
#include 
#include 
#include 
#include 
#include 
//函数声明
void *start_routine_1(void *dev);
void *start_routine_2(void *dev);

typedef void *(*start_routine) (void *);
start_routine fun[]={start_routine_1,start_routine_2};
pthread_t thread_id[2];                //存放线程的标识符
int clientfd[2];                       //保存TCP客户端的网络套接字
struct sockaddr_in client_address[2];  //存放客户端的信息
socklen_t address_len[2];              //存放客户端结构体信息的长度
/*服务器端口号定义*/
#define P_host 8080

/*TCP服务器代码*/
int main(int argc,char *argv[])
{
	 int socketfd;
	 struct sockaddr_in server_address;     //存放服务器的IP地址信息
	 memset(&server_address,0,sizeof(struct sockaddr_in)); //初始化内存空间
	 memset(client_address,0,sizeof(struct sockaddr_in)*2); //初始化内存空间
	 server_address.sin_family=PF_INET;            //IPV4协议
	 server_address.sin_port=htons(P_host);        //端口号赋值
	 server_address.sin_addr.s_addr=INADDR_ANY;    //本地IP地址
  /*1 .创建套接字*/
   socketfd=socket(PF_INET,SOCK_STREAM,0);
   if(socketfd<0)
   	{
   	    printf("服务器网络套接字创建失败!\n");	
   	    return -1;
   	}
      	 
   /*2. 绑定端口,创建服务器*/
   if(bind(socketfd,(const struct sockaddr *)&server_address,sizeof(struct sockaddr))!=0)
   	{
   	    printf("服务器绑定端口失败!\n");	
   	    return -1; 	
   	}
   
   /*3. 设监听的端口数量*/
   if(listen(socketfd,10)!=0)
   	{
   	   printf("服务器端口监听失败!\n");	
   	   return -1;	 
   	}
   
    int i;
    
    for(i=0;i<2;i++)
   	{
   		 address_len[i]=sizeof(struct sockaddr);  //计算结构体大小 20 
   	  /*4. 等待客户端连接*/
	    if((clientfd[i]=accept(socketfd,(struct sockaddr *)&client_address[i],&address_len[i]))<0)
	   	{
	   	   	printf("等待客户端连接失败!\n");	
	   	    break;	
	   	} 
	    
	    //创建线程
	   	if(pthread_create(&thread_id[i],NULL,fun[i],NULL)!=0)
		{
		   printf("线程_%d_创建失败!\n",i);		
		} 	
   	}
   	
   	while(1)
   	{
   	    	
   	}
     	
   //阻塞方式等待线程的结束
	pthread_join(thread_id[0],NULL);
	pthread_join(thread_id[1],NULL);
	return 0;	
}
//线程1
void *start_routine_1(void *dev)
{
	 while(1)
	 {
	 	  printf("TCP客户端1连接!\n");
	 	  sleep(2);
	 }
	 //终止线程
	 pthread_exit(NULL);
}
//线程2
void *start_routine_2(void *dev)
{
	while(1)
	{
	 	  printf("TCP客户端2连接!\n");
	 	  sleep(2);
	}
	 //终止线程
	 pthread_exit(NULL);
}

任务3:使用的网络服务器接口

C语言:面向过程 、 面向对象

1.​车牌号识别

2.​二维码生成

3.​获取北京时间

获取接口的网址:http://www.k780.com/

1.​调用网络的接口的方式: (天气预报)

curl http://api.k780.com:88/?app=weather.future'&'weaid=南昌

'&&'appkey=10003'&'sign=b59bc3ef6191eb9f747dd4e83c99f2a4'&'format=json >123.txt

注意: &是特殊的符号,需要使用单引号或者双引号括起来。

Curl: 命令行的浏览器。

2.​调用二维码生成的接口

curl http://api.k780.com:88/?app=qr.get'&'data=www.wanbangee.com'&'level=L'&'size=6 >123.png

​ 练习:

1.​天气预报查询

查询的格式: ./app <城市的中文名称>

poYBAGMlPamARKUnAAA4mjEWJsA386.png

2.​获取北京标准时间,显示出来

pYYBAGMlPamAcAvwAAAMsIAQj18578.png

3.​二维码生成创建 运行格式: ./app <生成的二维码内容>

生成之后直接显示在屏幕上。可以使用eog命令

4.​车牌号的识别

5.​调用百度地图API接口 http://lbsyun.baidu.com/index.php?title=uri/api/web

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 服务器
    +关注

    关注

    12

    文章

    8088

    浏览量

    82433
  • TCP
    TCP
    +关注

    关注

    8

    文章

    1265

    浏览量

    78259
  • 文件
    +关注

    关注

    1

    文章

    540

    浏览量

    24394
收藏 人收藏

    评论

    相关推荐

    飞凌嵌入式RK3568开发板蓝牙收、发文件测试

    版本为Bluetooth5.0,速率高达3Mbps。笔者将在本文为大家介绍如何对OK3568-C开发板进行蓝牙接收文件发送文件测试。1、蓝牙接收文
    的头像 发表于 02-02 16:31 1369次阅读
    飞凌嵌入式RK3568<b class='flag-5'>开发</b>板蓝牙收、发<b class='flag-5'>文件</b>测试

    Linux系统文件比较工具集合

    Linux系统中,文件比较是一种常见的任务,用于比较两个文件之间的差异。文件比较可以帮助我们找出两个文件的不同之处,或者确定它们是否完全相
    的头像 发表于 01-02 13:53 306次阅读

    单片机串口通信的接收发送

    的原理。串口通信是通过发送接收两根线来实现的,分别为发送线(Tx)和接收线(Rx)。当单片机发送数据时,数据通过
    的头像 发表于 12-20 14:03 1480次阅读

    linux文件访问权限怎么设置

    Linux 文件访问权限是操作系统中一个非常重要的概念。正确地设置文件访问权限可以保护系统的安全性,防止未经授权的人员对文件进行修改、删除或执行。本文将详细介绍
    的头像 发表于 11-23 10:20 676次阅读

    STM32串口的发送接收

    USART是STM32内部集成的硬件外设,可以根据数据寄存器的一个字节数据自动生成数据帧时序,从TX引脚发送出去,也可以自动接收RX引脚的数据帧时序,拼接成一个字节数据,存放在数据寄存器里。 当配置
    的头像 发表于 11-10 16:04 586次阅读
    STM32串口的<b class='flag-5'>发送</b>和<b class='flag-5'>接收</b>

    LPC5500_SDK例程:串口DMA发送+中断接收

    LPC5500_SDK例程:串口DMA发送+中断接收
    的头像 发表于 10-30 16:59 511次阅读
    LPC5500_SDK例程:串口DMA<b class='flag-5'>发送</b>+中断<b class='flag-5'>接收</b>

    【LuckFox Pico Plus开发板免费试用】03_串口传输文件

    最终完成编译 此后就可以在src文件夹看到lrz和lsz这两个 .o 可执行文件 其中lrz是开发接收文件,lsz为开发
    发表于 10-23 19:14

    STM32串口发送数据和接收数据方式总结

    STM32串口发送数据和接收数据方式总结
    的头像 发表于 09-19 09:14 5649次阅读
    STM32串口<b class='flag-5'>发送</b>数据和<b class='flag-5'>接收</b>数据方式总结

    如何共享文件给虚拟机中的Linux系统

    软件开发时,很多时候会用到 Linux 虚拟机,而办公环境,又离不开 Windows ,导致有些文件需要在两个环境之间来回切换,为了方便文件传输,可以为虚拟机内的
    发表于 08-22 15:40 1688次阅读
    如何共享<b class='flag-5'>文件</b>给虚拟机中的<b class='flag-5'>Linux</b>系统

    RT-Thread源码分析之网卡数据的接收发送

    ethernetif.c是lwip的网卡接口,在该接口中处理网卡的数据接收发送,rt-thread在该接口文件中抽象了一个eth_device,管理网络数据的收发和向内核的netdev_list添加netdev。
    的头像 发表于 08-11 16:49 988次阅读

    嵌入式Linux入门(二、Linux文件系统、文件类型及权限管理)

    嵌入式 Linux入 门第二课, linux 文件系统、文件类型及权限管理。 ...... 矜辰所致
    的头像 发表于 06-20 11:44 1588次阅读
    嵌入式<b class='flag-5'>Linux</b>入门(二、<b class='flag-5'>Linux</b><b class='flag-5'>文件</b>系统、<b class='flag-5'>文件</b>类型及权限管理)

    Linux如何操作将数据包发送出去

      Linux 服务器收到网络数据包,需要经过哪些处理,一步步将数据传给应用进程的呢?应用进程发送数据包时,Linux 又是如何操作将数据包发送出去的呢?今天我们就来聊聊这个话题。 在
    的头像 发表于 06-17 16:00 711次阅读
    <b class='flag-5'>Linux</b>如何操作将数据包<b class='flag-5'>发送</b>出去

    C51与PC机串口通信中为何出现发送与接收数据长度不一致?

    C51与PC机串口通信中为何出现发送与接收数据长度不一致?比如我用单片机做下位机,无任何校验,发送1或2,3等几个数据,一个数据8个字节,串口调试助手收到的均是3个数据,或是收到的数据比发送
    发表于 05-15 15:02

    linux文件挂载相关介绍

    mount是Linux下的一个命令,它可以将分区挂载或挂接到Linux的一个文件夹下,从而将分区和该目录联系起来,当我们只要访问这个文件夹时,就相当于访问该分区了。
    的头像 发表于 05-12 15:23 416次阅读

    使用SCP和Rsync在Linux中传输文件

    Linux 中,有时需要将文件从一台计算机传输到另一台计算机。为了完成这个任务,有两个主要的工具可以使用:SCP 和 Rsync。本文将介绍如何使用这两个工具在 Linux 中传输文件
    的头像 发表于 05-12 14:32 738次阅读