Linux--网络编程

news2024/11/16 1:51:07

一、网络编程概述
1.进程间通信:

1)进程间通信的方式有**:管道,消息队列,共享内存,信号,信号量这么集中

2)特点:依赖于linux内核,基本是通过内核来实现应用层的两个进程间的通信

3)缺陷:无法多机通讯

2.网络编程:

1)网络编程适用去不同的pc间的通信,可以实现多机运行

2)它关心的是:地址和数据
地址是指:IP地址和端口号。每台PC机连网够都有一个IP地址,那么每台联网的PC机可能跑多个服务器,然后每个服务器中对应的有很多进程。当客户端接入的时候,不知道去对接哪个服务器。那么这时端口号对应的就是每个服务器的端口。客户就可以通过端口号连接到对应的服务器了。

数据是指:协议(HTTP/TCP/UDP)
它是一种数据格式

3.TCP/UDP对比

1)TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接

2)TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大的努力交付,即不保证可靠交付

3)TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的,UDP没用拥塞控制,因此网络出现拥塞不会使源主机的发送速率减低(对实时应用很有用,如IP电话,实时视频会议等)

4)每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信

5)TCP首部开销字节;UDP的首部开销小,只有8字节

6)TCP的逻辑通信信道是全双工的可靠信道;UDP则是不可靠信道

4.端口号的作用

一台拥有IP地址的主机可以提供许多服务,比如Web服务,FTP服务,SMTP服务
这些服务完全可以通过1个IP地址来实现。那么,主机是怎样区分不同的网络服务的呢?显然不能只靠IP地址,因为IP地址和网络服务的关系是一对多的关系。
实际上是通过“IP地址+端接口”来区分不同服务的。

端口提供了一种访问通道,
服务器一般都是通过知名端口号来识别的。例如,对于每个TCP/IP实现来说,FTP服务器的TCP端口号都是21,每个Telnet服务器的TCP端口号都是23,每个TFTP(简单文件传送协议)服务器的UDP端口号都是69

二、字节序
1.定义

字节序是指多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序。

2.常见序

1)Little endian(小端字节序):将低序字节存储在起始地址

LE little-endian

最符合人的思维的字节序

地址低位存储值的低位

地址高位存储值的高位

怎么讲是最符合人的思维的字节序,是因为从人的第一观感来说

低位值小,就应该放在内存地址小的地方,也即内存地址低位

反之,高位值就应该放在内存地址大的地方,也即内存地址高位

2) Big endian(大端字节序):将高序字节存储在起始地址

BE big-endian

最直观的字节序

地址低位存储值的高位

地址高位存储值的低位

为什么说直观,不要考虑对应关系

只需要把内存地址从左到右按照由低到高的顺序写出

把值按照通常的高位到低位的顺序写出

两者对照,一个字节一个字节的填充进去

三、socket编程步骤

1.创建套接字

函数原型:

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
int socket(int domain, int type, int protocol);

