当前位置: 首页 > news >正文

网页设计与网站建设大作业app拉新平台

网页设计与网站建设大作业,app拉新平台,wordpress 全站备份,如何看客户网站开发客户需要云服务器等云产品来学习Linux的同学可以移步/–腾讯云–/官网#xff0c;轻量型云服务器低至112元/年#xff0c;优惠多多。#xff08;联系我有折扣哦#xff09; 文章目录 1. 前置知识1.1 源IP和目的IP1.2 端口号1.3 TCP协议和UDP协议初识1.4 网络字节序1.5 … 需要云服务器等云产品来学习Linux的同学可以移步/–腾讯云–/官网轻量型云服务器低至112元/年优惠多多。联系我有折扣哦 文章目录 1. 前置知识1.1 源IP和目的IP1.2 端口号1.3 TCP协议和UDP协议初识1.4 网络字节序1.5 socket编程接口1.5.1 socket常见API1.5.2 sockaddr结构 2. 简单的UDP服务端和客户端代码实现2.1 makefile文件的编写2.2 server端的编写2.2.1 需要调用的函数2.2.2 代码2.2.3 测试 2.3 client端的编写2.3.1 需要调用的函数2.3.2 代码2.3.3 测试 1. 前置知识 1.1 源IP和目的IP 每台主机都有自己的IP地址当数据在进行通信的时候除了要发送的数据外在报头里面还要包含发送方的IP和接收方的IP这里发送方的IP就被称为源IP接收方的IP就是目的IP 现在有了源IP和目的IP之后是不是就能够通信了呢 源IP和目的IP的出现只能标识两台主机的唯一性但是在主机上还存在很多个进程在发送数据的时候肯定是由一个进程发送给另一个进程的所以还需要标识两台主机上进程的唯一性 为了更好的表示一台主机上服务进程的唯一性用端口号port标识服务进程、客户端进程的唯一性。 1.2 端口号 端口号port是传输层协议的内容 端口号是一个2字节16位的整数端口号用来标识一个进程, 告诉操作系统, 当前的这个数据要交给哪一个进程来处理IP地址 端口号能够标识网络上的某一台主机的某一个进程一个端口号只能被一个进程占用一个进程可以占用多个端口号 由上面可知IP地址主机的全网唯一性该主机上的端口号主机上进程唯一性可以标识一个唯一的进程。那么最终网络通信的本质就是进程间通信 进程已经有pid标识唯一性了为什么还要有端口号呢 系统是系统网络是网络单独设置为了让网络和系统解耦客户端需要每次都能够找到服务端进程这就要求了服务端的唯一性不能发生任何改变pid在每次进程创建的时候都有可能改变不是所有进程都需要进行网络通信的需要端口号但是所有进程都需要pid。 1.3 TCP协议和UDP协议初识 1. TCP协议 此处我们先对TCP(Transmission Control Protocol 传输控制协议)有一个直观的认识; 后面我们再详细讨论TCP的一些细节问题. 传输层协议有连接可靠传输面向字节流 2. UDP协议 UDP(User Datagram Protocol 用户数据报协议 传输层协议无连接不可靠传输面向数据报 1.4 网络字节序 在之前的文章中数据在内存中的存储我们提到了数据内存中存储的时候有大端小端之分磁盘文件中的多字节数据相对于文件中的偏 移地址也有大端小端之分。 大端机器和和小端机器也有可能通信那么这个时候如何定义网络通信的数据流呢 发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出;接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存;因此,网络数据流的地址应这样规定:先发出的数据是低地址,后发出的数据是高地址.TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节.不管这台主机是大端机还是小端机, 都会按照这个TCP/IP规定的网络字节序来发送/接收数据;如果当前发送主机是小端, 就需要先将数据转成大端; 否则就忽略, 直接发送即可 为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换 #include arpa/inet.h uint32_t htonl(uint32_t hostlong); uint16_t htons(uint16_t hostshort); uint32_t ntohl(uint32_t netlong); uint16_t ntohs(uint16_t netshort);实际上这些函数名是很好记的按照作用来组合即可其中h表示host是当前主机的意思n表示network是网络的意思l表示32位长整数s表示16位短整数 例如htonl表示将32位的长整数从主机字节序转换为网络字节序,例如将IP地址转换后准备发送。如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回;如果主机是大端字节序,这些 函数不做转换,将参数原封不动地返回 1.5 socket编程接口 1.5.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); // 开始监听socket (TCP, 服务器) int listen(int socket, int backlog); // 接收请求 (TCP, 服务器) int accept(int socket, struct sockaddr* address,socklen_t* address_len); // 建立连接 (TCP, 客户端) int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);1.5.2 sockaddr结构 套接字不仅支持跨网络通信还支持本地的进程间通信域间套接字。对于不同的通信方式需要使用的接口在细节上是有一些不同的。所以套接字提供了两个结构体sockaddr_in和sockaddr_un结构体其中前者是用于跨网络通信的后者用于本地进程间通信。但是除此之外通信的方法基本都是相同的所以为了让两种通信方式能使用同一套函数接口所以就定义了sockaddr结构体该结构体与sockaddr_in和sockaddr_un的结构都不相同但这三个结构体头部的16个比特位都是一样的这个字段叫做协议家族。 三个结构体的内容如下 所以当我们在传参的时候就直接传sockaddr结构体在函数内部做识别执行对应的操作。 注意 实际我们在进行网络通信时定义的还是sockaddr_in这样的结构体只不过在传参时需要将该结构体的地址类型进行强转为sockaddr*罢了。 既然传递的类型是指针类型那么为什么不用C语言的void *类型而进行了这么复杂的设计 在网络通信的结构进行设计的时候C语言的标准还没有出来。所以进行了设计在之后为了向前兼容就沿用了这套接口 2. 简单的UDP服务端和客户端代码实现 这里我们采用C和C混编的方式就封装成类来实现通过makefile进行自动化编译。 2.1 makefile文件的编写 # 这是构建本项目的makefile文件ccg # 这里cc是一个变量表示构建项目使用的编译器.PHONY:all # 构建一个伪对象表示我们要同时构建两个目标文件 all: udpServer udpClient# 这里是两个目标文件的依赖和构建方法 udpServer:udpServer.cc $(cc) -o $ $^ -stdc11 udpClient:udpClient.cc $(cc) -o $ $^ -stdc11# 删除所有产生的目标文件 .PHONY:clean clean: rm -f udpServer udpClient 2.2 server端的编写 2.2.1 需要调用的函数 1. socket 头文件:#include sys/types.h#include sys/socket.h 函数原型:int socket(int domain, int type, int protocol); 参数解释:domain:表示通信类型本质是一个宏socket支持多种通信方式一般来说有本地和网络两种。AF_INET表示使用IPv4进行网络通信AF_UNIX表示本地通信。详情见man手册type:表示套接字提供服务的类型如SOCK_STREAM:流式服务TCP策略SOCK_DGRAM:数据报服务UDP策略protocol:表示对应的协议实际上可以由前两个参数确定所以这里设计成0没有问题 函数描述:创建一个用于网络通信的文件描述符 返回值:调用成功返回文件描述符否则返回-1同时设置错误码2. bind 头文件:#include sys/types.h#include sys/socket.h 函数原型:int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 参数解释:sockfd:需要设置的sockfdaddr:将需要设置的内容对应的结构体指针强转为struct sockaddr *再传入为了统一接口addrlen:传入的addr对应的变量大小 函数描述:将local设置到内核中。 返回值:调用成功返回0否则返回-1同时设置错误码为什么要使用bind不能直接通信吗 通信是要使用网络的最终也是要通过OS进行通信。所以相关信息需要让OS来维护我们没有办法直接操作OS内核数据结构因此需要通过系统调用bind来将相关内容设置进内核 sockaddr相关结构的定义 sockaddr的定义 typedef unsigned short int sa_family_t;#define __SOCKADDR_COMMON(sa_prefix) \sa_family_t sa_prefix##familystruct sockaddr{__SOCKADDR_COMMON (sa_);char sa_data[14];};所以可以看出来sockaddr是一个结构体内部有两个成员变量其中第一个变量是16位的地址类型一个14位的地址数据。__SOCKADDR_COMMON是一个宏作用是将括号内的内容拼接到family前面最终形成一个sa_family_t类型的变量 sockaddr_in的定义 struct sockaddr_in{__SOCKADDR_COMMON (sin_); // 定义sin_family变量16位的数据类型in_port_t sin_port; // 16端口号struct in_addr sin_addr; // 32位IP地址/* 数据填充无意义 */unsigned char sin_zero[sizeof (struct sockaddr) -__SOCKADDR_COMMON_SIZE -sizeof (in_port_t) -sizeof (struct in_addr)];};3. bzero 头文件:#include strings.h 函数原型:void bzero(void *s, size_t n); 参数解释:s:需要设置的变量的地址n:变量的长度 函数描述:从s开始的n个字节设置为0类似于memset4. inet_aton 头文件:#include sys/socket.h#include netinet/in.h#include arpa/inet.h 函数原型与描述:int inet_aton(const char *cp, struct in_addr *inp); // 将点分十进制的IP地址转换为符合网络字节序的二进制形式存放到in_addr结构体中 参数解释:cp:点分十进制形式的C式ip字符串inp:存放网络字节序的二进制i形式IP 返回值:如果地址有效则返回非0如果地址无效则返回05. recvfrom 头文件:#include sys/types.h#include sys/socket.h 函数原型:ssize_t recvfrom(int sockfd, void *buf, size_t len, int falgs, struct sockaddr *src_addr, socklen_t *addrlen); 函数描述:接收信息 参数解释:sockfd:用于接收的sockfdbuf:len:flags:读取的方式默认为0阻塞读取src_addr:收到消息除了本身还得知道是谁发的输入输出型参数返回对应的消息内容是从哪一个client发来的addrlen:结构体大小 返回值:返回接收到的字节数出错返回-1同时设置错误码。如果发送方正常关闭返回02.2.2 代码 /*udpServer.hpp*/ #pragma once #include iostream #include string #include functional #include string.h #include cerrno #include cstdlib #include sys/types.h #include sys/socket.h #include arpa/inet.hnamespace Server {using func_t std::functionvoid(std::string, uint16_t, std::string);static void Usage(){std::cout \nUsage:\n\t./udpServer local_port\n\n;}enum // 枚举出错类型{USAGE_ERR 1,SOCKET_ERR,BIND_ERR};const static std::string defaultIP 0.0.0.0;const int gnum 1024; // 处理任务的缓冲区大小class udpServer{public:udpServer(const func_t cb, const uint16_t port, const std::string ip defaultIP): _port(port), _ip(ip) {}// 这里初始化要做的事情有两件 1. 创建sockfd 2.bind端口号和ipvoid initServer(){_sockfd socket(AF_INET, SOCK_DGRAM, 0); // 参数1:这里使用AF_INET表示使用IPv4进行网络通信参数2:我们这里使用UDP策略参数3:这里使用0表示默认if (_sockfd -1) // 差错处理{std::cerr socket error errno strerror(errno) std::endl;exit(SOCKET_ERR);}std::cout socket sucess : _sockfd std::endl;// 在当前函数的栈帧上创建一个local对象设置相关属性然后将相关属性bind到系统内核中struct sockaddr_in local; // 这里struct sockaddr_in类型需要头文件arpa/inet.hbzero(local, sizeof(local)); // 在填充数据之前首先将对象内部元素清空这里使用bzerolocal.sin_family AF_INET; // 设定协议家族local.sin_port htons(_port); // 设置端口号这里端口号需要首先转换成网络端口号local.sin_addr.s_addr inet_addr(_ip.c_str()); // 设置ip这里的ip是string类型但是实际在传输的时候使用的是整型所以需要转换这里使用inet_addr// inet_addr的作用有两个: 1.string - uint32_t; 2. htonl()int n bind(_sockfd, (struct sockaddr *)local, sizeof(local)); // 将local设置到内核中即bindif (n -1){std::cerr bind error errno strerror(errno) std::endl;exit(BIND_ERR);}// 至此初始化的操作完成}void start() // 让服务器开始跑起来{// 服务器的本质是一个死循环在循环内部处理收到的任务char buffer[gnum];while (true){// 1. 读取数据struct sockaddr_in peer; // 定义一个变量用于接收数据socklen_t len sizeof(peer);ssize_t n recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)peer, len);// a. 数据是什么 b. 谁发的if (n 0){buffer[n] 0;std::string clientIp inet_ntoa(peer.sin_addr); // 转换网络字节序 点分十进制uint16_t clientPort ntohs(peer.sin_port);std::string message buffer;std::cout clientIp [ clientPort ]# message std::endl;// 2. 处理任务_callback(clientIp, clientPort, message);}}}private:// 成员变量分析作为一个服务端进程我们首先需要一个端口号port和一个本地ip// 还需要有一个文件描述符sockfd用于进行通信(网络通信是基于文件的所以使用的都是文件的一套内容包括fd)int _sockfd; // socket文件描述符std::string _ip; // 本地ipuint16_t _port; // 服务进程端口号func_t _callback;}; }2.2.3 测试 查看网络情况就可以用指令netstat -a显示所有连线中的Socket-e显示网络其他相关信息-i显示网络界面信息表单-l显示监控中的服务器的Socket-n直接使用ip地址(数字)而不通过域名服务器-p显示正在使用Socket的程序识别码和程序名称-t显示TCP传输协议的连线状况-u显示UDP传输协议的连线状况 那么本地测试没有问题这里使用的是云服务器能不能bind公网IP呢 ./udpServer 8080 公网IP云服务器是虚拟化的服务器不能直接bind你的公网IP可以绑定内网IPifconfig显示的如果是虚拟机或者独立真实的Linux环境你可以bind你的IP 如何保证云服务器能够被别人访问 实际上一款网络服务器不建议指明一个IP也就是不要显示地绑定IP。服务器IP可能不止一个如果只绑定一个明确的IP最终的数据可能用别的IP来访问端口号访问不出来所以真实的服务器IP一般采用INADDR_ANY(全0任意地址)代表任意地址bind 最终代码 /*udpServer.hpp*/ #pragma once #include iostream #include string #include functional #include string.h #include cerrno #include cstdlib #include sys/types.h #include sys/socket.h #include arpa/inet.hnamespace Server {using func_t std::functionvoid(std::string, uint16_t, std::string);static void Usage(){std::cout \nUsage:\n\t./udpServer local_port\n\n;}enum // 枚举出错类型{USAGE_ERR 1,SOCKET_ERR,BIND_ERR};const static std::string defaultIP 0.0.0.0;const int gnum 1024; // 处理任务的缓冲区大小class udpServer{public:udpServer(const func_t cb, const uint16_t port, const std::string ip defaultIP): _port(port), _ip(ip) {}// 这里初始化要做的事情有两件 1. 创建sockfd 2.bind端口号和ipvoid initServer(){_sockfd socket(AF_INET, SOCK_DGRAM, 0); // 参数1:这里使用AF_INET表示使用IPv4进行网络通信参数2:我们这里使用UDP策略参数3:这里使用0表示默认if (_sockfd -1) // 差错处理{std::cerr socket error errno strerror(errno) std::endl;exit(SOCKET_ERR);}std::cout socket sucess : _sockfd std::endl;// 在当前函数的栈帧上创建一个local对象设置相关属性然后将相关属性bind到系统内核中struct sockaddr_in local; // 这里struct sockaddr_in类型需要头文件arpa/inet.hbzero(local, sizeof(local)); // 在填充数据之前首先将对象内部元素清空这里使用bzerolocal.sin_family AF_INET; // 设定协议家族local.sin_port htons(_port); // 设置端口号这里端口号需要首先转换成网络端口号// local.sin_addr.s_addr inet_addr(_ip.c_str()); // 设置ip这里的ip是string类型但是实际在传输的时候使用的是整型所以需要转换这里使用inet_addrlocal.sin_addr.s_addr INADDR_ANY;// inet_addr的作用有两个: 1.string - uint32_t; 2. htonl()int n bind(_sockfd, (struct sockaddr *)local, sizeof(local)); // 将local设置到内核中即bindif (n -1){std::cerr bind error errno strerror(errno) std::endl;exit(BIND_ERR);}// 至此初始化的操作完成}void start() // 让服务器开始跑起来{// 服务器的本质是一个死循环在循环内部处理收到的任务char buffer[gnum];while (true){// 1. 读取数据struct sockaddr_in peer; // 定义一个变量用于接收数据socklen_t len sizeof(peer);ssize_t n recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)peer, len);// a. 数据是什么 b. 谁发的if (n 0){buffer[n] 0;std::string clientIp inet_ntoa(peer.sin_addr); // 转换网络字节序 点分十进制uint16_t clientPort ntohs(peer.sin_port);std::string message buffer;std::cout clientIp [ clientPort ]# message std::endl;// 2. 处理任务_callback(clientIp, clientPort, message);}}}private:// 成员变量分析作为一个服务端进程我们首先需要一个端口号port和一个本地ip// 还需要有一个文件描述符sockfd用于进行通信(网络通信是基于文件的所以使用的都是文件的一套内容包括fd)int _sockfd; // socket文件描述符std::string _ip; // 本地ipuint16_t _port; // 服务进程端口号func_t _callback;}; }/*udpServer.cc*/ #include udpServer.hpp #include memoryusing namespace Server;void handleMessage(std::string clientIp, uint16_t clientPort, std::string message) {std::cout 我是一个回调函数执行收到的消息是 message std::endl; }// 调用的指令 ./udpServer port int main(int argc, char *argv[]) {// 解析指令if (argc ! 2){Usage();exit(USAGE_ERR);}uint16_t port atoi(argv[1]);// 创建对象进行通信std::unique_ptrudpServer usvr(new udpServer(handleMessage, port));usvr-initServer(); // 初始化服务进程usvr-start(); // 开始监听return 0; }2.3 client端的编写 2.3.1 需要调用的函数 头文件:#include sys/types.h#include sys/socket.h 函数原型:ssize_t sendto(int sockfd, void *buf, size_t len, int falgs, struct sockaddr *dest_addr, socklen_t *addrlen); 函数描述:向指定IP和端口号的进程发送信息 参数解释:sockfd:用于发送的sockfdbuf:要发送的数据的地址len:要发送的数据长度flags:发送的方式默认为0阻塞发送dest_addr:接收方的IP和端口号addrlen:结构体大小 返回值:调用成功返回接发送的字节数出错返回-1同时设置错误码2.3.2 代码 /*udpCliet.hpp*/ #pragma once #include iostream #include string #include string.h #include cerrno #include cstdlib #include sys/types.h #include sys/socket.h #include arpa/inet.hnamespace Client {enum // 枚举出错类型{USAGE_ERR 1,SOCKET_ERR,BIND_ERR,};class udpClient{public:udpClient(const std::string serverIp, const uint16_t serverPort): _serverIp(serverIp), _serverPort(serverPort), _sockfd(-1), _quit(false) {}void initClient(){// 1.创建套接字_sockfd socket(AF_INET, SOCK_DGRAM, 0);if (_sockfd -1){std::cerr socket error: errno : strerror(errno) std::endl;exit(SOCKET_ERR);}std::cout socket success: _sockfd std::endl;// 2. bind// a. Client要不要bind -- 当然要// b. Client要不要程序员显示bind -- 不用由OS自动形成端口进行bind。因为Client是在客户机上运行的客户机上同时会有很多其他的Client在跑不能确定哪些端口已经被使用// c. OS在什么时候如何bind -- 在Client发起网络连接时自动执行bind操作}void run(){struct sockaddr_in server;memset(server, 0, sizeof server);server.sin_family AF_INET;server.sin_addr.s_addr inet_addr(_serverIp.c_str());server.sin_port htons(_serverPort);std::string message;while(!_quit){std::cout Please Enter# ;std::cin message;sendto(_sockfd, message.c_str(), message.size(), 0, (struct sockaddr *)server, sizeof(server));}}private:int _sockfd; // 套接字std::string _serverIp; // 服务端IPuint16_t _serverPort; // 服务端端口号bool _quit; // 客户端退出标志}; } // namespace Client/*udpCliet.cc*/ #include udpClient.hpp #include string #include memoryusing namespace Client; static void Usage(std::string proc) {std::cout \nUsage:\n\t proc server_ip server_port\n\n; }// ./udpClient server_ip server_port int main(int argc, char *argv[]) {// 解析指令if (argc ! 3){Usage(argv[0]);exit(USAGE_ERR);}std::string serverIp argv[1];uint16_t serverPort atoi(argv[2]);std::unique_ptrudpClient ucli(new udpClient(serverIp, serverPort));ucli-initClient();ucli-run();return 0; }2.3.3 测试 ./udpClient 127.0.0.1 18989 # 客户端启动 ./udpServer 18989 # 服务端启动本节完…
http://www.zqtcl.cn/news/534783/

