嵌入式学习第二十五天!(网络的概念、UDP编程)

news2024/11/18 15:30:32

网络:

    可以用来:数据传输数据共享

1. 网络协议模型:

    1. OSI协议模型:

应用层实际收发的数据
表示层发送的数据是否加密
会话层是否建立会话连接
传输层数据传输的方式(数据包,流式)
网络层数据的路由(如何从一个局域网到达另一个局域网)
数据链路层局域网下如何通信
物理层物理介质的连接

      2. TCP/IP协议模型:

应用层传输的数据
传输层传输的方式
网络层数据如何从一个台主机到达另一台主机
网络接口层物理介质的连接
        1. 应用层:

               例如有:HTTP      超文本传输协议

                              HTTPS   

                              FTP        文件传输协议

                              TFTP      简单文本传输协议

                              SMTP     邮件传输协议

                              MQTT

                              TELNET

                              ...

        2. 传输层:

              UDP:用户数据报协议

                    特点:1. 实现机制简单

                               2. 资源开销小

                               3. 不安全不可靠

              TCP:传输控制协议

                      特点:1. 实现机制复杂

                                 2. 资源开销大

                                 3. 安全可靠

        3. 网络层:

              IPv4

              IP地址:唯一网络中一台主机的标号

              IP地址:网络位 + 主机位

              子网掩码:用来标识IP地址的网络位和主机位

                                子网掩码是1的部分表示IP地址的网络位

                                子网掩码是0的部分表示IP地址的主机位

                网段号:网络位不变,主机位全位0,表示网段号

                广播地址:网络位不变,主机位全为1,表示广播地址

                IP地址类型:

                A类:

                        1.0.0.0  -  126.255.255.255

                        子网掩码:255.0.0.0

                        管理超大规模网络

                        私有IP地址:10.0.0.0  -  10.255.255.255

                B类:

                        128.0.0.0  -  191.255.255.255

                        子网掩码:255.255.0.0

                        管理大中规模型网络

                        私有IP地址:172.16.0.0  -  172.31.255.255

                C类:

                        192.0.0.0  -  223.255.255.255

                        子网掩码:255.255.255.0

                        管理中小规模型网络

                        私有IP地址:192.168.0.0  -  192.168.255.255

                D类:

                        224.0.0.0  -  239.0.0.0

                        用于组播

                E类:

                        240.0.0.0  -  255.255.255.255

                        用于实验

        4. UDP编程:

            socket套接字(全双工)编程:

            发端:socket  ->  sendto  ->  close

            收端:socket  ->  bind  ->  recvfrom  ->  close

            1. 发端
                1. socket:
int socket(int domain, int type, int protocol);

                    功能:创建一个用来通信的文件描述符

                    参数:

                        domain:使用的协议族 AF_INET(IPv4协议族)

                        type:套接字类型

                                SOCK_STREAM:流式套接字

                                SOCK_DGRAM:数据报套接字

                                SOCK_RAW:原始套接字

                        protocol:协议

                                默认为0;

                    返回值:

                        成功返回文件描述符
                        失败返回-1

                2. sendto:
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                      const struct sockaddr *dest_addr, socklen_t addrlen);

                    功能:利用套接字向指定地址发送数据信息

                    参数:

                        sockfd:套接字文件描述符

                        buf:发送数据空间首地址

                        len:发送数据的长度

                        flags:属性默认为0

                        dest_addr:目的地址信息存放的空间首地址

                        addrlen:目的地址的长度

struct sockaddr_in {
    sa_family_t    sin_family; /* address family: AF_INET */
    in_port_t      sin_port;   /* port in network byte order */
    struct in_addr sin_addr;   /* internet address */
};

/* Internet address. */
struct in_addr {
    uint32_t       s_addr;     /* address in network byte order */
};

                    返回值:

                        成功返回实际发送字节数
                        失败返回-1

                3. inet_addr:
in_addr_t inet_addr(const char *cp);

                    功能:将字符串IP地址转换为内存中的IP地址

                4. htons:
uint16_t htons(uint16_t hostshort);

                    功能:将本地字节序转换为网络的大端字节序

            练习:

                1. 编写程序实现从终端接收字符串发送给windows软件调试助手,并接收软件助手的回复,显示在终端屏幕上

#include "head.h"

