【计算机网络】socket编程

news2024/11/24 17:54:08

文章目录

  • 1. 网络通信的理解
  • 2.进程PID可以取代端口号吗?
  • 3. 认识TCP协议
  • 4. 认识 UDP协议
  • 5. socket编程接口
    • udp_server.hpp的代码解析
      • socket——创建 socket 文件描述符
      • Initserver——初始化
        • 1.创建套接字接口,打开网络文件
          • bind——绑定的使用
        • 2.给服务器指明IP地址和端口号
          • struct sockaddr_in的理解
          • bzero 清空
          • 代码实现
          • inet_addr ——字符串风格转化为4字节风格
          • 服务器自己指定IP地址
        • 3. 云服务器,或者一款服务器,一般不要指明某一个确定的IP
      • start ——启动
        • 1. 收到客户端发来的消息
          • recvfrom——获取用户数据报
          • inet_addr ——将4字节风格转为字符串风格
        • 2.将消息发给别人
          • sendto
    • udp_client.cc的代码解析
      • 客户端如何绑定?
      • 服务器为什么要自己绑定?
      • 代码实现
    • 完整代码
      • err.hpp (枚举错误码)
      • makefile
      • udp_client.cc(客户端的实现,无封装)
      • udp_clinet.hpp
      • udp_server.cc (有封装)
      • udp_server.hpp(服务器的实现)

1. 网络通信的理解

主机A将自己的数据交给主机B,就需要给主机B发送消息,主机B未来要给主机A回消息

但实际上 主机A将自己的数据交给主机B 并不是最终目的

如:你在淘宝上买了一件衣服,卖家发货后,从广东省发货 到 你所在的地区 ,最终包裹成功到达你的手上,你还需要决定这个快递该怎么用

数据的传送不是目的,让两台主机通过数据进行通信来协同完成任务才是目的


如:唐僧说要去西天去取经,唐僧所对应的寺庙是A主机,西天的大雷音寺是B主机,唐僧并不是到大类饮食就完了,这只是他的手段,
他还需要面见如来,如来会提供给他经书的服务


数据发起时,从主机A的传输层开始,交给主机B的传输层
而数据是从主机A的应用层中的某种客户端传来的
而将数据交给主机B的传输层不是直接目的,要把数据再交给应用层 中的某种服务器

主机A对应的客户端一定要启动起来,所以其本质是 进程

因为主机B的某种服务器在以进程的方式运行,所以可以随时随地能够访问某种服务

网络通信的本质是 进程间的通信


通信的第一个阶段:先将数据通过操作系统,将数据发送到目标主机(手段)
通信的第二个阶段:在本主机将收到的数据,推送给自己上层的指定进程

第一个阶段 可以通过TCP/IP协议完成,因为IP可以表示互联网上唯一的一台主机

当主机B的传输层把数据交给应用层,应用层对应的进程非常多
所以为了标识自己主机上网络进程的唯一性,提出了 端口号 的概念

端口号是传输层协议的字段,是一个2个字节16位的整数,用来标识系统层面上进程的唯一性

所以 IP地址 + 端口号 可以表示 互联网中唯一的一个进程

通信时,是有两个进程进行通信,所以就有源IP 和源 端口号 以及 目标IP 和目标 端口号
源IP 和源 端口号表示 互联网中唯一的一个进程
目标IP 和目标 端口号也表示 互联网中唯一的一个进程

所以 网络通信的本质 是通过IP+PORT号 构建唯一性,来进行网络进程间通信, 简称 套接字通信

2.进程PID可以取代端口号吗?

进程PID在系统层面上每个进程也是唯一的,也能表示该系统上进程的唯一性,所以用进程PID可以代替端口号的
但会存在一些问题
1.不是所有的进程都要进行网络通信,只有部分进程可能会网络通信,若用进程PID来作为网络标识该进程,就很难区分清楚那些是进行网络通信的,那些不是进行网络通信的

2. PID是操作系统进程管理的概念,网络模块也要包含进程管理的部分,要不然无法认识PID
增加了系统当中进程管理和网络管理的耦合度

