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

青海省建设厅查询网站外贸汽车配件做那个网站

青海省建设厅查询网站,外贸汽车配件做那个网站,江西建网站,推广竞价托管费用目录 0.前言 1.前置知识 网络通信的大致流程 IP地址 端口号#xff08;port#xff09; 客户端如何得知服务器端的IP地址和端口号#xff1f; 服务器端如何得知客户端的IP地址和端口号#xff1f; 2.实现代码 代码模块的设计 服务器端代码 成员说明 成员实现 U…目录 0.前言 1.前置知识 网络通信的大致流程 IP地址 端口号port 客户端如何得知服务器端的IP地址和端口号 服务器端如何得知客户端的IP地址和端口号 2.实现代码 代码模块的设计 服务器端代码 成员说明 成员实现 UdpServer(uint16_t port) 的实现 ~UdpServer() 的实现 void InitServer() 的实现 void Start() 的实现 客户端代码 3.程序拓展 4.源代码附录 客户端代码 服务器端代码 服务端启动逻辑代码main.cc 0.前言 1.目标使用UDP协议实现客户端程序和服务器端程序之间的通信。 2.功能客户端给服务器发送什么消息服务器端就给客户端响应什么消息。 3.效果 客户端效果当用户根据提示Please Enter# 输入消息之后按下回车键发送给服务器端立马就收到了服务器端发送过来的相同的消息。 服务器端效果服务器端接收到客户端发送过来的消息之后会打印客户端的ip地址和端口号以及用户发送过来的数据。服务器端给客户端发送的消息并不会在服务器端显示。 1.前置知识 网络通信的大致流程 客户端想要将信息发送到服务器端主机客户端用户在客户端主机的应用层输入的数据必须要自顶向下贯穿TCP/IP网络协议栈并封装每一层的协议报头然后到达物理层的设备然后通过物理的介质将信息传输到服务器端主机的物理层的设备然后将信息自底向上贯穿TCP/IP协议栈进行解包和分用将客户端用户输入的信息传输到服务器端应用层的程序。 服务器端主机给客户端主机发送的信息也是如此。 如果你想要更加细致的研究这个过程可以参考这篇文章 文章链接https://blog.csdn.net/D5486789_/article/details/142029716?spm1001.2014.3001.5501 IP地址 什么是IP地址呢我们可以这样理解。假如A主机想要将信息发送到B主机但是在整个网络中的主机数量非常多所以A主机必须要知道那一台主机是B主机这个时候就可以给每一台主机一个编号用户在网络中标识唯一的一台主机这个编号就是IP地址。由于历史发展的原因IP地址有IPV4和IPV6两个版本但我们主要使用IPV4。 IPv4地址由32位二进制数组成通常用点分十进制的方式来表示即每组8位二进制数转换成一个十进制数并用点.分隔例如192.168.1.1。 端口号port 什么是端口号呢我们可以这样理解。当A主机已经有能力通过IP地址在网络中如此众多的主机中找到B主机并将信息发送到B主机在物理层的设备上此时消息需要自底向上贯穿TCP/IP协议栈交付到B主机的应用层但是B主机应用层启动的软件程序可能不止一个发送的消息到底要交付给哪一个软件程序呢所以A主机还需要有能力将发送给B主机的信息正确的交付给B主机中对应的软件程序。这个时候可以给每个启动的软件程序一个编号用于唯一的标识一个启动的软件程序这个编号就是端口号。 端口号是一个16位的数字范围从0到65535。其中一些端口号被预留给特定的服务或应用程序这些端口号被称为“知名端口号”或“系统端口号”。例如HTTP服务通常使用端口号80HTTPS服务通常使用端口号443FTP服务使用端口号21等。这些知名端口号在Internet上被广泛认可和使用使得客户端可以很容易地找到并连接到相应的服务。客户端程序的端口号在1024之后随便选。 如果你有操作系统的知识的话你就知道我上面所说的软件程序就是操作系统中的进程但是标识系统中唯一的一个进程不是有进程PID吗为什么还要端口号呢 我们可以这样理解 用户使用角度用户访问服务器端的服务程序的时候需要知道该服务的IP地址和端口号并且用户一旦认定了这个IP地址和端口号当用户再次想访问对应的服务的时候输入的还是这个IP地址和端口号所以这就要求服务端程序所在主机的IP地址和自己的端口号是不能改变的但是进程PID不同每次启动同一个程序时系统分配给进程的PID是会变化的所以在网络通信中不能使用进程PID来唯一标识唯一的一个进程。 从操作系统的角度进程PID是属于操作系统中进程管理的范畴网络通信是数据操作系统中网络管理的范畴不同的模块之间最好是低耦合的一层变化不会影响另一层。所以操作系统中网络管理模块需要有独属于自己的用于唯一的标识一个进程的设计这个设计就是端口号。 总结不同的两台主机之间通信必须要提前知道对方的IP地址和端口号这样才能在整个错综复杂的网络中有目的的找到对方并将信息准确的交付给对方启动的应用程序。 客户端如何得知服务器端的IP地址和端口号 客户端需要知道服务器端的IP地址和端口号那客户端是如何得知服务器端的IP地址和端口号的呢 我们可以设想一下开发人员开发出一个应用服务之后要如何让别人来访问自己开发出的应用服务呢是不是需要提前告诉用户呢只有提前告诉用户用户才知道访问对应的服务需要输入特定的IP地址和端口号。 但是IP地址和端口号太难记忆了不方便用户使用于是便有了域名。比如当我们想要买东西时我们就可以在浏览器输入 www.taobao.com浏览器就会将用户输入的域名解析成为指定的IP地址和端口号。 所以客户端要想得知服务器端的IP地址和端口号一定是商业公司提前做了宣传。 服务器端如何得知客户端的IP地址和端口号 那服务器端是如何得知客户端的IP地址和端口号的呢 我们可以这样理解当用户输入指定的IP地址和端口号之后用户输入的信息在自定向下贯穿TCP/IP协议栈的时候不是会进行封装吗这个过程就会将用户所使用的主机的IP地址和该主机上客户端程序的端口号也封装进用户发送的数据中形成一个数据包当服务器端拿到这个数据包时就能知道客户端的IP地址和端口号。 所以服务器端之所以能知道客户端的IP地址和端口号是客户端发送给服务器端的。 好了有了上面这些知识我们就可以编写代码了。但是还有一些网络通信的基础知识在 “实现代码” 部分讲解。 2.实现代码 注意在使用网络编程相关接口时我们需要包含这四个头文件 #include sys/types.h #include sys/socket.h #include arpa/inet.h #include netinet/in.h 代码模块的设计 客户端只需要实现UdpClient.cc服务器端需要实现UdpServer.hpp、Main.cc。 服务器端代码 服务器类代码总览 成员说明 成员变量说明 在整个服务器类中成员变量我们设计三个分别是_sockfd、_port。 _sockfd这是一个文件描述符服务器端程序在进行网络通信的过程中接收的数据从该文件描述符所关联的文件中拿发送的数据通过该文件描述符所关联的文件发送。 _port这是服务器端程序所使用的端口号是我们开发人员给手动的给服务器端程序绑定的。 成员函数说明 在真个服务器类中一共四个成员函数分别是 UdpServer(uint16_t port)、 ~UdpServer()、 void InitServer()、 void Start()。 UdpServer(uint16_t port)构造函数负责成员变量的初始化将_port 初始化为我们开发人员给服务器端程序指定的portport是在启动服务器端程序时我们自己指定的。 ~UdpServer()析构函数负责成员变量的释放但并没有成员变量管理资源所以不需要写啥。 void InitServer()该成员函数负责初始化服务器端程序也就是为网络通信做必要的准备。比如创建套接字绑定端口号。 void Start()该成员函数负责启动服务器当调用这个函数之后我们的服务器端程序就可以进行消息的收和发了。 成员实现 成员实现部分我们主要实现成员函数。 UdpServer(uint16_t port) 的实现 _sockfd我们先初始化为defaultfd这是我们定义的const 静态全局变量也就是-1。 _port 成员变量初始化为portport 是需要我们在启动服务器端程序时手动输入的。 _isrunnig 大家不用管不影响。 UdpServer(uint16_t port) : _sockfd(defaultfd), _port(port), _isrunning(false) {} ~UdpServer() 的实现 额这个嘛确实没啥要析构的使用默认的就可以。 ~UdpServer() {} void InitServer() 的实现 这个成员方法的实现我们分为两步第一步为创建udp socket套接字第二步为绑定本地信息和网络信息。 先看看代码后面有非常详细的解释。 void InitServer() {// 1. 创建udp socket 套接字_sockfd socket(AF_INET, SOCK_DGRAM, 0);if (_sockfd 0){LOG(FATAL, socket error, %s, %d\n, strerror(errno), errno);exit(SOCKET_ERROR);}LOG(INFO, socket create success, sockfd: %d\n, _sockfd);// 填充sockaddr_in结构struct sockaddr_in local; bzero(local, sizeof(local)); //将该字段全部清空为0.local.sin_family AF_INET;local.sin_port htons(_port);local.sin_addr.s_addr INADDR_ANY; // htonl(INADDR_ANY);// 2.bind sockfd和网络信息(IP Port)int n bind(_sockfd, (struct sockaddr *)local, sizeof(local));if (n 0){LOG(FATAL, bind error, %s, %d\n, strerror(errno), errno);exit(BIND_ERROR);}LOG(INFO, socket bind success\n); } 第一步解释 我们首先创建udp socket。大家可以这样理解服务器端的程序需要进行消息的收和发收消息一定是该主机的物理层的网络设备先收到也就是网卡网卡收到的消息要放在哪里呢在回答这个问题之前我们需要先明确一点 “Linux下一切皆文件”硬件也是一种文件。所以操作系统要为网卡分配一个收发消息的缓冲区用来存放收到的消息和发送的消息。再简单一点理解就是创建udp socket相当于把网卡打开了就可以通过网卡收发消息了。 第一步实现 实现第一步需要使用这个函数 函数功能通过制定的协议创建用于网络通信的文件。 第一个参数domain 表明我们要进行何种通信是本地通信还是网络通信我们实现的是网络通信所以将domain设置为 AF_INET即可。 第二个参数type 指定了套接字的类型是面向数据报的套接字类型还是面向字节流的套接字类型UDP是面向数据报的通信协议所以我们将其设置为SOCK_DGRAM即可。 第三个参数protocol 用于指定特定的协议但是前两个参数已经表明我们要使用UDP协议了所以设置为0即可。 返回类型 失败时返回-1并设置错误码。 成功时返回新创建的文件描述符。这个文件描述符后续会被用于其他套接字函数如bind()、listen()、accept()、connect()、send()、recv()等这也是我们设计一个_sockfd 成员变量的原因。 第二步解释 前面我们说过socket函数返回值是一个文件描述符与该文件描述符所关联的文件用于该主机在网络通信中收发数据可是光光有一个收发数据的文件还是远远不够的还需要将该文件和主机的网络信息比如IP地址端口号等关联起来这样客户端就能通过指定的IP地址和端口号找到提供服务的服务端程序并向该程序用于网络通信的文件中发送数据。服务器端向客户端发送消息也是如此。 第二步实现 实现这一步需要使用bind函数 函数功能将通信主机的本地信息(sockfd)和网络信息关联起来。 第一个参数sockfd 是我们需要关联的文件描述符。 第二个参数struct sockaddr 中包含本机的网络信息。 第三个参数这个参数指定了 addr 参数所指向的结构的长度。对于 sockaddr_in这个长度通常是 sizeof(struct sockaddr_in) 说明一下         addr的类型是 struct sockaddr但实际上addr的类型是 struct sockaddr_in。这是因为socket编程不仅可以用于网络通信使用struct sockaddr_in结构还可以用于本地通信使用struct sockaddr_un结构还有其他通信……通信方式这么多操作系统的开发者就要多开发几套通信接口给用户使用不仅仅开发的人头疼使用的人也头疼。于是操作系统的开发人员便想到一种方案提供统一的接口用户想要进行那种通信就传入特定的参数即可该函数内部自动做解析判断用户要进行何种通信。也就是说为了统一接口的使用设计了struct sockaddr 类型。         需要注意的是这个参数是一个结构体类型所以我们需要先填充结构体中的字段之后再将该结构体对象作为参数传递进去。struct sockaddr_in结构中的字段如下所示 struct sockaddr_in { sa_family_t sin_family; // 地址族对于 IPv4 来说这个值总是 AF_INET uint16_t sin_port; // 端口号网络字节顺序 struct in_addr sin_addr; // IPv4 地址网络字节顺序 }; // 其中struct in_addr 结构体定义如下 struct in_addr { uint32_t s_addr; // IPv4 地址网络字节顺序 }; sin_family我们设置为AF_INET表示要进行网络通信。 sin_port表示我们给该服务器端程序绑定的端口号。 sin_addr表示该服务器端程序所在主机的IP地址。 htons和htonl函数的介绍 函数功能将主机序列转换成网络序列。             由于历史发展的原因产生了大端机和小端机大端机和小端机之间可能也要进行通信数据需要经过网络那么数据在网络中是大端序列还是小端序列呢为了解决这个问题网络中的序列被规定为大端序列小端机发送的数据要经过网络就需要转化成网络序列也就是大端序列大端机发送的数据已经是大端的了就不需要进行转化了。         对于IP地址在主机中显示的时候显示出来的是 点分十进制的IP地址但是在网络中传输的时候为了节省空间往往被设计为四字节的IP地址。         所以我们发送的端口号 需要转换成网络序列需要使用htons函数表示将一个16位的整数转换成网络序列。 在认识一个函数         发送的IP地址 需要转换成四字节的IP同时也需要转换成网络序列可以使用inet_addr函数这一个函数会帮我们完成这两步事情。 这句代码是什么意思呢—— local.sin_addr.s_addr INADDR_ANY;   我们将 local.sin_addr.s_addr 设置为INADDR_ANY这是为什么呢因为如果我们指定了服务器端的IP地址客户端只能通过特定的IP地址来访问这个服务端程序也就是说 这个服务端程序只能通过绑定的IP地址来访问但是一台主机不止一个IP地址可能有公网IP内网IP不同的IP需要提供给不同的用户使用需要保证用户使用该主机的不同IP地址能访问到指定的服务端程序。所以我们将服务器端的IP地址绑定为0在代码实现方面库当中将INADDR_ANY定义为0并且0 的大端序列和小端序列是相同的。 void Start() 的实现 当我们完成服务器端程序网络通信的初始化工作之后我们的服务器端程序就可以通信了这段代码也体现了我们这个通信程序的功能 —— 接收客户端的消息给客户端返回同样的消息。 先看代码再解释 void Start() {// 一直运行直到管理者不想运行了 服务器都是死循环// UDP是面向数据报的协议while (true){char buffer[1024];struct sockaddr_in peer;socklen_t len sizeof(peer); // 必须初始化成为sizeof(peer)// 1. 我们要让server先收数据ssize_t n recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)peer, len);if (n 0){buffer[n] 0;LOG(DEBUG, get message: %s\n, buffer);// 2. 我们要将server收到的数据发回给对方sendto(_sockfd, buffer, strlen(buffer), 0, (struct sockaddr *)peer, len);}} } 先介绍基于UDP协议进行网络通信的两个函数 我们的程序是基于UDP协议进行通信的UDP协议是面向数据报的协议所以我们不能使用一般的文件读写接口从基于UDP网络通信的文件中读写数据而要使用UDP协议的网络通信读写接口 —— recvfrom和sendto。 recvfrom 函数功能从指定的网络通信文件中读取数据。 参数说明 1.sockfd 表明我们要从那个文件中读。 2.buf 是一个输出型参数表明我们读取的数据放到哪里。 3.len 表明我们要读取多长的数据。 4.flags 是一个标志位表示我们以什么方式读通常设为0。 5.src_addr 表明发送数据方的网络信息(比如发送方的IP地址和端口号信息。)也就是说要知道是谁给我发的消息。 6.addrlen 是指向一个整数的指针该整数在调用前应该包含 src_addr 指向的结构体的大小在调用后它将包含实际写入 src_addr 的字节数。 返回值该函数执行成功的返回值表示接收到的字节数。如果连接已正常终止则返回0。如果发生错误则返回-1并设置相应的errno来指示错误的类型。 sendto 函数功能通过指定的网络通信文件发送数据。 参数介绍 1.sockfd 表示我们要通过哪个通信文件发送数据。 2.buf 表示我们要发送的数据在内存中存储的位置。 3.len 表明我们要发送多长的数据。 4.flags 表明我们要以什么方式发送数据。 5.dest_addr 表明接收数据方的网络信息也就是说要把数据发送给谁。 6.addrlen 表明dest_addr所指向的对象的大小。 返回值如果发送成功则返回发送的字节数可能小于请求发送的字节数如果发送缓冲区空间不足或网络限制。如果发生错误则返回-1并设置errno来指示错误的类型。 代码解释 作为服务器端程序肯定是需要一直运行的这样才能确保客户随时随地都能访问所以是在一个死循环中直到管理者不想让这个程序执行了。 服务器端程序肯定是要先接收消息的所以我们使用recvfrom这个函数将接收到的信息存放在buffer这个缓冲区中同时通过输出型参数 struct sockaddr_in peer 获取发送方的IP地址和端口号如果接收消息成功立马通过sendto函数将存放在buffer中的数据发送给对方因为我们通过输出型参数获取到了发送方的网络信息所以我们同样可以使用这个网络信息将数据发回给对方。 至此服务器端的代码就编写完毕了。 客户端代码 当我们在启动客户端程序的时候要使用这样的命令 ./udpclient 127.0.0.1 8888这样的命令其中127.0.0.1是服务器端的IP地址8888是服务器端程序的端口号。Usage函数帮我们检查启动客户端程序的格式是否正确。 补充127.0.0.1是本地环回IP主要用于测试。 第一步创建UDP socket。 客户端程序的第一步还是创建基于UDP协议通信的套接字也就是创建自己用于该服务中进行网络通信的文件。创建的方式和服务器端一模一样。 第二步绑定客户端的本地信息和网络信息。特别注意 客户端需不需要绑定客户端的本地信息和网络信息呢答案是要但是不能够由我们开发人员在代码中手动的绑定比如你写的客户端程序绑定端口号为8888我写的客户端程序也绑定端口号为8888但是用户主机上的一个端口号只能唯一标识一个进程。所以客户端程序的端口号不能手动绑定 只能由用户主机上的操作系统自动分配。所以这一步我们什么也不需要做 接下来的工作就和在服务器端程序中的差不多了客户端程序也是在死循环中跑的只能让用户手动的退出。客户端程序通过sendto接口向客户端发送数据通过recvfrom接口接收客户端发过来的数据。 void Usage(std::string proc) {std::cout Usage:\n\t proc serverip serverport\n std::endl; }// ./udpclient serverip serverport int main(int argc, char *argv[]) {if (argc ! 3){Usage(argv[0]);exit(1);}std::string serverip argv[1];uint16_t serverport std::stoi(argv[2]);// 1. 创建socketint sockfd socket(AF_INET, SOCK_DGRAM, 0);if(sockfd 0){std::cerr socket error std::endl;}// 构建目标主机的socket信息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());std::string message;// 2. 直接通信即可while(true){std::cout Please Enter# ;std::getline(std::cin, message);sendto(sockfd, message.c_str(), message.size(), 0, (struct sockaddr*)server, sizeof(server));struct sockaddr_in peer;socklen_t len sizeof(peer);char buffer[1024];ssize_t n recvfrom(sockfd, buffer, sizeof(buffer)-1, 0, (struct sockaddr*)peer, len);if(n 0){buffer[n] 0;std::cout server echo# buffer std::endl;}}return 0; } 至此就可以完成客户端和服务器端的通信了。 3.程序拓展 我们写的服务器端代码中接收到用户的信息之后直接就返回相同的信息那我们能不能改变服务器端的返回逻辑呢针对客户端的不同信息给客户响应不同的结果这一点可以通过回调函数实现读者可以自行拓展。 4.源代码附录 客户端代码 #include iostream #include string #include cstring #include cstdlib #include sys/types.h #include sys/socket.h #include netinet/in.h #include arpa/inet.hvoid Usage(std::string proc) {std::cout Usage:\n\t proc serverip serverport\n std::endl; }int main(int argc, char *argv[]) {if (argc ! 3) {Usage(argv[0]);exit(1);}std::string serverip argv[1];uint16_t serverport std::stoi(argv[2]);// 1. 创建socketint sockfd socket(AF_INET, SOCK_DGRAM, 0);if(sockfd 0){std::cerr socket error std::endl;}// 构建目标主机的socket信息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());std::string message;// 2. 直接通信即可while(true){std::cout Please Enter# ;std::getline(std::cin, message);sendto(sockfd, message.c_str(), message.size(), 0, (struct sockaddr*)server, sizeof(server));struct sockaddr_in peer;socklen_t len sizeof(peer);char buffer[1024];ssize_t n recvfrom(sockfd, buffer, sizeof(buffer)-1, 0, (struct sockaddr*)peer, len);if(n 0){buffer[n] 0;std::cout server echo# buffer std::endl;}}return 0; } 服务器端代码 #pragma once#include iostream #include string #include cerrno #include cstring #include cstdlib #include strings.h #include sys/types.h #include sys/socket.h #include arpa/inet.h #include netinet/in.henum {SOCKET_ERROR 1,BIND_ERROR,USAGE_ERROR };const static int defaultfd -1;class UdpServer { public:UdpServer(uint16_t port) : _sockfd(defaultfd), _port(port), _isrunning(false){}void InitServer(){// 1. 创建udp socket 套接字 --- 必须要做的_sockfd socket(AF_INET, SOCK_DGRAM, 0);if (_sockfd 0){LOG(FATAL, socket error, %s, %d\n, strerror(errno), errno);exit(SOCKET_ERROR);}LOG(INFO, socket create success, sockfd: %d\n, _sockfd);// 2.0 填充sockaddr_in结构struct sockaddr_in local; // struct sockaddr_in 系统提供的数据类型。local是变量用户栈上开辟空间。int a 100; a 20;bzero(local, sizeof(local));local.sin_family AF_INET;local.sin_port htons(_port); // port要经过网络传输给对面先到网络_port主机序列- 主机序列转成网络序列// a. 字符串风格的点分十进制的IP地址转成 4 字节IP// b. 主机序列转成网络序列// in_addr_t inet_addr(const char *cp) - 同时完成 a b// local.sin_addr.s_addr inet_addr(_ip.c_str()); // 192.168.3.1 - 字符串风格的点分十进制的IP地址 - 4字节IPlocal.sin_addr.s_addr INADDR_ANY; // htonl(INADDR_ANY);// 2.1 bind sockfd和网络信息(IP(?) Port)int n bind(_sockfd, (struct sockaddr *)local, sizeof(local));if (n 0){LOG(FATAL, bind error, %s, %d\n, strerror(errno), errno);exit(BIND_ERROR);}LOG(INFO, socket bind success\n);}void Start(){while (true){char buffer[1024];struct sockaddr_in peer;socklen_t len sizeof(peer); // 必须初始化成为sizeof(peer)// 1. 我们要让server先收数据ssize_t n recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)peer, len);if (n 0){buffer[n] 0;LOG(DEBUG, get message: %s\n, buffer);// 2. 我们要将server收到的数据发回给对方sendto(_sockfd, buffer, strlen(buffer), 0, (struct sockaddr *)peer, len);}}_isrunning false;}~UdpServer(){}private:int _sockfd;uint16_t _port; // 服务器所用的端口号 }; 服务端启动逻辑代码main.cc #include iostream #include memory #include UdpServer.hppvoid Usage(std::string proc) {std::cout Usage:\n\t proc local_port\n std::endl; }// ./udpserver portint main(int argc, char *argv[]) {if(argc ! 2){Usage(argv[0]);exit(USAGE_ERROR);}uint16_t port std::stoi(argv[1]);std::unique_ptrUdpServer usvr std::make_uniqueUdpServer(port); usvr-InitServer();usvr-Start();return 0; }
http://www.w-s-a.com/news/638525/