相关文章:

  • 网站哪个服务器好软装设计培训机构
  • 夜间正能量网站入口免费下载2022最新泛站群程序
  • 网站建设个人简历wordpress手写字体
  • 专门做商标的网站有哪些wordpress新文章加new
  • 全国商务网站大全木樨园网站建设公司
  • 网站搜索排名和什么有关系嘉兴建设局网站
  • 创建免费网站注意事项电商网站建设价格低
  • 网站开发接私单企业软文范例
  • 浙江省建设培训中心网站首页wordpress如何修改上传文件大小
  • 网站建设需要什么语言学完html怎么做网站
  • 国内外网站建设wordpress评论嵌套样式修改
  • 广州网站制作系统市场监督管理局投诉电话
  • 局域网建网站的详细步骤海南省建设网站的公司
  • 长沙市网站建设推广绵阳网站推广排名
  • 美容手机网站模板招标
  • 怎样用虚拟主机建网站访客可以用微信回复wordpress
  • 什么做网站做个网站一般要多少钱啊做网站界面尺寸
  • 装修网站怎样做网站中如何做图片轮播
  • 未备案网站如何加cdn河北网站制作
  • 出版社网站建设方案微信公众号h5网站开发
  • 南京建行网站云主机开网站教程
  • 炫酷表白网站在线制作微网站栏目图标
  • 西安做兼职网站设计昆山做网站的公司有哪些
  • vue手机网站开发买域名价格
  • 济南网站推广优化外包合肥住房和城乡建设部网站
  • 商品定制平台网站江苏港口建设费申报网站
  • 仿站酷网站模板网站建设捌金手指花总六
  • 南通网站建设计划书抖音关键词seo系统
  • 怎么做服务器网站下载链接生产类营销型网站
  • 做网站网站内容怎么找微信公众号免费做影视网站