3. 认识TCP协议

TCP协议(Transmission Control Protocol) 传输控制协议
特点:
传输层协议
面向连接
在通信过程中,会自带可靠性
面向字节流
在进行发和收数据时,在TCP层没有报文的概念,收到一堆的数据,把这一堆的东西一次将给上层的应用层,也可一个字节一个字节交
字节数据如何解释TCP不关心,只关心要都多少,给你多少,最终解释信息由应用层自己解释,这种从称之为字节流

4. 认识 UDP协议

UDP协议(User Datagram Protocol)用户数据报协议
特点:
传输层协议
无连接
不可靠传输
面向数据报
如:收快递,收一个就是一个完整的快递,具体的快递不可能收半个或者一个半,若对方发了三次,你就必须收三次

5. socket编程接口

实验室做出来一套进程间通信的标准,既可在本地通信,又可以在网络跨主机通信的标准 即 socket标准 隶属于 posix标准

最常见的为 基于网络通信的套接字 sockaddr_in

预间套接字 (使用在两个进程间使用本地进程通信的) sockaddr_un

套接字的设计者为了能够让所有人以 一套接口的方式 既能本地通信 又能网络通信,
所以设计出一个公共的数据结构 叫做 struct sockaddr
若想进行网络通信 (struct sockaddr_in) 或者 进行 本地通信 (struct sockaddr_un) ,使用 sockaddr 进行强制转换即可


在结构最开始时,都要有16位的地址类型
AF_INET 与AF_UNIX 实际上都是宏,用整数来表示的
将地址进行比较判断,
若等于 AF_INET,就为网络通信,把 sockaddr强转为 sockaddr_in
若等于 AF_UNIX,就为本地通信,把 sockaddr强转为 sockaddr_un


udp_server.hpp的代码解析

通过网络协议栈的通信功能 ,来把数据交付给对方的应用层,来完成双方进程的通信

将客户端的数据交给 服务端 ,就需要给服务端发送消息,服务端再给客户端回消息


在 udp_server.hpp 中 使用namspace 将命名空间 命名为 ns_server
其中再定义一个类 udpserver

socket——创建 socket 文件描述符

输入 man socket创建套接字

第一个参数 domain ,用于区分 进行网络通信还是 本地通信
若想为网络通信,则使用 AF_INET
若想为本地通信,则使用 AF_UNIX

第二个参数 type, 套接字对应的服务类型

在这里插入图片描述

SOCK_STREAM 流式套接
SOCK_DGRAM 无连接不可靠的通信(用户数据报)

第三个参数 protocol ,表示想用那种协议,协议默认为0
若为 流式套接,则系统会认为是TCP协议 ,若为用户数据报,则系统会认为是UDP协议

套接字的返回值:若成功则返回文件描述符,若失败则返回 -1

Initserver——初始化

1.创建套接字接口,打开网络文件

在这里插入图片描述
使用socket套接字,创建出 网络通信、UDP协议
若套接字返回-1表示失败,则初始化也就失败,程序就没有必要在继续运行了,所以使用exit终止程序

若套接字创建成功,则返回文件描述符
文件描述符的前三个分别被 标准输入 标准输出 标准错误占用,所以此时的文件描述符应该打印出3

bind——绑定的使用

输入 man 2 bind ,查看绑定

给一个套接字绑定一个名字
第一个参数 sockfd 为 文件描述符
第二个参数 addr 为 通用结构体类型
第三个参数 addrlen 为 第二个参数的实际长度大小

bind返回值:若成功,则返回0,若失败,返回 -1

2.给服务器指明IP地址和端口号

想要使用struct sockaddr_in类型 需添加头文件

定义一个 struct sockaddr_in(网络通信) 类型的 变量 local

struct sockaddr_in的理解

在这里插入图片描述
将 struct sockaddr_in 转到定义
16位地址类型:将 sa_prefix替换成 sin_ ,sin## family 实际上为 sin_family
此时的 sin_port 对应 当前绑定的端口号
sin_addr对应的是IP地址
再次将 in_addr转到定义,IP地址就是一个32位的整数

