嵌入式学习day16-22(2024.04.06-13)

news2024/11/15 20:06:57

文章目录

  • C语言网络编程
    • socket
      • 主机与网络字节序转换
        • inet_addr、inet_aton(ip转换)
        • inet_ntoa 网络字节序转换为IP字符串
        • 端口转换为网络字节序
        • 网络字节序转换为端口
        • atoi (字符串转换为整数)
    • UDP通信流程
      • UDP多进程并发服务器
      • 服务端
      • 客户端
    • TCP通信流程
      • 客户端
      • 服务端
      • TCP粘包
      • 并发服务器

C语言网络编程

socket

在这里插入图片描述

Linux提供的socket
socket套接字类型
1、流式套接字(TCP)
2、数据报套接字(UDP)
3、原始套接字
在这里插入图片描述
网络数据流在cpu中以不同的方式存储,有小端和大端两种方式(小端与人的读写同向,大端与人的读逆向)
在这里插入图片描述
网络传输时先判断是否为小端,若为小端则进行转换。可以用共用体判断是大端还是小端存储。

主机与网络字节序转换

inet_addr、inet_aton(ip转换)

在这里插入图片描述

inet_ntoa 网络字节序转换为IP字符串
端口转换为网络字节序
网络字节序转换为端口

在这里插入图片描述

atoi (字符串转换为整数)

UDP通信流程

在这里插入图片描述
发送流程
1、创建socket函数
int socket(int domain, int type, int protocol);
udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
2、sendto,发送函数
发送端代码

#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
void send_data(int sockfd,struct sockaddr_in *addr,int len){
        int n=0;
        char buf[1024]={0};

        while(1){
                putchar('>');
                memset(buf,0,sizeof(buf));
                fgets(buf,sizeof(buf),stdin);
                buf[strlen(buf)-1] = '\0'; // ’\n‘ ==>'\0'
                n = sendto(sockfd,buf,strlen(buf),0,(struct sockaddr *)addr,len);//发送写buf实际长度,收时写buf最大长度
                if(n < 0){
                        perror("[ERROR] sendto():");
                        exit(EXIT_FAILURE);
                }
                if(strncmp(buf,"quit",4) == 0){
                        printf("END SEND\n");
                        break;
                }
                printf("\033[43msend message:\033[0m %s \n",buf);
        }
        return ;
}

int main(int argc,char *argv[]){

        int sockfd;
        struct sockaddr_in peer_addr;
        int len = sizeof(peer_addr);
        if(argc != 3){
                fprintf(stderr,"Usage : %s ip port !\n",argv[0]);
                exit(EXIT_FAILURE);
        }

        //1、通过socket创建文件描述符
        sockfd = socket(AF_INET,SOCK_DGRAM,0);
        if(sockfd == -1){
                perror("[ERROR] socket():");
                exit(EXIT_FAILURE);
        }
        //2、填充服务器ip和端口号
        memset(&peer_addr,0,sizeof(peer_addr)); //初始化结构体
        peer_addr.sin_family=AF_INET;
        peer_addr.sin_port=htons(atoi(argv[2]));
        peer_addr.sin_addr.s_addr = inet_addr(argv[1]);

        //3、发送数据
        send_data(sockfd,&peer_addr,len);
        //4、关闭文件描述符

        close(sockfd);


        return 0;
}

接收流程
1、创建socket
2、绑定ip和端口到socket bind
3、接收数据 recvfrom

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
void recv_data(int sockfd){
	//接收数据函数
	int n = 0;
	char buf[1024] = {0};
	struct sockaddr_in client_addr;
	int len = sizeof(client_addr);

	while(1){
		memset(buf,0,sizeof(buf));
		n = recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&client_addr,&len); //接收发送方IP port 以及数据
		if(n < 0){
			perror("[error] recvfrom():");
			exit(EXIT_FAILURE);
		}
		printf("===================================================\n");
		printf("\033[34m Recv from IP = %s \033[0m\n",inet_ntoa(client_addr.sin_addr));
		printf("\033[34m Recv from PORT = %d \033[0m\n",ntohs(client_addr.sin_port));
		printf("Recv  %d bytes:\033[35m %s\033[0m\n",n,buf);
		if(strncmp(buf,"quit",4) == 0){
			printf("\033[31mEND RECV\033[0m\n");
			break;
		}
	}
	

}