int main(void)
{
	int sockfd = 0;
	ssize_t nsize = 0;
	char tmpbuff[1024] = {0};
	struct sockaddr_in recvaddr;

	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sockfd == -1)
	{
		perror("fail to socket");
		return -1;
	}
	
	gets(tmpbuff);


	recvaddr.sin_family = AF_INET;
	recvaddr.sin_port = htons(50000);
	recvaddr.sin_addr.s_addr = inet_addr("192.168.1.162");
	
	bind(sockfd, (struct sockaddr *)&recvaddr, sizeof(&recvaddr));

	nsize = sendto(sockfd, tmpbuff, strlen(tmpbuff), 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));
	if(nsize == -1)
	{
		perror("fail to sendto");
		return -1;
	}

	printf("成功发送 %ld 字节!\n", nsize);

	
	memset(tmpbuff, 0, sizeof(tmpbuff));
	nsize = recvfrom(sockfd, tmpbuff, sizeof(tmpbuff), 0, (struct sockaddr *)&recvaddr, (socklen_t *)sizeof(&recvaddr));
	printf("%s\n",tmpbuff);

	close(sockfd);

	return 0;
}
             2. 收端
                1. recvfrom:
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen);

                    功能:从套接字中接收数据

                    参数:

                        sockfd:套接字文件描述符

                        buf:存放数据空间首地址

                        flags:属性,默认为0

                        src_addr:存放IP地址信息的空间首地址

                        addlen:存放接收到IP地址大小空间的首地址

                    返回值:

                        成功返回实际接收字节数
                        失败返回-1 

                2. 修改虚拟机到桥接模式:

                    点击“虚拟机”

                    点击“设置”

                    点击“网络适配器”

                    选择“桥接模式”

                    点击“确定”

                3. 将网卡桥接到无线网卡:

                    点击“编辑”

                    点击“虚拟网络编辑器”

                    点击“更改设置”

                4. 在Ubuntu中重启网络服务:
sudo /etc/init.d/networking restart 
                5. 通过ifconfig查看虚拟机IP地址
                6. bind:
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

                    功能:在套接字上绑定一个IP地址和端口号

                    参数:

                        sockfd:套接字文件描述符

                        addr:绑定IP地址空间首地址

                        addrlen:绑定IP地址的长度

                    返回值:

                        成功返回0 
                        失败返回-1 

            3. UDP需要注意的细节点:

                1. UDP是无连接,发端退出,收端没有任何影响

                2. UDP发送数据上限,最好不要超过1500个字节

                3. UDP是不安全不可靠的,连续且快速的传输数据容易产生数据丢失

            4. wireshark

                可以通过wireshark抓包工具来查看收发的数据

                操作流程:

                    1. 打开wireshark:

sudo wireshark

                    2. 选择抓取数据包的网卡:any

                    3. 执行通信的代码

                    4. 停止通信

                    5. 设定过滤条件

                        ip.addr == IP地址  :通过IP地址查找

                        udp                        :通过传输方式udp查找

                        tcp                         :通过传输方式tcp查找

                        udp.port == 端口号:通过端口号查找

            5. UDP包头长度:8个字节

                源端口号(2个字节)

                目的端口号(2个字节)

                长度(2个字节)

                检验和(2个字节)

            练习:

                要求在不同主机中编写两个程序,实现全双工聊天功能

                1. 进入软件后接收当前用户的昵称

                2. 显示的格式为对方用户昵称 (对方IP:对方端口) > 接收到的内容

                3. 用户输入“.quit”退出聊天

                4. 网络通信时收发结构体

struct person 
{
    char name[32];
    char text[512];
};
#include "head.h"

int sockfd = 0;
ssize_t nsize = 0;
struct sockaddr_in tmpaddr;
struct sockaddr_in sendaddr;
socklen_t addrlen = sizeof(tmpaddr);

struct person
{
	char name[32];
	char text[512];
};

pthread_t tid_recv;
pthread_t tid_send;