相关文章:

  • 西安网站开发公司价格保定徐水网站建设
  • 学做川菜下什么网站软件著作权和专利的区别
  • 百度网站标题东莞外包公司有哪些
  • 织梦增加网站英文名称网页界面设计特点
  • 企业如何进行网站建设棋牌代理平台
  • 韩国做美食网站有哪些seo优化在线诊断
  • 网站建设规划模板做擦边网站
  • 做网站台式还是笔记本网上下载的免费网站模板怎么用
  • 高校网站群管理系统凡科建站是永久的吗
  • 深圳网站建设服务电话网站通栏设计素材
  • 网站里面的视频功能怎么做网站名注册
  • 网站游戏下载厦门php网站建设
  • 沈阳关键词网站排名一台服务器做两个网站吗
  • 哪个行业该做网站但是没有做dom手表官方网站
  • 网站建设费 大创wordpress中函数get
  • 怎样建设个自己的网站首页有没有专门教做扯面的网站
  • 网站后台怎么添加模板教育类网站开发公司
  • 网站的外链是什么php创建一个网站
  • 语文建设 官方网站网络工程可以从事什么工作
  • 无锡便宜做网站如何下载网站模板
  • 南宁高端网站网络小说网站推广策划方案
  • 苏州网站制作方法建设银行 网站
  • 技术网站推广范例素材网站哪个好
  • 网站找人做的他能登管理员吗网站建设一般多少钱
  • 衡水哪有做网站的wordpress主题站主题
  • 网络建设的流程网站公司注册资本
  • 杭州旅游团购网站建设建立一个网站需要哪些步骤
  • 实木餐桌椅网站建设浦东网站建设哪家好
  • 高端手机网站定制网站网络推广推广
  • 做网站的颜色大学网站群建设方案