bzero 清空

sin_zero 作为 该结构体的填充字段
结构体可能很大,用不完,则使用填充字段将其填充上即可

输入 man bzero

将有n个字节的缓冲区,全部写为0

代码实现

在这里插入图片描述

将local对应的family(16位地址类型) 设置为 网络通信


设置一个私有的端口号port_


在这里插入图片描述
在类外设置一个端口号,用于构造时,若没有端口号传入,则8082充当缺省值


若我给你发消息,未来也需要将消息发回来,所以就必须知道我的IP地址和端口号
即端口号 以报文的形式发送到网络中

类内定义的port_,被称为本地主机序列, 需要把这个port_从主机序列 转成网络序列

输入 man htons ,表示短整数的主机转网络序列



定义一个私有的变量 ip_ 由于我们设置的IP地址是字符串风格的,而系统中的IP地址是4字节风格的 所以就需要将字符串风格的转化为 4字节风格的
inet_addr ——字符串风格转化为4字节风格

输入 man inet_addr

作用为:将字符串风格的IP地址 转化为 4字节风格的IP地址,并 默认会把主机序列 转换为 网络序列


由于local实际上定义在用户层的栈上,并没有在内核

所以借助bind,将填充好的套接字字段和文件字段,进行绑定关联,这样的文件才是网络文件
由于local 是 struct sock_addr_in 类型 ,需要强转为 struct sockaddr 公共类型


服务器自己指定IP地址

此时运行 udp_server可执行程序,会发现套接字创建成功,但绑定会失败


云服务器 不需要bind IP地址,需要让服务器自己指定IP地址


所以在main函数中添加命令行参数
命令行参数
main函数的两个参数,char* argv[] 为指针数组 ,argv为一张表,包含一个个指针,指针指向字符串
int argc,argc为数组的元素个数

设计一个usage函数,用以表示出 出现问题的可执行程序的名字 proc


再次创建一个err.hpp,使用enum枚举,将USAGE_ERR设置成1 ,默认将SOCKET_ERR(套接字报错)设置为2,
将 BIND_ERR(绑定错误)设置为3


通过argv数组的第二个下标指明字符串风格的端口号,再通过atoi将字符串转化为整数
最终只传入 端口号即可


在这里插入图片描述

3. 云服务器,或者一款服务器,一般不要指明某一个确定的IP

在这里插入图片描述

使用 INADDDR_ANY , 让udpserver在启动的时候,bind本主机上的任意IP


将 INADDDR_ANY 转到定义,实际上为缺省的0值


start ——启动

服务器本质是一个死循环,永远不退出
如:半夜打开王者荣耀,依旧可以玩


1. 收到客户端发来的消息

recvfrom——获取用户数据报

输入 man recvfrom, 获取用户数据报

第一个参数 sockfd 为 套接字
第二个参数 buf 为 自己定义的缓冲区
第三个参数 len 为 缓冲区的长度
第四个参数 flags 为读取方式,默认设为0,以阻塞方式读取
剩余两个参数 src_addr 和 addrlen 为 输入 输出型 参数
使用recvfrom收到数据,最终还要把数据还回去,想要还回去就必须知道别人是谁
src_addr 为 作为一个结构体,内部记录客户端的IP地址和端口号
addrlen 为 输出时结构体的大小
返回值:若大于0,则读取成功


定义一个 struct sockaddr_in(网络通信) 类型的 变量 peer
使用 len 来表示 未来的结构体大小

若n大于0,则读取成功,将最后一个位置的下一个位置设为\0
若读取失败,则继续读取


peer下的IP地址为 4字节整数,需要将其转为字符串风格

inet_addr ——将4字节风格转为字符串风格

输入 man inet_addr,将4字节IP转为字符串风格的IP


peer下的端口号为网络序列,想要获取客户端的端口号 clientport,需要使用 ntohs 将网络序列转为主机序列

2.将消息发给别人

sendto

输入 man sendto