void *RecvInfo(void *arg)
{
	struct person user;
	while(1)
	{
		memset(&user, 0, sizeof(user));
		nsize = recvfrom(sockfd, &user, sizeof(user), 0, (struct sockaddr *)&tmpaddr, &addrlen);
		if(nsize == -1)
		{
			perror("fail to recvfrom");
			return NULL;
		}
		printf("%s %s : %d > %s\n", user.name, inet_ntoa(tmpaddr.sin_addr), ntohs(tmpaddr.sin_port), user.text);
		if(!strcmp(user.text, ".quit"))
		{
			break;
		}
	}
	pthread_cancel(tid_send);
	return NULL;
}

void *SendInfo(void *arg)
{
	struct person user;
	while(1)
	{
		memset(&user, 0, sizeof(user));
		scanf("%s", user.name);
		scanf("%s", user.text);
		nsize = sendto(sockfd, &user, sizeof(user), 0, (struct sockaddr *)&sendaddr, sizeof(sendaddr));
		if(nsize == -1)
		{
			perror("fail to sendto");
			return NULL;
		}
		printf("success send %ld byte\n", nsize);
		if(!strcmp(user.text, ".quit"))
		{
			break;
		}
	}
	pthread_cancel(tid_recv);
	
	return NULL;
}

int main(void)
{
	struct sockaddr_in recvaddr;

	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sockfd == -1)
	{
		perror("fail to socket");
		return -1;
	}
	
	recvaddr.sin_family = AF_INET;
	recvaddr.sin_port = htons(30000);
	recvaddr.sin_addr.s_addr = inet_addr("192.168.1.153");
	bind(sockfd, (struct sockaddr *)&recvaddr, sizeof(recvaddr));
	
	sendaddr.sin_family = AF_INET;
	sendaddr.sin_port = htons(30000);
	sendaddr.sin_addr.s_addr = inet_addr("192.168.1.152");
	
	pthread_create(&tid_recv, NULL, RecvInfo, NULL);
	pthread_create(&tid_send, NULL, SendInfo, NULL);

	pthread_join(tid_recv, NULL);
	pthread_join(tid_send, NULL);


	close(sockfd);

	return 0;

}
        5. UDP项目练习:

        题目:基于UDP实现直播间聊天的功能:

        需求:

                软件划分为用户客户端和主播服务端两个软件client.c和server.c

                用户客户端负责:

                        1.接收用户的昵称
                        2.接收用户输入的信息,能够将信息发送给服务端
                        3.接收服务端回复的数据信息,并完成显示

                主播服务端负责:

                        1.对所有加入直播间的用户的IP地址和端口实现管理(加入、退出)
                        2.当有新的客户端加入时,能够向所有客户端提示:"欢迎 XXX 用户进入直播间"
                        3.当有客户端退出时,能够向所有客户端提示:"XXX 离开直播间"
                        4.能够实现客户端聊天内容的转发,当某个客户端发送聊天信息时,能够将该信息转给除了该用户之外聊天室内所有其余客户端用户

client.c

#include "head.h"

int sockfd = 0;
char name[32];
struct sockaddr_in recvaddr;
pthread_t tid_send;
pthread_t tid_recv;

void *SendMsg(void *arg)
{
	struct msgbuf sendmsg;
	ssize_t nsize = 0;
	while(1)
	{
		memset(&sendmsg, 0, sizeof(sendmsg)); 
		sendmsg.type = USER_TYPE_CHAT;
		sprintf(sendmsg.name, "%s", name);
		gets(sendmsg.text);
		if(strcmp(sendmsg.text,".quit") == 0)
		{
			sendmsg.type = USER_TYPE_OUT;
		}
		nsize = sendto(sockfd, &sendmsg, sizeof(sendmsg), 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));
		if(nsize == -1)
		{
			perror("fail to sendto");
			return NULL;
		}
		if(sendmsg.type == USER_TYPE_OUT)
		{
			break;
		}
	}
	pthread_cancel(tid_recv);

	return NULL;
}

void *RecvMsg(void *arg)
{
	struct msgbuf recvmsg;
	ssize_t nsize = 0;

	while(1)
	{
		nsize = recvfrom(sockfd, &recvmsg, sizeof(recvmsg), 0, NULL, NULL);
		if(nsize == -1)
		{
			perror("fail to recvfrom");
			return NULL;
		}
		if(recvmsg.type == USER_TYPE_CHAT)
		{
			printf("%s>%s\n", recvmsg.name, recvmsg.text);
		}
		if(recvmsg.type == USER_TYPE_OUT)
		{
			break;
		}
	}
	
	return NULL;
}