domain:
指明所使用的协议族,通常为AF_INET,表示互联网协议族(TCP/IP协议族
AF_INET IPv4 因特网域
AF_INET6 IPv6 因特网域
AF_UNIX Uinx 域
AF_ROUTE 路由套接字
AF_KEY 密匙套接字
AF_UNSPEC 未指定

type参数指定socket的类型:
SOCK_STREAM:
流式套接字提供可靠的,面向连接的通信流;它使用TCP协议,从而保证了数据传输的正确性和顺序性

SOCK_DGRAM:
数据报套接字定义了一种无连接的服,数据通过相互独立的报文传输,是无序了,并且不保证是可靠,无差错的。它使用数据包协议UDP

SOCK_RAW:
允许程序使用底层协议,原始套接字允许对底层协议如IP或ICMP进行直接访问,功能强大但使用较为不便,主要用于一些协议的开发

protocol:
通常赋值:0
0选择type类型对应的默认协议
IPPROTO_TCP TCP传输协议
IPPROTO_UDP UDP传输协议
IPPROTO_SCTP SCTPC传输协议
IPPROTO_TIPC TIPC传输协议
 

2.bind()函数:IP端口号与相应描述字赋值函数
函数原型:

 #include <sys/types.h>          /* See NOTES */
 #include <sys/socket.h>

int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

功能:

用于绑定IP地址和端口号到socketfd

参数:
sockfd
是一个socket描述符

addr
是一个指向包含有本机IP地址及端口号等信息的sockaddr类型的指针,指向要绑定给sockfd的协议地址结构,这个地址结构根据地址创建socket时的地址协议族的不同而不同
addrlen

addr指向的结构体的大小,以字节为单位

struct sockaddr *addr:一般用替换的:

ipv4对应的是:
struct sockaddr {
               sa_family_t sa_family;//协议族
               char        sa_data[14];//IP+端口号
           }

同等替换:
struct sockaddr_in{
   		           sa_family_t  sin_family;//协议族
   		           in_port_t sin_port;//端口号
                   struct in_addr sin_addr;//IP地址结构体
                   unsigned char sin_zero[8];//填充,没用实际意义,只是为sockaddr结构在内存中对齐,这样两者才能相互转换
 }

地址转换API

//把字符串形式“127.0.0.1”转化为网络能识别的格式
int inet_aton(const char* straddr,struct in_addr *addrp);

//把网络格式的IP地址转化为字符串形式
char* inet_ntoa(struct in_addr sin_addr);

将主机字节顺序转换为网络字节顺序

网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian排序方式。

为了进行转换 bsd socket提供了转换的函数 有下面四个
htons 把unsigned short类型从主机序转换到网络序
htonl 把unsigned long类型从主机序转换到网络序
ntohs 把unsigned short类型从网络序转换到主机序
ntohl 把unsigned long类型从网络序转换到主机序

在使用little endian的系统中 这些函数会把字节序进行转换 
在使用big endian类型的系统中 这些函数会定义成空宏

同样 在网络程序开发时 或是跨平台开发时 也应该注意保证只用一种字节序 不然两方的解释不一样就会产生bug.

htonl()函数

头文件
#include <arpa/inet.h> 
htonl()函数
函数原型是:uint32_t htonl(uint32_t hostlong)

1.hostlong是主机字节顺序表达的32位数,htonl中的h–host主机地址,to–to,n–net网络,l–unsigned long无符号的长整型(32位的系统是4字节);
2.函数返回值是一个32位的网络字节顺序;
3.函数的作用是将一个32位数从主机字节顺序转换成网络字节顺序。
htons()函数
函数原型是:uint16_t htons(uint16_t hostlong)

1.hostlong是主机字节顺序表达的16位数,htons中的h–host主机地址,to–to,n–net网络,s–short long无符号的短整型(32位的系统是2字节);
2.函数返回值是一个16位的网络字节顺序;
3.函数的作用是将一个16位数从主机字节顺序转换成网络字节顺序,简单的说就是把一个16位数高低位呼唤。
ntohs()函数
函数原型是:uint16_t ntohs(uint16_t hostlong)

1.hostlong是网络字节顺序表达的16位数,ntohs中的,n–net网络,to–toh–host主机地址,s–short long有符号的短整型(32位的系统是2字节);
2.函数返回值是一个16位的主机字节顺序;
3.函数的作用是将一个16位数由网络字节顺序转换为主机字节顺序,简单的说就是把一个16位数高低位互换。
ntohl()函数
函数原型是:uint32_t ntohs(uint32_t hostlong)

1.hostlong是网络字节顺序表达的32位数,ntohs中的,n–net网络,to–toh–host主机地址,s–unsigned long无符号的短整型(32位的系统是4字节);
2.函数返回值是一个32位的主机字节顺序;
3.函数的作用是将一个32位数由网络字节顺序转换为主机字节顺序。
大小端
比如: unsigned long hostlong = 0xa2b4c6d8;

大端顺序存放:
偏移地址 存放内容
0x00000000 0xa2
0x00000001 0xb4
0x00000002 0xc6
0x00000003 0xd8

小端顺序存放:
偏移地址 存放内容
0x00000000 0xd8
0x00000001 0xc6
0x00000002 0xb4
0x00000003 0xa2

网络字节顺序一定是大端顺序,主机字节不一定
 

3.监听
listen()函数:监听设置函数

 #include <sys/types.h>          /* See NOTES */
 #include <sys/socket.h>

 int listen(int sockfd, int backlog);

功能:
设置能处理的最大连接数,listen() 并未开始接收连接,只是设置socket 的 listen 模式,listen 函数只用于服务端,服务器进程不知道要与谁连接,因此,它不会主动要求与某个进程连接,只是一直监听是否有其他客户进程与之连接,然后响应该连接请求,并对他做出处理,一个服务进程可以同时处理多个客户进程的连接。主要就两个功能:将一个未连接的套接字转换为一个被动的套接字(监听),规定内核为相应套接字排队的最大连接数。

内核为任何一个给定监听套接字维护两个队列:
未完成连接队列,每个这样的SYN 报文段对应其中一项:已由某个客户端发出并到达服务器,而服务器正在等待完成相应的TCP 三次握手过程。这些套接字处于SYN_REVD 状态;

已完成连接队列,每个已完成TCP 三次握手过程的客户端对应其中一项。这些套接字处于ESTABLISHED 状态;

参数
sockfd

sockfd 是socket 系统调用返回的服务器端socket 描述符
backlog
backlog 指定在请求队列中允许的最大请求数

4.接受连接
accept()函数

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

功能:
accept 函数由TCP 服务器调用,用于从已完成连接队列对头返回下一个已完成连接。如果已完成连接队列为空,那么进程被投入睡眠。

参数:
sockfd
sockfd 是socket 系统调用返回的服务器端(s_addr)socket 描述符

addr
用来返回已连接的对端(客户端)的协议地址

addrled
客户端大小(c_addr)

返回值:
该函数的返回值是一个新的套接字描述符,返回值是表示已连接的套接字描述符,而第一个参数是服务器监听套接字描述符。一个服务器通常仅仅创建一个监听套接字,它在该服务器的生命周期内一直存在。内核为每个由服务器进程接收的客户连接创建一个已连接套接字(表示TCP 三次握手已完成),当服务器完成对某个给定客户的服务器时,相应的已连接套接字就会被关闭。

5.数据的收发:
字节流读取函数

在套接字通信中进行字节读取函数:read(); write(); 与I/O 中的读取读取函数略有区别,因为它们输入或输出的字节数比可能比请求的要少。

ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
 ssize_t send(int sockfd, const void *buf, size_t len, int flags);
 ssize_t recv(int sockfd, void *buf, size_t len, int flags);

注意:这里fd文字描述符就是套接字。。

6.客户端的connect函数:
connect()函数:客户连接主机

int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

功能:
该函数用于绑定之后的client 端(客户端),与服务器建立连接

参数:
sockfd:是目的服务器的socket 描述符
addr:是服务器端的IP 地址和端口号的地址结构指针
addrlen:地址长度,常被设置为sizeof(struct sockaddr)

返回值:
成功返回0,遇到错误时返回 -1,并且error中包含相应的错误码

7.网络消息代码:

1.服务器代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>






int main()
{

	int s_fd;
	char readbuf[128] = {0};
	int nread;

	char *msg = "I get your message,QINGYuan is handsome.\n";
	struct sockaddr_in s_addr;
	struct sockaddr_in c_addr;


	memset(&s_addr,0,sizeof(struct sockaddr_in));
	memset(&c_addr,0,sizeof(struct sockaddr_in));
//1.socket
	s_fd = socket(AF_INET,SOCK_STREAM,0);
	if(s_fd == -1){
	perror("socket");
	exit(-1);
}
	

//2.bind
	s_addr.sin_family = AF_INET;
        s_addr.sin_port = htons(8989);

        inet_aton("192.168.1.71",&s_addr.sin_addr);

        bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));