第一个参数 sockfd 为 套接字
第二个参数 buf 为 自己定义的缓冲区
第三个参数 len 为 缓冲区的长度
第四个参数 flags 为读取方式,默认设为0,以阻塞方式读取
剩余两个参数 src_addr 和 addrlen 为 输入 输出型 参数
使用recvfrom收到数据,最终还要把数据还回去,想要还回去就必须知道别人是谁
src_addr 为 将以前收到的消息转会给客户端
addrlen 为 输出时结构体的大小
返回值:若大于0,则读取成功



udp_client.cc的代码解析

第一个参数 使用 AF_INET,表示网络通信
第二个参数 使用SOCK_DRAM,表示数据报
第三个参数 默认设为0,由于上述为数据报,所以为UDP协议


客户端如何绑定?

客户端是需要绑定的
socket通信的本质 是 客户端的IP与端口号 与 服务器的IP与端口号 进行网络版本的进程间通信
但客户端是不需要自己绑定的,由操作系统自动进行绑定
如:电脑和手机充满大量客户端,这些客户端来自于不同的企业,每个客户端的端口号不可以是固定的
必须让操作系统随机去选择,本质是为了防止确定的客户端被别人去占用,减少客户端层面的冲突
所以客户端的端口号要让操作系统随机分配,防止客户端出现启动冲突

服务器为什么要自己绑定?

1.服务器的端口 是 众所周知并不能随意改变的
如:110是报警电话,不可能报警电话每天都变,否则会导致当真正想打电话时都不知道打那个

2.服务器都是一家公司的,所以端口号需要统一规范化
如:淘宝不会把自己的服务部署到知乎上


代码实现

进行while循环,向服务器发送消息

目前没有消息,所以让用户输入充当消息源
使用 sendto,将消息发送给服务端

作为客户端将消息发送给 服务器主机
想要运行 客户端 ,就需要服务器的IP 和端口号


在这里插入图片描述
借助命令行参数,通过用户的输入的第二个参数 作为服务器的IP
用户输入的第三个作为 服务器的端口号

虽然此时服务器的IP和端口号知道了,但是想要借助sendto,后两个参数是需要套接字结构体


新建一个结构体server,内部包含服务器的IP和端口号
使用 htons ,将主机序列转为网络序列
使用inet_addr,将字符串转化为 4字节


在这里插入图片描述

此时 sendto的后两个参数 添加 创建的结构体 sever ,来完成发送服务器的任务
由于server 的类型 是 struct sockaddr_in ,而参数的类型为 公共结构体类型 struct sockaddr ,所以需要强转


使用 revfrom ,获取用户数据报
收到来自服务器转回来的消息 ,所以 定义一个 temp结构体,用于接收

在首次系统调用发送数据的时候,操作系统在底层随机选择客户端的端口号 加上自己的IP
先构建bind,再构建发送的数据报文

完整代码

err.hpp (枚举错误码)

#pragma once


enum 
{
    USAGE_ERR=1,
    SOCKET_ERR,
    BIND_ERR
};

makefile

.PHONY:all
all: udp_client udp_server

udp_client:udp_client.cc
	g++ -o  $@ $^ -std=c++11
udp_server:udp_server.cc
	g++ -o $@  $^ -std=c++11

.PHONY:clean
clean:
	rm -f udp_clinet udp_server
  

udp_client.cc(客户端的实现,无封装)

#include"udp_client.hpp"
#include"err.hpp"
#include<cstring>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>