int main(void)
{
	ssize_t nsize = 0;
	struct msgbuf sendmsg; 


	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sockfd == -1)
	{
		perror("fail to socket");
		return -1;
	}
	
	printf("请输入你的名字:\n");
	gets(name);
	
	memset(&sendmsg, 0, sizeof(sendmsg));
	sendmsg.type = USER_TYPE_INT;
	sprintf(sendmsg.name, "%s", name);

	recvaddr.sin_family = AF_INET;
	recvaddr.sin_port = htons(SERVER_PORT);
	recvaddr.sin_addr.s_addr = inet_addr(SERVER_ADDR);
	nsize = sendto(sockfd, &sendmsg, sizeof(sendmsg), 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));
	if(nsize == -1)
	{
		perror("fail to sendto");
		return -1;
	}

	pthread_create(&tid_send, NULL, SendMsg, NULL);
	pthread_create(&tid_recv, NULL, RecvMsg, NULL);

	pthread_join(tid_send, NULL);
	pthread_join(tid_recv, NULL);

	close(sockfd);
}

server.c

#include "head.h"

int main(void)
{
	int sockfd = 0;
	ssize_t nsize = 0;
	ssize_t size = 0;
	struct sockaddr_in serveraddr;
	
	struct address useraddr[100];
	struct sockaddr_in userinfo;
	socklen_t addrlen = 0;
	addrlen = sizeof(userinfo);

	struct msgbuf recvuser;
	int i = 0;

	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sockfd == -1)
	{
		perror("fail to socket");
		return -1;
	}
	
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_port = htons(SERVER_PORT);
	serveraddr.sin_addr.s_addr = inet_addr(SERVER_ADDR);
	bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
	
	memset(useraddr, 0, sizeof(useraddr));

	while(1)
	{
		memset(&recvuser, 0, sizeof(recvuser));
		memset(&userinfo, 0, sizeof(userinfo));
		nsize = recvfrom(sockfd, &recvuser, sizeof(recvuser), 0, (struct sockaddr *)&userinfo, &addrlen);
		if(nsize == -1)
		{
			return -1;
		}
		if(recvuser.type == USER_TYPE_INT)
		{
			for(i = 0; i < 100; i++)
			{
				if(useraddr[i].mark == 1)
				{
					continue;
				}
				else if(useraddr[i].mark == 0)
				{
					useraddr[i].mark = 1;
					useraddr[i].cltaddr.sin_family = AF_INET;
					useraddr[i].cltaddr.sin_port = userinfo.sin_port;
					useraddr[i].cltaddr.sin_addr.s_addr = userinfo.sin_addr.s_addr;
					printf("欢迎用户:%s来到直播间!\n", recvuser.name);
					break;
				}
			}
		}
		else if(recvuser.type == USER_TYPE_OUT)
		{
			for(i = 0; i < 100; i++)
			{
				if(memcmp(&useraddr[i].cltaddr, &userinfo, sizeof(userinfo)) == 0)
				{
						useraddr[i].mark = 0;
						printf("用户:%s离开直播间!\n", recvuser.name);
				}
			}
		}
		else if(recvuser.type == USER_TYPE_CHAT)
		{
			printf("%s(%s:%d)>%s\n", recvuser.name, inet_ntoa(userinfo.sin_addr), ntohs(userinfo.sin_port), recvuser.text);
			for(i = 0; i < 100; i++)
			{
				if(useraddr[i].mark != 0)
				{
					size = sendto(sockfd, &recvuser, sizeof(recvuser), 0, (struct sockaddr *)&useraddr[i].cltaddr, sizeof(useraddr[i].cltaddr));
					if(size == -1)
					{
						perror("fail to sendto");
						return -1;
					}
				}
			}
		}
	}	
	close(sockfd);

	return 0;
}

在这里head.h中定义了两个结构体,已经定义了客户发过来的状态

#ifndef _HEAD_H_
#define _HEAD_H_

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>

struct msgbuf
{
	int type;
	char name[32];
	char text[512];
};

struct address
{
	struct sockaddr_in cltaddr;
	int mark;
};

#define USER_TYPE_INT  100
#define USER_TYPE_OUT   200
#define USER_TYPE_CHAT  300