//3.listen
	listen(s_fd,10);


//4.accept
	int clen = sizeof(struct sockaddr_in);
	int c_fd = accept(s_fd,(struct sockaddr*)&c_addr,&clen);
	if(c_fd == -1){
	perror("accept");
	exit(-1);

}
	printf("start conneting...\n");
	sleep(2);
	printf("get connect:%s\n",inet_ntoa(c_addr.sin_addr));

//5.read
	nread = read(c_fd,readbuf,128);
	if(nread == -1){
	perror("read");


}else{
	printf("get message :%d,%s\n",nread,readbuf);
}



//6.write
	if(write(c_fd,msg,strlen(msg))<0){
	perror("write");
	exit(-1);
}

	return 0;

}

运行结果:

客户端代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
 
int main()
{
	int c_fd;
	char readbuf[128];
	int nread;
 
	char *msg="msg from client\n";
	struct sockaddr_in c_addr;
 
	
	memset(&c_addr,0,sizeof(struct sockaddr_in));
 
	//1.socket
	c_fd=socket(AF_INET,SOCK_STREAM,0);
	if(c_fd==-1){
		perror("socket");
		exit(-1);
	}
	//2.connect
	c_addr.sin_family=AF_INET;
	c_addr.sin_port=htons(8989);
	inet_aton("192.168.1.5",&c_addr.sin_addr);
 
	if(connect(c_fd,(struct sockaddr*)&c_addr,sizeof(struct sockaddr))==-1){
		perror("connect");
		exit(-1);
	}
	//3.write
	write(c_fd,msg,strlen(msg));
	
	//4.read
	nread=read(c_fd,readbuf,128);
	if(nread==-1){
		perror("read");
	}else{
		printf("get message from sever:%d,%s\n",nread,readbuf);
	}
 
	return 0;
}