int main(int argc,char *argv[]){
	//参数判断
	if(argc != 3){
		printf("\033[31m %s 参数错误: ip port\033[0m\n");
		exit(EXIT_FAILURE);
	}
	int sockfd;
	struct sockaddr_in my_addr;
	int len = sizeof(my_addr);
	//1、创建socket
	sockfd = socket(AF_INET,SOCK_DGRAM,0);
	if(sockfd < 0){
		perror("[ERROR] socket():");
		exit(EXIT_FAILURE);
	}
	//2、填充ip和端口
	memset(&my_addr,0,sizeof(my_addr)); //初始化结构体
	my_addr.sin_family = AF_INET;
	my_addr.sin_port = htons(atoi(argv[2]));
	my_addr.sin_addr.s_addr = inet_addr(argv[1]);

	//3、绑定端口
	if(bind(sockfd,(struct sockaddr *)&my_addr,len)<0){
		perror("[ERROR] bind():");
		exit(EXIT_FAILURE);
	}		
	printf("\033[35m wait recv from port %s \033[0m \n",argv[2]);


	//4、接收数据
	recv_data(sockfd);

	//关闭描述符
	close(sockfd);

	return 0;	
}

UDP多进程并发服务器

在这里插入图片描述

在这里插入图片描述

服务端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

/*udp 多进程服务器端*/
/*
1、创建主进程,用与接收客户端请求
2、接收客户端请求后,分配新的socket以及端口用于和客户端连接
 */


void send_client(struct sockaddr_in *seradd,struct sockaddr_in *newcadd,struct sockaddr_in *newclient);

int main(int argc,char *argv[]){
	/*变量定义*/
	int sfd; //主进程socket
	int len;//记录结构体长度
	int rev;//接收函数返回值
	struct sockaddr_in seradd;//填充服务端信息
	struct sockaddr_in cliadd;//接收客户端信息
	char buf[1024] = {0};  //接收数据缓冲区
	pid_t cpid; //接收子进程号

	/*代码*/
	len = sizeof(seradd);
	//创建主进程
	//1、创建socket
	sfd = socket(AF_INET,SOCK_DGRAM,0);
	if(sfd == -1){
		perror("error in socket():");
		exit(EXIT_FAILURE);
	}
	//2、填充信息到结构体
	memset(&seradd,0,len);
	seradd.sin_family = AF_INET;
	seradd.sin_port = htons(atoi(argv[2]));
	seradd.sin_addr.s_addr = inet_addr(argv[1]);
	//3、绑定ip和端口至socket
	rev = bind(sfd,(struct sockaddr *)&seradd,len);
	if(rev == -1){	
		perror("error in bind():");
		exit(EXIT_FAILURE);
	}
	//接收数据
	while(1){
		memset(buf,0,sizeof(buf));
		memset(&cliadd,0,len);
		rev = recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr *)&cliadd,&len);
		if(rev == -1){
			perror("error in recvfrom():");
			exit(EXIT_FAILURE);
		}
		//输出客户端信息
		printf("The connect from:\033[32m %s %d\033[0m\n",inet_ntoa(cliadd.sin_addr),ntohs(cliadd.sin_port));
		printf("data : \033[31m %s \033[0m\n",buf);
		//创建子进程
		cpid = fork();
		if(cpid == -1){
			perror("error in fork():");
			exit(EXIT_FAILURE);
		}
		else if(cpid == 0){
			struct sockaddr_in new_seradd;//创建新的端口等
			struct sockaddr_in new_client;//创建新的端口等
			memset(&new_seradd,0,len);
			memset(&new_client,0,len);
			new_client = cliadd;
			send_client(&seradd,&new_seradd,&new_client);
			exit(EXIT_SUCCESS);
		}

		}


	return 0;
}




/*函数*/