#define SERVER_ADDR  "192.168.1.162"
#define SERVER_PORT  5000

#endif

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

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

相关文章

Day22:安全开发-PHP应用留言板功能超全局变量数据库操作第三方插件引用

目录 开发环境 数据导入-mysql架构&库表列 数据库操作-mysqli函数&增删改查 数据接收输出-html混编&超全局变量 第三方插件引用-js传参&函数对象调用 完整源码 思维导图 PHP知识点&#xff1a; 功能&#xff1a;新闻列表&#xff0c;会员中心&#xff0…

Python爬虫——scrapy-3

目录 免责声明 任务 文件简介 爬取当当网内容单管道 pipelines.py items.py setting dang.py 当当网多管道下载图片 pipelines.py settings 当当网多页下载 dang.py pielines.py settings items.py 总结 免责声明 该文章用于学习&#xff0c;无任何商业用途 …

深度学习-2.3损失函数

文章目录 损失函数深度学习优化思想回归&#xff1a;误差平方和SSE二分类交叉熵损失函数1. 极大似然函数估计求解二分类交叉熵函数2.用tensor实现二分类交叉熵损失 多分类交叉熵损失函数1.由二分类推广到多分类2.用PyTorch实现多分类交叉熵损失 损失函数 在之前的文章中&#…

OpenAI劲敌吹新风! Claude 3正式发布,Claude3使用指南

Claude 3是什么&#xff1f; 是Anthropic 实验室近期推出的 Claude 3 大规模语言模型&#xff08;Large Language Model&#xff0c;LLM&#xff09;系列&#xff0c;代表了人工智能技术的一个显著飞跃。 该系列包括三个不同定位的子模型&#xff1a;Claude 3 Haiku、Claude 3…

Chapter20-Ideal gases-CIE课本要点摘录、总结(编辑中)

20.1 Particles of a gas Brownian motion Fast modules 速率的数值大概了解下&#xff1a; average speed of the molecules:400m/s speed of sound:approximately 330m/s at STP&#xff08;standard temperature and pressure&#xff09; Standard Temperature and Pres…

如何使用WinSCP结合Cpolar实现公网远程访问内网Linux服务器

文章目录 1. 简介2. 软件下载安装&#xff1a;3. SSH链接服务器4. WinSCP使用公网TCP地址链接本地服务器5. WinSCP使用固定公网TCP地址访问服务器 1. 简介 ​ Winscp是一个支持SSH(Secure SHell)的可视化SCP(Secure Copy)文件传输软件&#xff0c;它的主要功能是在本地与远程计…

linux上安装fastdfs及配置

一、基础环境准备 1、所需软件 名称说明libfastcommonfastdfs分离出的一些公用函数包fastdfsfastdas软件包fastdfs-nginx-modulefastdfst和nginx的关联模块nginxnginxl软件包 2、编辑环境 安装一些基础的支持环境 yum install git gccc gcc-c make automake autoconf libto…

图遍历算法

图的遍历算法有两种&#xff1a;深度优先遍历、广度优先遍历算法。 深度优先遍历算法就是从起始结点开始&#xff0c;只要有相邻且未被访问的结点就要直接进行访问&#xff0c;直到最后不能向下遍历为止&#xff0c;再回溯寻找下一个策略。 广度优先遍历算法&#xff0c;就是从…

线性代数笔记13--正交向量和正交子空间

0. 四个子空间 1. 正交向量 两向量点乘为0&#xff0c;向量正交。 A ⊤ B 0 A^{\top}B0 A⊤B0 勾股定理 ∣ ∣ x ∣ ∣ 2 ∣ ∣ y 2 ∣ ∣ ∣ ∣ x y ∣ ∣ 2 ||x||^2||y^2||||xy||^2 ∣∣x∣∣2∣∣y2∣∣∣∣xy∣∣2 验证正交条件 ∣ ∣ x ∣ ∣ 2 x ⊤ x x x ⊤ ∣…

vue2【详解】生命周期(含父子组件的生命周期顺序)

1——beforeCreate&#xff1a;在内存中创建出vue实例&#xff0c;数据观测 (data observer) 和 event/watcher 事件配置还没调用&#xff08;data 和 methods 属性还没初始化&#xff09; 【执行数据观测 (data observer) 和 event/watcher 事件配置】 2——created&#xf…