2.多个客户端连接代码:

服务器代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
 
int main(int argc,char **argv)
{
	int s_fd;
	char readbuf[128];
	int nread;
	int mark=0;
	
	char msg[128]={0};
	struct sockaddr_in s_addr;
	struct sockaddr_in c_addr;
	if(argc!=3){
		printf("param is not good\n");
		exit(-1);
	}
	
	memset(&s_addr,0,sizeof(struct sockaddr_in));
	memset(&c_addr,0,sizeof(struct sockaddr_in));
 
	//1.socket
	s_fd=socket(AF_INET,SOCK_STREAM,0);
	if(s_fd==-1){
		perror("socket");
		exit(-1);
	}
	//2.bind
	s_addr.sin_family=AF_INET;
	s_addr.sin_port=htons(atoi(argv[2]));
	inet_aton(argv[1],&s_addr.sin_addr);
 
	bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
	//3.listen
	listen(s_fd,10);
	//4.accept
	int clen=sizeof(struct sockaddr_in);
	while(1){
		int c_fd=accept(s_fd,(struct sockaddr*)&c_addr,&clen);
		if(c_fd==-1){
			perror("accept");
		}
		printf("connect\n");
		mark++;
		sleep(2);
		printf("get connect:%s\n",inet_ntoa(c_addr.sin_addr));
		if(fork()==0){
			if(fork()==0){
				while(1){
					memset(msg,0,sizeof(msg));
					sprintf(msg,"welcome No.%d client",mark);
					//6.write
					write(c_fd,msg,strlen(msg));
					sleep(3);
				}
			}
			while(1){
				//5.read
				memset(readbuf,0,sizeof(readbuf));
				nread=read(c_fd,readbuf,128);
				if(nread==-1){
					perror("read");
				}else{
					printf("get message:%d,%s\n",nread,readbuf);
				}
			}
			break;
		}	
	}
	return 0;
}

客户端代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>






int main()
{

	int s_fd;
	char readbuf[128] = {0};
	int nread;

	char *msg = "I get your message,QINGYuan is handsome.\n";
	struct sockaddr_in s_addr;
	struct sockaddr_in c_addr;


	memset(&s_addr,0,sizeof(struct sockaddr_in));
	memset(&c_addr,0,sizeof(struct sockaddr_in));
//1.socket
	s_fd = socket(AF_INET,SOCK_STREAM,0);
	if(s_fd == -1){
	perror("socket");
	exit(-1);
}
	

//2.bind
	s_addr.sin_family = AF_INET;
        s_addr.sin_port = htons(8989);

        inet_aton("192.168.1.71",&s_addr.sin_addr);

        bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));




//3.listen
	listen(s_fd,10);


//4.accept
	int clen = sizeof(struct sockaddr_in);
	int c_fd = accept(s_fd,(struct sockaddr*)&c_addr,&clen);
	if(c_fd == -1){
	perror("accept");
	exit(-1);

}
	printf("start conneting...\n");
	sleep(2);
	printf("get connect:%s\n",inet_ntoa(c_addr.sin_addr));

