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

文章目录

  • 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、创建socketsockfd = 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; //主进程socketint len;//记录结构体长度int rev;//接收函数返回值struct sockaddr_in seradd;//填充服务端信息struct sockaddr_in cliadd;//接收客户端信息char buf[1024] = {0};  //接收数据缓冲区pid_t cpid; //接收子进程号/*代码*/len = sizeof(seradd);//创建主进程//1、创建socketsfd = 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和端口至socketrev = 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,并分配新portstruct sockaddr_in * client; //接收目的ip,并分配新portint 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、创建socketsfd = 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.rhkb.cn/news/309485.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue指令案例

通过Vue完成表格数据的渲染展示 最终结果为&#xff1a; <!DOCTYPE html> <html lang"en"><head><script src"vue.js">//引入vue文件</script><meta charset"UTF-8"><meta name"viewport" c…

设计模式系列:责任链模式

简介 责任链模式是一种行为型设计模式&#xff0c;它允许你将请求沿着处理者链进行发送。每个处理者都可以对请求进行处理&#xff0c;或者将其传递给链上的下一个处理者。责任链模式主要应用于面向对象编程中&#xff0c;特别是当系统中的对象需要根据其属性来决定如何处理请…

DNS正反向解析

1.先连接X-shell 主服务器&#xff1a;192.168.32.168&#xff08;server&#xff09; 从服务器&#xff1a;192.168.32.169&#xff08;node&#xff09; 2.给主从服务器做准备工作 [rootserver ~]# setenforce 0 setenforce: SELinux is disabled [rootserver ~]# systemc…

基于SpringBoot+Mybatis框架的私人影院预约系统(附源码,包含数据库文件)

基于SpringBootMybatis框架的私人影院预约系统&#xff0c;附源码&#xff0c;包含数据库文件。 非常完整的一个项目&#xff0c;希望能对大家有帮助哈。 本系统的完整源码以及数据库文件都在文章结尾处&#xff0c;大家自行获取即可。 项目简介 该项目设计了基于SpringBoo…

季节更迭 关爱不变 | 鲁南制药四季守护您的健康生活

春天&#xff0c;万物复苏的季节&#xff0c;一切都充满了生机和活力。在春日的阳光下&#xff0c;鲜花盛开&#xff0c;绿叶茂盛&#xff0c;鸟儿欢歌&#xff0c;蝴蝶翩翩起舞。我们的身体也需要特别的关爱和养护&#xff0c;保持健康和活力&#xff0c;更好地迎接每一次季节…

冯喜运:4-15周一黄金原油行情分析及操作建议

【 黄金消息面分析】&#xff1a;周五(4月12日)美盘时段&#xff0c;黄金价格再创历史新高一度突破2420美元关口&#xff0c;最高触及2431美元/盎司&#xff0c;尽管相对强弱指数(RSI)显示超买状态&#xff0c;但随着以色列和伊朗之间的地缘政治紧张局势升级&#xff0c;投资者…

Object和Objects