前TVB「御用泼妇」原来是亿万富婆,离婚后狂买楼养大子女。

今年72岁的昔日TVB老戏骨陈曼娜Manna姐最近突然亮相隔壁ViuTV的新剧《飞黄腾达》&#xff0c;本色出演炒股女富豪&#xff0c;她大赞剧集监制、导演有眼光&#xff0c;角色的背景与她本身十分相似&#xff0c;演起来可谓得心应手。 众所周知&#xff0c;陈曼娜最爱「买砖头」&a…

跟无神学AI之Tensorflow笔记搭建网络八股

虽然Pytorch在论文中使用较多&#xff0c;但是像Alphafold在蛋白质结构预测的模型&#xff0c;仍然是用Tensorflow写成&#xff0c;遂近期在学其中的语法。 本系列来自慕课北大软微曹健老师的Tensorflow笔记&#xff0c;摘选其中重要部分。 1.导包 2.定义训练集测试集和数据…

平台工程指南:从架构构建到职责分工

平台工程只是 DevOps 专业化的另一个术语&#xff0c;还是另有所指&#xff1f;事实可能介于两者之间。DevOps 及其相关的 DevXOps 有着浓厚的文化色彩&#xff0c;以各个团队为中心。不幸的是&#xff0c;在许多地方&#xff0c;DevOps 引发了新的问题&#xff0c;如工具激增和…

leetcode 热题 100_三数之和

题解一&#xff1a; 双指针遍历&#xff1a;暴力解法的三层遍历会超时&#xff0c;因此需要优化遍历的过程。首先是需要对结果进行去重&#xff0c;这里采用排序跳过重复值的做法&#xff0c;在指针遍历时跳过已经遍历过的相同值。在第一层循环确定第一个值后&#xff0c;剩下两…

【你也能从零基础学会网站开发】Web建站之HTML+CSS入门篇 常用HTML标签(3)

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;web开发者、设计师、技术分享 &#x1f40b; 希望大家多多支持, 我们一起学习和进步&#xff01; &#x1f3c5; 欢迎评论 ❤️点赞&#x1f4ac;评论 &#x1f4c2;收藏 &#x1f4c2;加关注 HTML框架集…

吴恩达机器学习笔记十五 什么是导数 计算图 大型神经网络案例

假设函数 J(w)w^2&#xff0c;当 w3 时&#xff0c; J(w)3*39 当我们给w增加一个很小的量时&#xff0c;观察J(w)如何变化。 例如 w30.001&#xff0c; 则J&#xff08;w&#xff09;9.006001&#xff0c;因此当w3且增加一个变化量 ε 时&#xff0c;J(w)将会增加 6ε&#x…

SpringCloud 微服务架构编码构建

一、前言 接下来是开展一系列的 SpringCloud 的学习之旅&#xff0c;从传统的模块之间调用&#xff0c;一步步的升级为 SpringCloud 模块之间的调用&#xff0c;此篇文章为第一篇&#xff0c;即不使用 SpringCloud 组件进行模块之间的调用&#xff0c;后续会有很多的文章循序渐…

【学习心得】websocket协议简介并与http协议对比

一、轮询和长轮询 在websocket协议出现之前&#xff0c;要想实现服务器和客户端的双向持久通信采取的是Ajax轮询。它的原理是每隔一段时间客户端就给服务器发送请求找服务器要数据。 让我们通过一个生活化的比喻来解释轮询和长轮询假设你正在与一位不怎么主动说话的老大爷&…

软考68-上午题-【面向对象技术2-UML】-事物

一、事物 UML中有4种事物&#xff1a; 结构事物&#xff1b;&#xff08;模型的静态部分&#xff09;行为事物&#xff1b;&#xff08;模型的动态部分&#xff09;分组事物&#xff1b;注释事物。 1-1、结构事物 1-2、行为事物 1-3、分组事物 1-4、注释事物 二、真题 真题1…

excel统计分析——裂区设计

参考资料&#xff1a;生物统计学 裂区设计&#xff08;split-plot design&#xff09;是安排多因素试验的一种方法&#xff0c;裂区设计对因素的安排有主次之分&#xff0c;适用于安排对不同因素试验精度要求不一的试验。 裂区设计时&#xff0c;先按第一因素的处理数划分主区&…