//5.read
	nread = read(c_fd,readbuf,128);
	if(nread == -1){
	perror("read");


}else{
	printf("get message :%d,%s\n",nread,readbuf);
}



//6.write
	if(write(c_fd,msg,strlen(msg))<0){
	perror("write");
	exit(-1);
}

	return 0;

}

结果:

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

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

相关文章

线上bug-接口速度慢

&#x1f47d;System.out.println(“&#x1f44b;&#x1f3fc;嗨&#xff0c;大家好&#xff0c;我是代码不会敲的小符&#xff0c;双非大四&#xff0c;Java实习中…”); &#x1f4da;System.out.println(“&#x1f388;如果文章中有错误的地方&#xff0c;恳请大家指正&a…

十四、Docker的基本操作

目录 &#xff08;一&#xff09;镜像命令 一、拉取Nginx 二、查看镜像 三、导出文件 四、删除镜像 五、加载镜像 &#xff08;二&#xff09;容器命令 一、例子&#xff1a;运行一个nginx容器 1、输入运行命令 2、使用命令查看宿主机ip 3、在外部浏览器访问 4、查看…

函数调用分析

目录 函数相关的汇编指令 JMP指令 call指令 ret指令 VS2019正向分析main函数 总结调用函数堆栈变化规律 x64dbg分析调用函数 IDA分析调用函数 函数相关的汇编指令 JMP指令 JMP 指令表示的是需要跳转到哪个内存地址&#xff0c;相当于是间接修改了 EIP 。 call指令 ca…

NX二次开发UF_CAM_ask_blank_matl_db_object 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;里海NX二次开发3000例专栏 UF_CAM_ask_blank_matl_db_object Defined in: uf_cam.h int UF_CAM_ask_blank_matl_db_object(UF_CAM_db_object_t * db_obj ) overview 概述 This function provides the database object which …

使ros1和ros2的bag一直互通

很多文章都是先source ros1 然后source ros2,再play bag source /opt/ros/noetic/setup.bash source /opt/ros/foxy/setup.bash ros2 bag play -s rosbag_v2 kitti_raw00.bag 但实测会出问题: 为使ros1和ros2的bag一直互通 sudo apt update sudo apt install ros-foxy-ro…

axios的原理及实现一个简易版axios

面试官&#xff1a;你了解axios的原理吗&#xff1f;有看过它的源码吗&#xff1f; 一、axios的使用 关于axios的基本使用&#xff0c;上篇文章已经有所涉及&#xff0c;这里再稍微回顾下&#xff1a; 发送请求 import axios from axios;axios(config) // 直接传入配置 axio…

hdfsClient_java对hdfs进行上传、下载、删除、移动、打印文件信息尚硅谷大海哥

Java可以通过Hadoop提供的HDFS Java API来控制HDFS。通过HDFS Java API&#xff0c;可以实现对HDFS的文件操作&#xff0c;包括文件的创建、读取、写入、删除等操作。 具体来说&#xff0c;Java可以通过HDFS Java API来创建一个HDFS文件系统对象&#xff0c;然后使用该对象来进…

PPT幻灯片里的图片,批量提取

之前分享过如何将PPT文件导出成图片&#xff0c;今天继续分享PPT技巧&#xff0c;如何提取出PPT文件里面的图片。 首先&#xff0c;我们将PPT文件的后缀名&#xff0c;修改为rar&#xff0c;将文件改为压缩包文件 然后我们将压缩包文件进行解压 最好是以文件夹的形式解压出来…

车载毫米波雷达行业发展1——概述

1.1 毫米波雷达定义及产品演进 1.1.1 毫米波雷达定义 毫米波雷达(mmWave Radar)是指工作在毫米波波段的雷达&#xff0c;其频域介于 30&#xff5e;300GHz&#xff0c;波长1~10mm。毫米波雷达稳定性高&#xff0c;抗干扰能力强&#xff0c;可穿透雾、烟、灰尘环境&#xff0…

发币成功,记录一下~