Object Object是Java中的顶级父类.所有的类都直接或间接的继承Object类. Object类中的方法可以被所有子类访问,所以我们要学习Object类和其中的方法. Object的构造方法: Object的成员方法 public class test {public static void main(String[] args) {//1.toString 返回对象…

跨平台桌面应用 Electron 入门学习

本文章主要为该视频的学习笔记&#xff0c;如果侵权会速删。 Electron 01 课程介绍_哔哩哔哩_bilibiliElectron 01 课程介绍, 视频播放量 3046、弹幕量 0、点赞数 75、投硬币枚数 43、收藏人数 179、转发人数 2, 视频作者 极客丶张德龙, 作者简介 当你的能力还不足以撑起自己的…

蓝桥杯算法题:练功

【问题描述】 小明每天都要练功&#xff0c;练功中的重要一项是梅花桩。 小明练功的梅花桩排列成 n 行 m 列&#xff0c;相邻两行的距离为 1&#xff0c;相邻两列的距离也为 1。 小明站在第 1 行第 1 列上&#xff0c;他要走到第 n 行第 m 列上。小明已经练了一段时间&#xff…

【系统分析师】数据库部分

文章目录 1、数据库模式2、数据库设计过程2.1ER模型 3、关系代数 ☆5、规范化理论☆5.1 非规范存在的问题5.2 相关概念5.3范式5.3.1 第一范式-1NF5.3.2 第二范式-2NF5.2.3 第三范式5.2.4 BC范式 5.4 函数依赖分解5.4.1保持函数依赖分解5.4.2 无损分解 5.5 Armstong公理系统 6、…

物联网实战--驱动篇之(七)RTC时钟(DS1302)

目录 一、RTC简介 二、DS1302介绍 三、初始化 四、字节读写 五、功能函数 一、RTC简介 实时时钟&#xff0c;简称RTC&#xff0c;这个在STM32的外设里也有&#xff0c;不过STM32F1系列的RTC实际上只有一个计数器功能&#xff0c;如果需要年月日要自己写软件计算 &#xff…

数字IC/FPGA(时钟简介)

本文主要介绍以下几点&#xff1a; 什么是时钟什么是外部时钟和内部时钟时钟偏斜skew、时钟延迟delay和时钟抖动jitter的定义、三者的区别时钟抖动、时钟偏斜、时钟延迟会引起或不会引起什么情况布线方式的影响&#xff0c;正偏差和负偏差的好处和坏处什么是同步电路什么是异步…

二叉树经典OJ题(2)

一、根据二叉树创建字符串 . - 力扣&#xff08;LeetCode&#xff09; class Solution { public://前序遍历&#xff1a;根 左 右//左子树为空&#xff0c;右子树不为空的时候&#xff0c;不能省略左//左不为空&#xff0c;右子树为空的时候&#xff0c;可以省略右//都为空&am…

【springCloud】版本学习

Spring Cloud介绍 官网地址&#xff1a;https://spring.io/projects/spring-cloud Spring Cloud 是一个基于 Spring Boot 的微服务架构解决方案&#xff0c;它提供了一系列工具和模式来帮助开发者构建分布式系统。Spring Cloud 的组件和模式包括配置管理、服务发现、断路器、…

【Linux】tcpdump P3 - 过滤和组织返回信息

文章目录 基于TCP标志的过滤器格式化 -X/-A额外的详细选项按协议(udp/tcp)过滤低详细输出 -q时间戳选项 本文继续展示帮助你过滤和组织tcpdump返回信息的功能。 基于TCP标志的过滤器 可以根据各种TCP标志来过滤TCP流量。这里是一个基于tcp-ack标志进行过滤的例子。 # tcpdump…

vue源码解析——diff算法/双端比对/patchFlag/最长递增子序列

虚拟dom——virtual dom&#xff0c;提供一种简单js对象去代替复杂的 dom 对象&#xff0c;从而优化 dom 操作。virtual dom 是“解决过多的操作 dom 影响性能”的一种解决方案。virtual dom 很多时候都不是最优的操作&#xff0c;但它具有普适性&#xff0c;在效率、可维护性之…

《由浅入深学习SAP财务》:第2章 总账模块 - 2.7 总账模块报表 -2.7.2 对外报表:现金流量表

2.7.2 对外报表&#xff1a;现金流量表 现金流量表包括直接法和间接法。使用SAP出具现金流量表&#xff0c;一般只能出具直接法报表。间接法是指按照净利润倒推出现金流量的发生额&#xff0c;由于其中存在人为“分析”的因素&#xff0c;很难直接通过科目的加加减减得出所需要…

Fiddler工具的操作和功能时-----定位到步骤图(助力抓包)

前言&#xff1a; 继续上一篇&#xff0c;已经对fiddler的安装、配置和代理的问题进行了讲解&#xff1a; Fiddle配置代理&#xff0c;保手机模拟器访问外部网络-CSDN博客 本章&#xff0c;讲对一些fiddler的操作进行一系列讲解&#xff01;Fiddler作为一款网络调试工具&…

Java复习第十七天学习笔记(转发、重定向,GET,POST),附有道云笔记链接

【有道云笔记】十七 4.3 转发、重定向、Get、POST、乱码 https://note.youdao.com/s/GD5TRksQ 一、转发 转发&#xff1a;一般查询了数据之后&#xff0c;转发到一个jsp页面进行展示 req.setAttribute("list", list); req.getRequestDispatcher("student_lis…

浅谈函数 fscanf/sscanf 和 fprintf/sprintf

目录 一&#xff0c;fprintf 的介绍和使用1. 函数介绍2. 函数使用 二&#xff0c;fscanf 的介绍和使用1. 函数介绍2. 函数使用 三&#xff0c;sprintf 的介绍和使用1. 函数介绍2. 函数使用 四&#xff0c;sscanf 的介绍和使用1&#xff0c;函数介绍2&#xff0c;函数使用 五&am…