static void usage(std::string proc)
{
    std::cout<<"usage:\n\t"<<proc<<"serverip serverport\n"<< std::endl;
}
// ./udp_client serverip sevrerport
int main(int argc ,char* argv[])//命令行参数 传入的是 客户端的运行 服务器的IP和端口号
{
  if(argc!=3)
  {
    std::cout<<" "<<std::endl;
    exit( USAGE_ERR);//终止程序
  }
   std::string serverip = argv[1];//服务器的IP
   uint16_t serverport =atoi(argv[2]);//服务器的端口号

  int sock=socket(AF_INET,SOCK_DGRAM,0);
  if(sock<0)//创建套接字失败
  {
     std::cout<<"create socket error"<<std::endl;
     exit( SOCKET_ERR);
  }

  //明确server是谁
  struct sockaddr_in server;//设置网络通信的结构体
  memset(&server,0,sizeof(server)); //将结构体清空
  server.sin_family=AF_INET;
  server.sin_port=htons(serverport);//端口号
  server.sin_addr.s_addr=inet_addr(serverip.c_str());//IP地址

  while(true)
  {
    //用户输入  
    std::string message;
    std::cout<<  "please enter# ";
    std::cin>> message;
    //发送消息
    sendto(sock,message.c_str(),message.size(),0,(struct sockaddr*)&server,sizeof(server));
   
   //接收消息
    char buffer[1024];
    struct sockaddr_in temp;
    socklen_t len=sizeof(temp);
    int n=recvfrom(sock,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&temp,&len);
    if(n>0)
    {
      buffer[n]=0;
      //收到回显消息
      std::cout<<"server echo"<<buffer<<std::endl;
    }
  }
    return 0;
}

udp_clinet.hpp

#pragma once
#include<iostream>
using namespace std;

udp_server.cc (有封装)

#include"udp_server.hpp"
#include"err.hpp"
#include<memory>
#include<string>
using namespace ns_server;
using namespace std;

static void usage(string proc)
{
    std::cout<<"usage:\n\t"<<proc<<"prot\n"<< std::endl;
}

//udp_server port
int main(int argc,char*argv[])//命令行参数
{
    if(argc!=2)//若命令行参数个数不为2,则当前会报错
    {
        usage(argv[0]);
        exit(USAGE_ERR);//终止程序
    }
    //端口号
    uint16_t port=atoi(argv[1]);//atoi可将字符串转化为整数

    //只需传入由用户指明的端口号
   unique_ptr<UdpServer> usvr(new UdpServer (port));

   usvr->Initserver();//服务器的初始化
   usvr->Start();//启动服务器
    return 0;
}






udp_server.hpp(服务器的实现)

#pragma once
#include<iostream>
#include<cerrno>
#include<cstring>
#include<cstdlib> 
#include<strings.h>
#include<functional>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/socket.h>
#include"err.hpp"

namespace  ns_server
{
  const static uint16_t  default_port=8082;//设置端口号为8082 
   class UdpServer
   {
     public:
       UdpServer(uint16_t port=default_port)//构造
       :port_(port)
       {}

      void  Initserver()//初始化
       {
        //1.创建套接字接口,打开网络文件
        sock_=socket(AF_INET,SOCK_DGRAM,0);
        if(sock_<0)//创建失败
        {
          //打印错误信息
            std::cout<<" create socket   error: "<<strerror(errno)<<std::endl;
            exit(SOCKET_ERR);//终止程序
        }
         std::cout<<"create socket success:"<<sock_<<std::endl;//3

         //2.给服务器指明IP地址和端口号
         struct sockaddr_in local;
        bzero(&local,sizeof(local));//全部置为0
        local.sin_family=AF_INET;//将16位地址类型 置为 网络通信
         local.sin_port=  htons(port_); //主机转网络的端口号

         //1.需要将字符串风格转化为 4字节
         //2.需要 将主机序列转换为 网络序列
         local.sin_addr.s_addr= INADDR_ANY ; //bind本机上的任意IP
         
         //bind 绑定
         int n=bind(sock_,(struct sockaddr*)&local,sizeof(local));
         if(n<0)//绑定失败
         {
           std::cout<<" bind  socket   error: "<<strerror(errno)<<std::endl;
           exit(BIND_ERR);
         }
           std::cout<<"bind socket success:"<<sock_<<std::endl;//3
       }
       void Start()//启动
       {
        char buffer[1024];//用于保护用户数据
         //设置一个死循环
           while(true)
           {
            //1.收到客户端发来的消息
             struct sockaddr_in peer;
             socklen_t len=sizeof(peer);//传入的缓冲区大小
             int n=recvfrom(sock_,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&peer,&len);
             if(n>0)
             {
              buffer[n]='\0';
             }
             else 
             {
              //读取失败,则继续读取
              continue;
             }

             //提取客户端信息
             //4字节IP转为 字符串IP
             std::string clientip =inet_ntoa(peer.sin_addr);//客户端IP
             //将网络序列转换为主机序列
             uint16_t clientport =ntohs(peer.sin_port);//客户端 端口号
             std::cout<<clientip<<"-"<<clientport<<"-"<<"get message# "<<buffer<<std::endl;

             //2.将消息发给别人
             sendto(sock_,buffer,strlen(buffer),0,(struct sockaddr*)&peer,sizeof(peer));
             
           }
       }
       ~UdpServer()//析构
       {}
     private:
     int sock_; //文件描述符
     uint16_t port_;//端口号 
   }; 
}

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

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