void send_client(struct sockaddr_in *seradd,struct sockaddr_in *newcadd,struct sockaddr_in *newclient){
	struct sockaddr_in * new_ser; //接收目的ip,并分配新port
	struct sockaddr_in * client; //接收目的ip,并分配新port
	int sfd;
	int len;
	int rev;
	char buf[1024]={0};
	len = sizeof(struct sockaddr_in);
	new_ser = newcadd;
	client = newclient;
	sfd = socket(AF_INET,SOCK_DGRAM,0);
	if(sfd == -1){
			perror("error in socket():");
			exit(EXIT_FAILURE);
		}
		//输出客户端信息
	new_ser->sin_family = seradd->sin_family;
	new_ser->sin_port = htons(0);
	new_ser->sin_addr.s_addr = seradd->sin_addr.s_addr;
	
	rev = bind(sfd,(struct sockaddr *)new_ser,len);
	if(rev == -1){
			perror("error in rev():");
			exit(EXIT_FAILURE);
		}
	printf("以新端口发送数据\n");	

	rev =  sendto(sfd,"SEND NEW PORT",sizeof("SEND NEW PORT"),0,(struct sockaddr*)client,len);
	if(rev == -1){
			perror("error in sendto():");
			exit(EXIT_FAILURE);
		}
	printf("以新端口接收数据\n");	
	while(1){
		memset(buf,0,sizeof(buf));
		rev = recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr *)new_ser,&len);
	if(rev == -1){
			perror("error in recvfrom():");
			exit(EXIT_FAILURE);
		}
		printf("data:\033[32m%s\n\033[0m",buf);
	}
	close(sfd);
	return ;

}

客户端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

/*udp 多进程客户端*/
/*
1、创建socket,并发送一条信息
2、接收打一条信息 (struct sockaddr_in.sin_port 新更换端口)
 */


int main(int argc,char *argv[]){
	/*变量定义*/
	int sfd;
	int len;
	int rev;
	struct sockaddr_in seradd;
	char buf[1024] = {0};



	/*代码*/
	len = sizeof(seradd);
	//创建主进程
	//1、创建socket
	sfd = socket(AF_INET,SOCK_DGRAM,0);
	if(sfd == -1){
		perror("error in socket():");
		exit(EXIT_FAILURE);
	}
	//2、填充信息到结构体
   memset(&seradd,0,len);
   seradd.sin_family = AF_INET;
   seradd.sin_port = htons(atoi(argv[2]));
   seradd.sin_addr.s_addr = inet_addr(argv[1]);

   //3、发送信息获取端口号
   rev = sendto(sfd,"CONNECT",strlen("CONNECT"),0,(struct sockaddr *)&seradd,len);
	if(rev == -1){
		perror("error in sendto():");
		exit(EXIT_FAILURE);
	}
	//4、接收新的端口号	
	memset(buf,0,sizeof(buf));
	memset(&seradd,0,len);
	//接收新的端口号至结构体
	rev = recvfrom(sfd,buf,1024,0,(struct sockaddr *)&seradd,&len);
	if(rev == -1){
		perror("error in recvfrom when acquire new port:");
		exit(EXIT_FAILURE);
	}
	printf("接收新端口成功!!!\n");
	printf("请发送数据:\n");

	//正常接收发送数据
	while(1){
		memset(buf,0,sizeof(buf));
		fgets(buf,1024,0);
//		scanf("%s",buf);
//		printf("\n");
		printf("接收数据:%s\n",buf);
		rev = sendto(sfd,buf,sizeof(buf),0,(struct sockaddr *)&seradd,len);
		if(rev == -1){
			perror("error in sendto():");
			exit(EXIT_FAILURE);
		}
		rev = strncmp("exit",buf,4);
		printf("rev = %d\n",rev);
		if(rev == 0){
			printf("退出!!!!\n");
			break;
		}
/*	rev = recvfrom(sfd,buf,1024,0,(struct sockaddr *)&seradd),&len);
	if(rev == -1){
		perror("error in recvfrom when acquire new port:");
		exit(EXIT_FAILURE);
	}
*/	
	}

	/*资源关闭*/
	close(sfd);
	return 0;
}



TCP通信流程

客户端

流程:
1、创建socket
2、填充结构体 (bzeor() 清零函数)
3、创建连接 connect
4、发送数据 send (udp 为 sendto)
5、接收数据 recv (udp recvfrom) recv返回0,表示断开连接

