【网络】套接字 -- UDP
🥁作者: 华丞臧.
📕专栏:【网络】
各位读者老爷如果觉得博主写的不错,请诸位多多支持(点赞+收藏+关注
)。如果有错误的地方,欢迎在评论区指出。
推荐一款刷题网站 👉 LeetCode刷题网站
文章目录
- 一、网络编程套接字
- 1.1 认识端口号
- 1.2 认识UDP和TCP协议
- 1.3 网络字节序
- 二、UDP套接字
- 2.1 sockaddr结构
- 2.2 简单的UDP网络程序
- 2.1 socket 常见API
- recvform
- bind
- inet_addr
- 2.1 封装 UdpSocket
- server
- init
- start
- 2.2 udpclient
- 2.4 日志显示
- 2.5 测试
一、网络编程套接字
在数据包的头部中,有两个IP地址,分别叫做源IP地址和目的IP地址;但是光有这两个IP地址不能实现网路通信;在计算机上进行通信的时候,实际上是用户和用户在进行网络通信,而用户通常是用程序体现的,也就是说用户是通过计算机上的某一个进程(软件)来进行数据的交互。
结论:网络通信的本质就是进程间的通信。
因此在实现网络通信时,不仅需要IP地址来确保主机的唯一性,还需要一个标记来确保主机上进程的唯一性。我们将这个表示主机上进程唯一性的标记称为端口号。
1.1 认识端口号
端口号(port)是传输层协议的内容。
- 端口号是一个2字节16位的整数。
- 端口号用来标识一个进程, 告诉操作系统, 当前的这个数据要交给哪一个进程来处理。
- IP地址 + 端口号能够标识网络上的某一台主机的某一个进程。
- 一个端口号只能被一个进程占用。
- 端口号可以将操作系统的进程管理和网络解耦。
- 进程不一定都需要网络通信,端口号可以标识需要进行网络通信的进程。
- 0~1023的端口号是已经被使用了的,用户的端口号只能从1024 ~ 65536。
理解端口号和进程PID:
- PID表示唯一一个进程;
- 端口号也表示唯一一个进程;
- 一个进程可以绑定多个端口号;
- 一个端口号只能绑定唯一一个进程。
1.2 认识UDP和TCP协议
传输层协议(TCP和UDP)的数据段中有两个端口号,分别叫做源端口号和目的端口号,就是在描述 “数据是谁发的, 要发给谁”。
对TCP(Transmission Control Protocol 传输控制协议)有一个直观的认识,此处先了解TCP:
- 传输层协议
- 有连接
- 可靠传输
- 面向字节流
对UDP(User Datagram Protocol 用户数据报协议)有一个直观的认识,此处先了解UDP:
- 传输层协议
- 无连接
- 不可靠传输
- 面向数据报
UDP实现足够简单,TCP实现较为复杂;两个协议各有优缺点,不同场景选择合适的协议即可。
1.3 网络字节序
内存中的多字节数据相对于内存地址有大端和小端之分, 磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分, 网络数据流同样有大端小端之分, 那么如何定义网络数据流的地址呢?
两台主机进行网络通信,发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出;接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存;因此,网络数据流的地址应这样规定:先发出的数据是低地址,后发出的数据是高地址。
世界各地的计算机生产厂商非常多, 因此对于发送方和接收方的大小端字节序是无法确定的。无法控制通信双方主机,但是我们可以规定网络中的字节序;TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节。不管这台主机是大端机还是小端机,都会按照这个TCP/IP规定的网络字节序来发送/接收数据;如果当前发送主机是小端,就需要先将数据转成大端;否则就忽略, 直接发送即可。
为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络
字节序和主机字节序的转换。
- 这些函数名很好记,h表示host,n表示network,l表示32位长整数,s表示16位短整数。
- 例如htonl表示将32位的长整数从主机字节序转换为网络字节序,例如将IP地址转换后准备发送。
- 如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回。
- 如果主机是大端字节序,这些函数不做转换,将参数原封不动地返回。
二、UDP套接字
2.1 sockaddr结构
socket API是一层抽象的网络编程接口,适用于各种底层网络协议,如IPv4、IPv6,以及后面要讲的UNIX Domain Socket。然而,各种网络协议的地址格式并不相同。用于本地通信和用于网络通信的套接字接口需要的数据都是不同的,为了能够使用统一的接口来实现网络通信和本地通信,接口设计者给出了一个 抽象结构,如下图:
系统中存在三种结构体,struct sockaddr(抽象类型)、struct sockaddr_in(INET网路套接字)、struct sockaddr_un(Unix域套接字套接字)。struct sockaddr内部会处理判断数据的前16位进行类型识别,然后强转成对应的类型实现切片,可以理解为C++的中多态。
-
IPv4和IPv6的地址格式定义在netinet/in.h中,IPv4地址用sockaddr_in结构体表示,包括16位地址类型, 16位端口号和32位IP地址。
-
IPv4、IPv6地址类型分别定义为常数AF_INET、AF_INET6。这样,只要取得某种sockaddr结构体的首地址,不需要知道具体是哪种类型的sockaddr结构体,就可以根据地址类型字段确定结构体中的内容。
-
socket API可以都用struct sockaddr *类型表示,在使用的时候需要强制转化成sockaddr_in;这样的好处是程序的通用性, 可以接收IPv4, IPv6,以及UNIX Domain Socket各种类型的sockaddr结构体指针做为参数。
sockaddr 结构
sockaddr_in 结构
虽然socket api的接口是sockaddr, 但是我们真正在基于IPv4编程时, 使用的数据结构是sockaddr_in;这个结构里主要有三部分信息: 地址类型, 端口号, IP地址。
in_addr结构
in_addr用来表示一个IPv4的IP地址. 其实就是一个32位的整数。
2.2 简单的UDP网络程序
2.1 socket 常见API
// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)
int socket(int domain, int type, int protocol);// 绑定端口号 (TCP/UDP, 服务器)
int bind(int socket, const struct sockaddr *address,socklen_t address_len);
说明:
-
domain:域,进行本地通信还是网络通信。
- AF_UNIX:本地通信;
- AF_INET:IPV4;
-
type:套接字类型,决定通信对应的报文类型,常用的为流式和用户数据报。
-
protocol:协议类型,网络应用中直接设为0即可。
-
socket套接字返回的是文件描述符,可以理解所有网络操作最终都是文件描述符级的操作。
recvform
用于从套接字文件描述符中读取数据。
#include <sys/types.h>#include <sys/socket.h>ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
说明:
- sockfd:套接字
- buf:用于接收数据的指针,从sockfd文件中读取的数据放入指针指向的空间中;
- len:读取数据的字节数;
- flags:模式;
- src_addr:用于接收读取对方的port和ip地址;
- addrlen:src_addr数据的字节大小;
bind
用于绑定网络信息,指明ip和port。
#include <sys/types.h>
#include <sys/socket.h>int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
- sockfd:套接字文件描述符;
- addr:需要绑定的sockaddr结构;
- addrlen:对应sockaddr结构的字节大小;
inet_addr
用于将字符串中的点分十进制转换成32位4字节的表示形式。
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>int inet_aton(const char *cp, struct in_addr *inp);in_addr_t inet_addr(const char *cp);in_addr_t inet_network(const char *cp);char *inet_ntoa(struct in_addr in);struct in_addr inet_makeaddr(int net, int host);in_addr_t inet_lnaof(struct in_addr in);in_addr_t inet_netof(struct in_addr in);
2.1 封装 UdpSocket
server
server是提供服务的一端,可以理解为服务器,用来接收用户传输的消息,同时也可以给用户发消息;可以将服务器封装成一个类,类当中包含套接字的初始化以及提供服务的接口,启动服务器时必须将端口号以参数的形式传递给main函数,ip地址可传可不传。
#include <iostream>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>#include "Log.hpp"static void Usage(const std::string porc)
{std::cout << "Usage:\n\t" << porc << " port [ip]" << std::endl;
}// 写一个简单的udpSever
// 云服务器有一些特殊情况:
// 1. 禁止你bind云服务器上的任何确定IP, 只能使用INADDR_ANY,如果你是虚拟机,随意class UdpServer
{
public:UdpServer(int port, std::string ip = ""):sockfd_(-1),port_(port),ip_(ip){}~UdpServer(){}
public:void init() //初识化server{} void start() //server开始服务{}
private:// 服务器的fdint sockfd_;// 服务器必须得有端口号信息uint16_t port_;// 服务器必须得有IP地址std::string ip_;
};// ./server port ip
int main(int argc, char *argv[])
{if(argc != 2 && argc != 3) {Usage(argv[0]);exit(PARA_ERR);}uint16_t port = atoi(argv[1]); std::string ip;if(argc == 3){ip = argv[2];}UdpServer server(port,ip);server.init(); // 创建并配置套接字server.start(); // 提供服务return 0;
}
init
初识化的任务主要是创建套接字,将套接字绑定网络信息指明ip和port。一般初识化分为以下几个步骤:
void init(){// 1. 创建套接字// domain -- 域// type -- 套接字类型,SOCK_DGRAM--数据报格式// protocol -- 协议类型,网络应用中:0// 返回值其实是文件描述符sockfd_ = socket(AF_INET, SOCK_DGRAM, 0); //就是打开一个文件if(sockfd_ < 0){logMessage(FATAL, "socket:%s:%d", strerror(errno), sockfd_);exit(SOCK_ERR);}logMessage(DEBUG, "socket create success:%d", sockfd_);// 2. 绑定网络信息,指明ip+port// 2.1 先填充基本信息到 struct sockaddr_instruct sockaddr_in local;bzero(&local, sizeof(local)); //初始化为0local.sin_family = AF_INET; //填充协议家族,域local.sin_port = htons(port_); //填充服务对应的端口号信息,一定会发给对方,因此port_一定回到网络中//local.sin_addr;local.sin_addr.s_addr = ip_.empty()? htonl(INADDR_ANY) : inet_addr(ip_.c_str()); // htonl将INADDR_ANY转换成32位网络字节序, inet_addr将字符串中的点分十进制转换成32位比特位if(bind(sockfd_, (const struct sockaddr*)&local, sizeof(local)) == -1){logMessage(FATAL, "bind:%s", strerror(errno));exit(BIND_ERR);}logMessage(DEBUG, "socket bind success:%d", sockfd_);//完成}
start
start()是server提供服务的接口,因此该函数必须是一个死循环(服务器都是在一个死循环当中)以给用户提供持续的服务;在start函数中,主要完成接收用户发送的消息并且将消息提取出来,其主要步骤如下图:
void start()
{// 服务器都是在一个死循环当中char inbuffer[1024]; //将来读取到的数据,都放在这里char outbuffer[1024]; //将来发送的数据,都放在这里while(true){struct sockaddr_in peer; //输出型参数socklen_t len = sizeof(peer); //输入输出型参数// UDP是无连接的// 对方发消息,你需要接收消息ssize_t s = recvfrom(sockfd_, inbuffer, sizeof(inbuffer) - 1, 0, \(struct sockaddr*)&peer, &len);logMessage(DEBUG, "server 提供服务中.....");if(s > 0) {//接收成功inbuffer[s] = '\0';}else if(s == -1){//logMessage(WARINING, "recvfrom fialed:%s[%d]", strerror(errno), sockfd_);continue;}// 读取成功的,除了读取到对方的数据,你还要读取到对方的网络地址[ip:port]std::string peerIp = inet_ntoa(peer.sin_addr); //拿到对方的ipuint32_t peerPort = ntohs(peer.sin_port); //拿到对方的port// 打印出来客户端给服务器发送过来的消息logMessage(NOTICE, "[%s:%d]# %s", peerIp.c_str(), peerPort, inbuffer);logMessage(DEBUG, "server 提供服务中.....");//sleep(1);}
}
2.2 udpclient
客户端用来连接服务器,并且使用服务器提供的服务;用户想要客户端与服务器进行网络通信就必须将服务器使用的端口号和ip传给客户端,客户端通过端口号和ip可以实现与服务器地网络通信。
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include "Log.hpp"
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>static void Usage(std::string name)
{std::cout << "Usage:\n\t" << name << " server_ip server_port" << std::endl;
} // ./udpClient IP port
int main(int argc, char* argv[])
{if(argc != 3) //必须等于3,必须传ip和port{Usage(argv[0]);exit(PARA_ERR);}std::string ip = argv[1];uint16_t port = atoi(argv[2]);// 2. 创建客户端// 2.1 创建socketint sockfd = socket(AF_INET, SOCK_DGRAM, 0);assert(sockfd > 0);struct sockaddr_in ser;bzero(&ser, sizeof ser);ser.sin_family = AF_INET; //填充与服务器相同的协议ser.sin_port = htons(port); //服务器的端口号ser.sin_addr.s_addr = inet_addr(ip.c_str()); //服务器ipstd::string buffer;while(true){std::cerr << "Please Enter# ";std::getline(std::cin, buffer);// 发送消息给serversendto(sockfd, buffer.c_str(), buffer.size(), 0,(const struct sockaddr *)&ser, sizeof(ser)); // 首次调用sendto函数的时候,我们的client会自动bind自己的ip和port}close(sockfd);return 0;
}
2.4 日志显示
- vs_start:使用距离可变参数最近的一个参数初始化ap;
- va_arg:对可变参数列表提参,提参类型为type;
- va_end:将ap指针置为空;
//将可变参数列表全部转化为某个字符串当中
int vsnprintf(char *str, size_t size, const char *format, va_list ap);说明:str:用于保存数据的字符串数组地址;size:最大写入的空间大小;format:以什么格式化写入;ap:可变参数列表部分;
#pragma once
#include <cstdio>
#include <ctime>
#include <cstdarg>
#include <cassert>
#include <cstring>
#include <cerrno>
#include <stdlib.h>#define DEBUG 0
#define NOTICE 1
#define WARINING 2
#define FATAL 3
#define SOCK_ERR 4
#define BIND_ERR 5
#define PARA_ERR 6const char *log_level[]={"DEBUG", "NOTICE", "WARINING", "FATAL"};// logMessage(DEBUG, "%d", 10);
void logMessage(int level, const char *format, ...)
{assert(level >= DEBUG);assert(level <= FATAL);char *name = getenv("USER"); //获取用户名char logInfo[1024];va_list ap; // ap -> char* //va_start(ap, format); //vsnprintf(logInfo, sizeof(logInfo)-1, format, ap); //写入logInfova_end(ap); // ap = NULLFILE *out = (level == FATAL) ? stderr:stdout;fprintf(out, "%s | %u | %s | %s\n", \log_level[level], \(unsigned int)time(nullptr),\name == nullptr ? "unknow":name,\logInfo);
}
2.5 测试
- 使用127.0.0.1可以进行本地通信。
- 使用云服务器的ip地址可以进行网络通信。
相关文章:
【网络】套接字 -- UDP
🥁作者: 华丞臧. 📕专栏:【网络】 各位读者老爷如果觉得博主写的不错,请诸位多多支持(点赞收藏关注)。如果有错误的地方,欢迎在评论区指出。 推荐一款刷题网站 👉 LeetCode刷题网站 文章…...
Lambda原理及应用
Lambda原理及应用 Lambda介绍 Lambda 是 JDK8 以后版本推出的一个新特性,也是一个重要的版本更新,利用 Lambda 可以简化内部类,可以更方便的进行集合的运算,让你的代码看起来更加简洁,也能提升代码的运行效率。 Lambda语法 非…...
运动耳机推荐、最值得入手的运动耳机清单共享
现在市面上各式各样的运动蓝牙耳机着实让人挑花了眼,怎样才能从纷繁复杂的市场中挑选出专业性、安全性、舒适性等各个方面都做地可圈可点的运动蓝牙耳机可真不是一件易事啊,甚至连不少老朋友都会踩坑,为了能让大家挑到真正的运动蓝牙耳机,为此…...
c盘爆满--如何清理电脑C盘
问题 c盘饱满很多天了,今天终于忍无可忍,开始展开对c盘的处理 c盘的基本处理有两步, 第一步,电脑系统清理 1,c盘右键属性,有个磁盘清理,好像是系统更新的一些缓存资源,可以直接清理 当然这只…...
Nginx配置web服务器及部署反向代理
Nginx配置web服务器及部署反向代理配置web服务器location语法部署反向代理代理转发配置web服务器 项目部署到linux上的静态文件代理给Nginx处理。当访问服务器IP时,可以自动返回静态文件主页。 主配置文件中server块对应的次配置include /etc/nginx/conf.d/*.conf…...
mvvm和mvc
mvvm是model-view-viewmodel的缩写,前端开发的架构模式 m: model:模型,指的是数据和交互业务逻辑 v: view:视图,用户看到的ui界面 vm: viewmodel:视图模型࿰…...
JavaScript while 循环
JavaScript while 循环的目的是为了反复执行语句或代码块。只要指定条件为 true,循环就可以一直执行代码块。while 循环while 循环会在指定条件为真时循环执行代码块。语法while (条件){需要执行的代码 }实例本例中的循环将继续运行,只要变量 i 小于 5&a…...
CMU15-445 Project.0总结
在线测试 本地测试 Project #0 - C Primer 以下是Project #0的网址,2022FALL的Project #0本质上是实现一棵字典树,关于字典树的相关内容可以参考C实现字典树。 在本题中,为了存储对应着字符串的任意类型值,题目设计了一个Tri…...
计算机网络题库---错题本
(一)老生常谈 第一章: 1.什么是计算机网络?其主要功能是什么? 解答: 利用通信设备和线路,将分布在地理位置不同的、功能独立的多个计算机系统连接起来,以功能完善的网络软件实现网…...
【react】react创建项目与引入AntD组件库:
文章目录一、初始化项目:【1】创建项目【2】暴露项目配置文件【3】安装依赖【4】配置less二、快捷键:【1】rcctab三、安装AntD组件库:【1】安装【2】index.js【3】问题:【4】效果:一、初始化项目: 【1】创…...
hook与mixin
看完vue3就开始看vue3的源码,表示很懵~ 刚把rollup打包搞完,这不响应式就接着来了!,还是写篇直接使用vue3的博客清清脑吧! 什么是hook、mixin? mixin: Vue2中多个组件内存在重复JS业务逻辑,使…...
【C语言】自定义类型
一、什么是自定义类型C语言提供了丰富的内置类型,常见的有int, char, float, double, 以及各种指针。除此之外,我们还能自己创建一些类型,这些类型称为自定义类型,如数组,结构体,枚举类型和联合体类型。二、…...
没有上司的舞会(C++,树形DP)
题目描述 某大学有 nnn 个职员,编号为 1…n1\ldots n1…n。 他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。 现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数 ri…...
【java基础】static和final关键字的作用及其用法详解
文章目录static关键字静态字段静态方法静态代码块静态内部类final关键字final字段final方法final类static关键字 这个关键字表示静态的,用于不同地方意思不一样 静态字段 如果我们将其作用到字段上,那么该字段为类所拥有,我们使用new关键字…...
#集成学习#:bagging、boosting、stacking和blending
集成学习是一种机器学习方法,旨在提高单个模型的性能和鲁棒性。它基于这样一个假设:通过结合多个模型的预测结果,可以获得更好的预测性能,因为每个模型都可能从数据中提取不同的信息,因此他们的错误也可能是不同的&…...
NCRE计算机等级考试Python真题(一)
第一套试题1、关于数据的存储结构,以下选项描述正确的是A.数据所占的存储空间量B.数据在计算机中的顺序存储方式C.数据的逻辑结构在计算机中的表示D.存储在外存中的数据正确答案: C2、关于线性链表的描述,以下选项中正确的是A.存储空间不一定…...
C#协变逆变
文章目录协变协变接口的实现逆变里氏替换原则协变 协变概念令人费解,多半是取名或者翻译的锅,其实是很容易理解的。 比如大街上有一只狗,我说大家快看,这有一只动物!这个非常自然,虽然动物并不严格等于狗…...
算法设计与分析期末考试复习(四)
贪心算法(Greedy Algorithm) 找零钱问题 假设有4种硬币,面值分别为:二角五分、一角、五分和一分,现在要找给顾客六角三分钱,如何找使得给出的硬币个数最少? 首先选出1个面值不超过六角三分的最…...
qsort函数排序数据 and 模拟实现qosrt函数(详解)
前言:内容包括使用库函数qsort排序任意类型的数据,模拟实现qsort函数(冒泡排序的逻辑) 我们先了解qsort函数的语法:qsort函数默认按照升序排序数据 void qsort (void* base, size_t num, size_t size,int (*compar)(…...
Mysql视图,存储过程,触发器,函数以及Mysql架构
一,视图视图是基于查询的一个虚拟表 , 也就是将sql语句封装起来, 要用的时候直接调用视图即可, select语句查询的表称为基表, 查询的结果集称为虚拟表, 基本表数据发生了改变, 那么视图也会发生改变, 使用视图就是为了简化查询语句.1.CREATE VIEW view_admin AS SELECT * FROM…...
什么是线程死锁?如何解决死锁问题
死锁,一组互相竞争的资源的线程之间相互等待,导致永久阻塞的现象。 如下图所示: 与死锁对应的,还有活锁,是指线程没有出现阻塞,但是无限循环。 有一个经典的银行转账例子如下: 我们有个账户类…...
C语言几种判断语句简述
C 判断 判断结构要求程序员指定一个或多个要评估或测试的条件,以及条件为真时要执行的语句(必需的)和条件为假时要执行的语句(可选的)。 C 语言把任何非零和非空的值假定为 true,把零或 null 假定为 fals…...
【python学习笔记】:SQL常用脚本(二)
11、四舍五入ROUND函数 ROUND ( numeric_expression , length [ ,function ] ) function 必须为 tinyint、smallint 或 int。 如果省略 function 或其值为 0(默认值),则将舍入 numeric_expression。 如果指定了0以外的值,则将截…...
【Linux】进程地址空间
文章目录🎪 进程地址空间🚀1.写时拷贝与虚拟地址🚀2.地址空间引入🚀3.地址空间的意义⭐3.1 虚拟地址寻址⭐3.2 虚拟地址意义🎪 进程地址空间 地址空间(address space)表示任何一个计算机实体所…...
Qt音视频开发17-vlc内核回调拿图片进行绘制
一、前言 在众多播放器中,支持的种类格式众多,并支持DVD影音光盘,VCD影音光盘及各类流式协议,提供了sdk进行开发,这点是至关重要的,尽管很多优秀的播放器很牛逼,由于没有提供sdk第三方开发&…...
安装配置DHCP
本次实验采用CentOS71.检查在安装DHCP之前先使用rpm命令查看系统中已有的DHCP软件包rpm -qa | grep dhcp由此可知,系统中尚未安装DHCP软件包2.安装我们可以使用yum命令为系统安装DHCP软件包yum -y install dhcp安装完成后再次检查可以看到DHCP软件包3.配置dhcp配置文…...
MarkDown中写UML图的方法
目录序UML图之顺序图顺序图的四个要素关于消息箭头的语法Mermaid中顺序图的简单例子样例用小人表示对象为对象设置别名激活对象UML图之类图类图中常见的关系关于不同类型关系的语法Mermaid中类图的简单例子样例类定义的两种方式为类定义成员双向关系的表示多重性关系的表示UML之…...
Axure8设计—动态仪表盘
本次分享的的案例是Axure8制作的动态仪表盘,根据设置的数值,仪表盘指针旋转到相应的值位置 预览地址:https://2qiuwg.axshare.com 下载地址:https://download.csdn.net/download/weixin_43516258/87502161 一、制作原型 1、首先创建空白页…...
【C++】类和对象的六个默认成员函数
类的6个默认成员函数构造函数概念特性析构函数概念特性拷贝构造函数概念特征拷贝构造函数典型调用场景:赋值运算符重载运算符重载赋值运算符重载取地址及const取地址操作符重载类的6个默认成员函数 到底什么是类的6个默认成员函数呢?相信大家一定对此怀…...
4、算法MATLAB---认识矩阵
认识矩阵1、矩阵定义和基本运算1.1 赋值运算符:1.2 等号运算符:1.3 空矩阵1.4 一行一列矩阵1.5 行矩阵(元素用空格或逗号分隔)1.6 列矩阵(分号表示换行)1.7 m行n列的矩阵:行值用逗号间隔&#x…...
amazon免费虚拟机做网站/今日热点新闻头条排行榜
简单记录: 公司项目中,新开一个模块,本地编写模拟接口,数据请求,使用模块axios进行ajax请求,直接请求,肯定显示跨域,无法请求。 接口是这样的 报错类似这样: 解决方案 …...
网站开发数据交互/怎么引流到微信呢
给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。 案例: s "leetcode" 返回 0.s "loveleetcode", 返回 2. 我的思路: 利用字典记录每个字母出现的次数O(N) Python代…...
wordpress sql or/网络营销推广方案策划书
技术实现开发语言:jsp.框架:jspservlet.模式:B/S.数据库:mysql.开发工具:myeclipse eclipse 均可.论文字数:1万左右.功能实现本系统主要开发目的是方便舆情管理人员进行舆情信息监控管理,增加工作效率,面向的客户群体是各级行政人事的工作人员。根据本系…...
一家专门做护肤的网站/浅谈一下网络营销的几个误区
三核CPU XP系统终极安装SQL 2005三核CPU XP系统终极安装SQL 2005此贴并非转贴--hacbu84制作在实机下SQL2000可以安装(在不安装SP4补丁下,包括改动msconfig 工具),如果安装虚拟机再改动虚拟U核心,SQP4补丁完全可以安装成功,所以在用三核CPU的情况下不要再考虑安装SQL2000,CPU的…...
做淘客网站去哪里购买空间/关于普通话的手抄报
**前言**十多年前笔者就打算写一本Oracle数据库性能优化方面的书,屡次都是在提笔写了几行字后就放弃了。近几年,随着Oracle数据库的普及和水平的不断提高,国内出现不少Oracle数据库方面的高水平作品,相当多的作品都涉及了性能优化…...
网络营销工作/sem优化软件选哪家
条款7 预先准备好内存不够的情况 operator new在无法完成内存分配请求时会抛出异常(老的编译器返回0); C常用的做法, 定义一个类型无关的宏来分配内存并检查是否成功; 123#define NEW(PTR, TYPE) \try { (PTR) new TYPE; } \catch (std::bad_alloc&) { assert(0); }>…...