相关文章

【雕爷学编程】Arduino动手做(186)---WeMos ESP32开发板12

37款传感器与模块的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&#x…

Background-3 导入导出相关操作基础知识

文章目录 一、导入导出的相关操作一.load_file()导出文件1.**使用条件&#xff1a;**2.实际注入中的两个难点3.mysql注入load_file()常用路径 二、文件导入数据库三、导入到文件1.第一种直接将 select 内容导入到文件中&#xff1a;2.**第二种修改文件结尾** 总结 一、导入导出…

NotifyIcon控件基本使用

作用&#xff1a;系统托盘图标控件&#xff0c;用于应用程序最小化或后台运行时在托盘上面显示图标。 常用属性&#xff1a; 对象名称name&#xff0c;icon图标&#xff0c;右键菜单contextMenuStrip 常用事件&#xff1a; 后台代码示范&#xff1a; NotifyIcon、contextMen…

SQL ASNI where from group order 顺序

SQL语句执行顺序&#xff1a; from–>where–>group by -->having — >select --> order 第一步&#xff1a;from语句&#xff0c;选择要操作的表。 第二步&#xff1a;where语句&#xff0c;在from后的表中设置筛选条件&#xff0c;筛选出符合条件的记录。 …

QtAV for ubuntu16.04

下载ubuntu https://releases.ubuntu.com/16.04/ubuntu-16.04.7-desktop-amd64.iso 下载ffmpeg https://ffmpeg.org/download.html 下载QtAV https://github.com/wang-bin/QtAV/releases 更新 sudo apt update 安装库 sudo apt-get install libglu1-mesa-dev freeglut3-dev…

c++11 标准模板(STL)(std::basic_ofstream)(四)

定义于头文件 <fstream> template< class CharT, class Traits std::char_traits<CharT> > class basic_ofstream : public std::basic_ostream<CharT, Traits> 类模板 basic_ofstream 实现文件上基于流的高层输出操作。它将 std::basic_ost…

python 封装sql 增删改查连接MySQL

select * from Teacher limit 10 连接字符串配置MysqlConfig.py class MysqlConfig:HOST 192.168.56.210PORT 3306USER rootPASSWORD 1qaz0987654321DBStudentDBCHARSET utf8封装增删改查MysqlConnection.py Author: tkhywang 2810248865qq.com Date: 2023-06-19 15:44:48 Las…

Python - 【socket】 客户端client重连处理简单示例Demo(一)

一. 前言 在Python中&#xff0c;使用socket进行网络通信时&#xff0c;如果连接断开&#xff0c;可以通过以下步骤实现重连处理 二. 示例代码 1. 定义一个函数&#xff0c;用于建立socket连接 import socketdef connect_socket(host, port):while True:try:# 建立socket连…

webpack基础知识七:说说webpack proxy工作原理?为什么能解决跨域?

一、是什么 webpack proxy&#xff0c;即webpack提供的代理服务 基本行为就是接收客户端发送的请求后转发给其他服务器 其目的是为了便于开发者在开发模式下解决跨域问题&#xff08;浏览器安全策略限制&#xff09; 想要实现代理首先需要一个中间服务器&#xff0c;webpac…

三个主流数据库(Oracle、MySQL和SQL Server)的“单表造数