服务端

1、创建socket
2、绑定ip 与 端口 bind
3、设置套接字为监听状态,建立监听队列 listen
4、与客户端三次握手建立连接 accept,成功创建一个新的套接字
5、使用新的套接字 接收发送消息 send recv

TCP粘包

原因:
解决方法:
1、使用定长的数据包
2、发送时 数据长度+数据(发送不定长数据)

并发服务器

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1596272.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【已测 非网上加密版】全新UI彩虹站长在线工具箱系统源码下载 全开源版本

支持高达72种站长工具、开发工具、娱乐工具等功能。本地调用API、自带免费API接口&#xff0c;是一个多功能性工具程序支持后台管理、上传插件、添加增减删功能。 环境要求 * PHP > 7.3 * MySQL > 5.6 * fileinfo扩展 * 使用Redis缓存需安装Redis扩展 部署 * 下载源代码 …

【嵌入式】交叉编译指南:将开源软件带到嵌入式世界

&#x1f9d1; 作者简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向的学习指导…

Java反序列化Commons-Collections-CC1链

环境搭建 JDK8u71以下&#xff0c;这个漏洞已经被修复了&#xff0c;这个JDK的以上版本都修复了漏洞 JDK8u65 下载地址 https://www.oracle.com/cn/java/technologies/javase/javase8-archive-downloads.html这个时候来到 pom.xml 配置Maven依赖下载CommonsCollections3.2.…

20V/1.5A替代LT1963低压差线性稳压器

概述(替代LT1963) PCD3941 是一款低压差稳压器&#xff0c;专为快速瞬态响应而优化。该装置能够提供 1.5A 的输出电流&#xff0c;典型压降为 160mV。工作静态电流为 1mA&#xff0c;关机时降至 1μA以下&#xff0c;同时压差模式下静态电流控制良好。除了快速瞬态响应外&…

【Linux】封装一下简单库 理解文件系统

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、封装一下简单库 二、理解一下stdin(0)、stdout(1)、stderr(3) 2.1、为什么要有0、1、2呢&#xff1f; 2.2、特点 2.3、如果我想让2也和1重定向到一个文件…

护眼台灯哪个牌子好?护眼灯十大品牌推荐,绝对真香!

对于有孩子的家庭&#xff0c;特别是阅读爱好者&#xff0c;晚上阅读时的光线问题至关重要。昏暗环境长时间阅读&#xff0c;会严重伤害孩子的眼睛。因此&#xff0c;选择一款合适的护眼台灯显得尤为重要。但市场上品牌众多&#xff0c;护眼台灯哪个牌子好?这往往让人难以抉择…

【Tomcat 文件读取/文件包含(CVE-2020-1938)漏洞复现】

文章目录 前言 一、漏洞名称 二、漏洞描述 三、受影响端口 四、受影响版本 五、漏洞验证 六、修复建议 前言 近日在做漏扫时发现提示服务器存在CVE-2020-1938漏洞&#xff0c;故文章记录一下相关内容。 一、漏洞名称 Tomcat 文件读取/文件包含漏洞(CVE-2020-1938) 二、漏洞描…

a == 1 a== 2 a== 3 返回 true ?

1. 前言 下面这道题是 阿里、百度、腾讯 三个大厂都出过的面试题&#xff0c;一个前端同事跳槽面试也被问了这道题 // &#xff1f; 位置应该怎么写&#xff0c;才能输出 trueconst a ?console.log(a 1 && a 2 && a 3) 看了大厂的面试题会对面试官的精神…

这款开发工具大大降低IoT开发门槛!完全开源,上手超简单

对开发者来说&#xff0c;IoT 开发的难点是什么&#xff1f;首先&#xff0c;IoT 涉及到多个领域和多种开发技术&#xff0c;每一层的技术接口、协议都需要跨平台、跨领域、跨系统的合作协同&#xff1b;在互联互通方面&#xff0c;智能设备间的兼容性亟待进一步地打通融合&…

ANSYS 2023版 下载地址及安装教程