N年前就听说了这样一种说法——“一个熟练的区块链工程师&#xff0c;10分钟就可以发出一个新的币” 以前仅仅是有这么一个认识&#xff0c;但当时并不特别关注这个领域。 最近系统性学习中&#xff0c;今天尝试发币成功啦&#xff0c;记录一下&#xff5e; 发在 Sepolia Tes…

CentOS7安装部署Kafka with KRaft

文章目录 CentOS7安装部署Kafka with KRaft一、前言1.简介2.架构3.环境 二、正文1.部署服务器2.基础环境1&#xff09;主机名2&#xff09;Hosts文件3&#xff09;关闭防火墙4&#xff09;JDK 安装部署 3.单机部署1&#xff09;下载软件包2&#xff09;修改配置文件3&#xff0…

[Genode] ARM TrustZone

这是关于读文章ARM TrustZone的记录&#xff0c;原文是英文&#xff0c;刚开始会有点反应不过来&#xff0c;这里大部分是对文章的翻译与提取。 ARM信任区技术 ARM信任区是在 热烈讨论关于X86平台上的可信平台模块&#xff08;TPM&#xff09; 时引入的。。 就像TPM芯片神奇…

◢Django 分页+搜索

1、搜索数据 从数据库中获取数据&#xff0c;并进行筛选&#xff0c;xx__contains q作为条件&#xff0c;查找的是xx列中有q的所有数据条 当有多个筛选条件时&#xff0c;将条件变成一个字典&#xff0c;传入 **字典 &#xff0c;ORM会自行翻译并查找。 筛选电话号码这一列…

【Java】volatile-内存可见性问题

1、什么是内存可见性问题&#xff1f; &#xff08;1&#xff09;实例 要明白什么是内存可见性&#xff0c;我们首先来看一段代码 public class demo1 {public static int isQuit 0;public static void main(String[] args) {Thread thread1 new Thread(()->{while (is…

【每日刷题——语音信号篇】

思考与练习 练习2.1 语音信号在产生的过程中&#xff0c;以及被感知的过程中&#xff0c;分别要经过人体的哪些器官&#xff1f; 1.产生过程&#xff1a; 肺部空气 → \rightarrow →冲击声带 → \rightarrow →通过声道&#xff08;可以调节&#xff09; → \rightarrow →…

【小呆的力学笔记】有限元专题之循环对称结构有限元原理

文章目录 1. 循环对称问题的提出2. 循环对称条件2.1 节点位移的循环对称关系2.2 节点内力的循环对称关系 3. 在平衡方程中引入循环对称条件 1. 循环对称问题的提出 许多工程结构都是其中某一扇面的n次周向重复&#xff0c;也就是是周期循环对称结构。如果弹性体的几何形状、约…

【洛谷 P3743】kotori的设备 题解(二分答案+递归)

kotori的设备 题目背景 kotori 有 n n n 个可同时使用的设备。 题目描述 第 i i i 个设备每秒消耗 a i a_i ai​ 个单位能量。能量的使用是连续的&#xff0c;也就是说能量不是某时刻突然消耗的&#xff0c;而是匀速消耗。也就是说&#xff0c;对于任意实数&#xff0c;…

java学习part06数组工具类

1比较内容 2输出信息 3值填充 4快速排序 5二分查找 负数没找到&#xff0c;其他表示下标

SVG圆形 <circle>的示例代码

本专栏是汇集了一些HTML常常被遗忘的知识&#xff0c;这里算是温故而知新&#xff0c;往往这些零碎的知识点&#xff0c;在你开发中能起到炸惊效果。我们每个人都没有过目不忘&#xff0c;过久不忘的本事&#xff0c;就让这一点点知识慢慢渗透你的脑海。 本专栏的风格是力求简洁…

【MySql】13- 实践篇(十一)

文章目录 1. 自增主键为什么不是连续的&#xff1f;1.1 自增值保存在哪儿&#xff1f;1.2 自增值修改机制1.2.1 自增值的修改时机1.2.2 自增值为什么不能回退? 1.3 自增锁的优化1.3.1 自增锁设计历史 2. Insert语句为何很多锁?2.1 insert … select 语句2.2 insert 循环写入2…