oracle 1.创建表 CREATE TABLE "YZH2_ORACLE" ("VARCHAR2_COLUMN" VARCHAR2(20) NOT NULL ENABLE,"NUMBER_COLUMN" NUMBER,"DATE_COLUMN" DATE,"CLOB_COLUMN" CLOB,"BLOB_COLUMN" BLOB,"BINARY_DOUBLE_COLU…

flask-----蓝图

1.引入蓝图 flask都写在一个文件中&#xff0c;项目这样肯定不行&#xff0c;会导致循环导入的问题&#xff0c;分目录&#xff0c;分包&#xff0c;使用蓝图划分目录。 2.使用蓝图 步骤如下&#xff1a; -1 实例化得到一个蓝图对象-order_blueBlueprint(order,__name__,tem…

Linux(环境变量)

Linux&#xff08;环境变量&#xff09; 常见环境变量查看环境变量方法和环境变量相关的指令环境变量的组织方式通过代码如何获取环境变量 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数如&#xff1a;我们在编写C/C代码的时候&…

Goland设置运行时配置指定配置文件

目录 遇到了问题--GoLand读取不到配置文件的命令行参数查找问题解决 遇到了问题–GoLand读取不到配置文件的命令行参数 今天在命令行执行go run user.go -f etc/user.yaml依此来指定程序运行时的配置文件&#xff0c;最后可以运行。 但是这种方式运行&#xff0c;我就没法在G…

error C4430 缺少类型说明符 - 假定为 int。注意 C++ 不支持默认 int

出现原因&#xff1a;两个类头文件相互包含 使用声明类代替头文件包含

基于vue医院分时段预约挂号系统java病历管理系统snsj0

伴随着我国社会的发展&#xff0c;人民生活质量日益提高。互联网逐步进入千家万户&#xff0c;改变传统的管理方式&#xff0c;医院病历管理系统以互联网为基础&#xff0c;利用java技术&#xff0c;和mysql数据库开发设计一套医院病历管理系统&#xff0c;提高工作效率的同时&…

【学习笔记】Java安全之反序列化

文章目录 反序列化方法的对比PHP的反序列化Java的反序列化Python反序列化 URLDNS链利用链分析触发DNS请求 CommonCollections1利用链利用TransformedMap构造POC利用LazyMap构造POCCommonsCollections6 利用链 最近在学习Phith0n师傅的知识星球的Java安全漫谈系列&#xff0c;随…

QT生成可执行文件的步骤

QT生成可执行文件的步骤 第一步&#xff1a;debug为release&#xff0c;然后进行编译 第二步&#xff1a;添加QT生成必要的库 首先&#xff0c;建立一个新的文件夹&#xff0c;然后将Release中的可执行文件拷贝到新的文件夹中 然后&#xff0c;在新建文件夹中生成必要的库 …

Docker学习(二十四)报错速查手册

目录 一、This error may indicate that the docker daemon is not running 报错docker login 报错截图&#xff1a;原因分析&#xff1a;解决方案&#xff1a; 二、Get "https://harbor.xxx.cn/v2/": EOF 报错docker login 报错截图&#xff1a;原因分析&#xff1a…

vue3部署宝塔后请求接口404以及刷新页面404的问题解决方案

技术&#xff1a;vue3.2.13 UI框架:element-plus 2.1.1 服务器&#xff1a;腾讯云Centos系统宝塔面板 Nginx:1.22.1 前提&#xff1a;宝塔面板》网站PHP项目 已经新建了项目 1.处理vue页面刷新报错404 如上图&#xff0c;在PHP网站》设置》配置文件&#xff0c;新增如下代码…

EMD经验模态分解介绍

EMD概述 其实一种信号分解方法&#xff0c;是一种自适应的数据处理方法&#xff0c;适合非线性和非平稳时间序列的分析和研究&#xff0c;其本质是对数据序列或信号的平稳化处理。 将上面6个信号叠加如下&#xff1a; 就是6个简单信号叠加&#xff0c;形成一个复杂信号。 核心…