ANSYS是一款著名的工程仿真软件&#xff0c;广泛应用于航空航天、汽车、能源和制造等领域。它为工程师和设计师提供了强大的建模、分析和优化工具&#xff0c;可以帮助他们预测和优化产品的性能。 ANSYS提供了广泛的模拟功能&#xff0c;包括结构力学、流体力学、电磁场和热传…

Unity | Shader基础知识(第十二集:颜色混合)

目录 前言 一、日常生活中的常见现象 二、unity自带的一个结构体&#xff08;表面着色器SurfaceOutputStandard&#xff09; 三、自己写一个颜色混合的Shader 1.只加基础颜色Albedo 2.加入法线 3.加入光滑度 4.加入金属度 5.加入自发光 四、作者的话 前言 shader里每一…

2024第十五届蓝桥杯 JAVA B组

目录 前言&#xff1a;试题 A: 报数游戏试题 B: 类斐波那契循环数试题C:分布式队列 前言&#xff1a; 没参加这次蓝桥杯算法赛&#xff0c;十四届蓝桥杯被狂虐&#xff0c;对算法又爱又恨&#xff0c;爱我会做的题&#xff0c;痛恨我连题都读不懂的题&#x1f62d;,十四届填空只…

计算方法实验5:对鸢尾花数据集进行主成分分析(PCA)并可视化

任务 iris数据集包含150条数据&#xff0c;从iris.txt读取&#xff0c;每条数据有4个属性值和一个标签&#xff08;标签取值为0&#xff0c;1&#xff0c;2&#xff09;。要求对这150个4维数据进行PCA&#xff0c;可视化展示这些数据在前两个主方向上的分布&#xff0c;其中不…

鸿蒙原生应用元服务-访问控制(权限)开发Stage模型向用户申请授权

一、向用户申请授权 当应用需要访问用户的隐私信息或使用系统能力时&#xff0c;例如获取位置信息、访问日历、使用相机拍摄照片或录制视频等&#xff0c;应该向用户请求授权。这需要使用 user_grant 类型权限。在此之前&#xff0c;应用需要进行权限校验&#xff0c;以判断当前…

Golang教程一(环境搭建,变量,数据类型,数组切片map)

目录 一、环境搭建 1.windows安装 2.linux安装 3.开发工具 二、变量定义与输入输出 1.变量定义 2.全局变量与局部变量 3.定义多个变量 4.常量定义 5.命名规范 6.输出 格式化输出 7.输入 三、基本数据类型 1.整数型 2.浮点型 3.字符型 4.字符串类型 转义字…

贝叶斯公式中的先验概率、后验概率、似然概率

欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和技术。关…

Neo4j 图形数据库中有哪些构建块?

Neo4j 图形数据库具有以下构建块 - 节点属性关系标签数据浏览器 节点 节点是 Graph 的基本单位。 它包含具有键值对的属性&#xff0c;如下图所示。 NEmployee 节点 在这里&#xff0c;节点 Name "Employee" &#xff0c;它包含一组属性作为键值对。 属性 属性是…

华为HarmonyOS 4.2公测升级计划扩展至15款新机型

华为近日宣布&#xff0c;HarmonyOS 4.2操作系统的公测升级计划将扩展到包括华为P50系列在内的15款设备。这一更新旨在为用户提供更优化的系统性能和增强的功能。 参与此次公测的机型包括华为P50、华为P50 Pro及其典藏版、华为P50E、华为P50 Pocket及其艺术定制版、华为nova系…

Unity开发HoloLens2应用时,用VisualStudio进行真机在线Debug调试

一、需求 用Unity开发的应用&#xff0c;部署到真机设备出现启动崩溃&#xff0c;此时可以用在线调试&#xff0c;排查错误。 二、开发环境说明 MRholoLens2 Unity 2021.3.18 Win Win10 VS vs2022 三、调试操作步骤 1、HoloLens2与电脑的连接&#xff0c;Wifi连接&…

不是所有商业模式都叫传销!七星创客模式!

“商业模式是否等同于拉人头、传销&#xff1f;”近期&#xff0c;这一疑问在许多人心中萦绕。似乎每当提及商业模式&#xff0c;总有些人会将其与拉人头、传销等概念联系起来&#xff0c;仿佛所有的商业模式都带有某种负面色彩。 然而&#xff0c;商业模式的内涵远非如此单一。…