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

网站建设 制作网站建设方案书格式

网站建设 制作,网站建设方案书格式,尚海整装为啥口碑那么差,wordpress 外贸网站计算机网络 —— 网络编程#xff08;TCP#xff09; TCP和UDP的区别TCP (Transmission Control Protocol)UDP (User Datagram Protocol) 前期准备listen #xff08;服务端#xff09;函数原型返回值使用示例注意事项 accpect #xff08;服务端#xff09;函数原型返回… 计算机网络 —— 网络编程TCP TCP和UDP的区别TCP (Transmission Control Protocol)UDP (User Datagram Protocol) 前期准备listen 服务端函数原型返回值使用示例注意事项 accpect 服务端函数原型返回值注意事项 connect 客户端函数原型返回值注意事项 send 和 recvsend() 函数函数原型返回值 recv() 函数函数原型返回值 accpect为啥要返回一个新的文件描述符 我们之前了解过了UDP的网络编程接口今天我们要来了解一下TCP网络接口。 TCP和UDP的区别 TCP传输控制协议和UDP用户数据报协议是两种常用的传输层协议它们用于在网络中传输数据。尽管它们都是基于IP互联网协议之上的传输层协议但两者在设计目标、功能特性以及应用场景上有着显著的区别。 TCP (Transmission Control Protocol) 连接导向TCP 是面向连接的协议在数据传输前需要建立连接三次握手确保通信双方都准备好接收数据。可靠性TCP 提供可靠的数据传输服务通过确认机制ACK、重传机制和流量控制来保证数据包按序无误地到达接收端。有序交付TCP 会按照发送顺序将数据包传递给应用层即使某些数据包后到也会被正确排序。流控与拥塞控制TCP 实现了复杂的流量控制和拥塞控制算法如慢启动、拥塞避免等以优化网络资源利用并防止网络拥塞。高开销由于提供了多种保障机制TCP 的头部较大处理过程也更复杂因此相对UDP来说具有更高的CPU和带宽开销。适用于场景适合对数据完整性要求高的应用例如文件传输FTP、电子邮件SMTP、网页浏览HTTP/HTTPS等。 UDP (User Datagram Protocol) 无连接UDP 是无连接的协议不需要在发送数据之前建立连接可以直接发送数据报文。不可靠性UDP 不提供可靠性保证它不会重传丢失的数据包也不保证数据包的顺序。无序交付UDP 按照接收到的顺序将数据交给应用层可能会出现乱序现象。低开销相比TCPUDP 头部较小没有复杂的握手过程和确认机制所以它的处理速度更快开销更低。适用于场景适合对实时性要求较高或对少量数据丢失不敏感的应用如视频流媒体、在线游戏、DNS查询等。 我们要关注的是TCP在发送数据之前要三次握手建立连接所以TCP和UDP的网络接口主要差别就是在这个建立连接上大家如果想详细了解一下TCP和UDP之间的区别可以看看这几篇文章 https://blog.csdn.net/qq_67693066/article/details/139620649 https://blog.csdn.net/qq_67693066/article/details/139623241 https://blog.csdn.net/qq_67693066/article/details/139626168 前期准备 TCP前期的准备跟UDP是差不多的所以我们这边按照套路写一下就行了 #pragma once #includeiostream #includecstring #includesys/socket.h #includenetinet/in.h #includearpa/inet.hconst static uint16_t defaultport 8888;class TcpServer {public:TcpServer(const uint16_t port defaultport):_port(port){}void Init(){//创建套接字_listen_socketfd socket(AF_INET,SOCK_STREAM,0);if(_listen_socketfd 0){std::cout Create listensocket fail! std::endl;}//初始化本地服务器信息struct sockaddr_in local;local.sin_family AF_INET; //IPV4local.sin_port htons(_port);local.sin_addr.s_addr INADDR_ANY;//绑定if(bind(_listen_socketfd,(struct sockaddr*)local,sizeof(local))){std::cout Bind fail! std::endl;exit(1);}std::cout Bind successfully and the listensocketfd is _listen_socketfd std::endl;}void Start(){while(true){}}~TcpServer(){}private://端口号uint16_t _port; //监听套接字int _listen_socketfd -1; };#includeiostream #includesys/socket.h #includenetinet/in.h #includearpa/inet.h #includeunistd.h #includecerrno #includestdio.h #includecstringvoid Usage() {std::cout Usage ./TcpClient server_ip server_port std::endl; }int main(int argc,char* argv[]) {if(argc ! 3){Usage();return 1;}//创建客户端的套接字int socketfd socket(AF_INET,SOCK_STREAM,0);if(socketfd 0){std::cout Create socketfd fail std::endl;exit(1);}std::cout Create socketfd successfully and the socketfd is socketfd std::endl;//填充服务器端的信息uint16_t serverport std::stoi(argv[2]);std::string serverip argv[1];struct sockaddr_in server;memset(server,0,sizeof(server));server.sin_family AF_INET;server.sin_port htons(serverport);if(inet_pton(AF_INET,serverip.c_str(),server.sin_addr) 1){std::cout IPV4 converstion is successful! std::endl; }else{perror(Invalid IPv4 address);} }#includeTcpServer.hpp #includememoryvoid Usage() {std::cout Usage ./TcpServer port std::endl; }int main(int argc, char* argv[]) {if(argc ! 2){Usage();return 1;}//创建智能指针uint16_t serverport std::stoi(argv[1]);std::unique_ptrTcpServer usr std::make_uniqueTcpServer(serverport);usr-Init();usr-Start();return 0; } 接下来我们要写的部分就是和UDP不一样的部分了 listen 服务端 TCP建立连接的时候服务器要进入监听状态监听客户端是否有链接请求listen就是完成这部分工作的 listen() 函数是TCP服务器端编程中的一个重要步骤它用于将套接字转换为监听状态以便接受来自客户端的连接请求。一旦调用了 listen()该套接字就会开始排队等待连接请求并准备好通过 accept() 来处理这些请求。 函数原型 #include sys/types.h #include sys/socket.hint listen(int sockfd, int backlog);sockfd这是由 socket() 函数创建并已经绑定了地址信息通过 bind()的套接字描述符。backlog这是监听队列的最大长度即在服务器开始拒绝新的连接之前可以有多少个未完成的连接半连接。这个值并不是绝对的操作系统可能会根据实际情况调整它。通常设置一个合理的值即可例如5到10之间。 返回值 如果成功listen() 返回 0。如果发生错误则返回 -1并设置 errno 以指示具体的错误原因。 使用示例 以下是一个完整的C语言代码片段展示了如何使用 listen() 函数 #include stdio.h #include stdlib.h #include string.h #include unistd.h #include arpa/inet.h#define PORT 8080 #define BACKLOG 10 // 监听队列的最大长度int main() {int server_fd;struct sockaddr_in address;// 创建套接字if ((server_fd socket(AF_INET, SOCK_STREAM, 0)) 0) {perror(socket failed);exit(EXIT_FAILURE);}// 设置地址结构体address.sin_family AF_INET;address.sin_addr.s_addr INADDR_ANY;address.sin_port htons(PORT);// 绑定套接字到指定地址和端口if (bind(server_fd, (struct sockaddr *)address, sizeof(address)) 0) {perror(bind failed);close(server_fd);exit(EXIT_FAILURE);}// 将套接字设置为监听状态if (listen(server_fd, BACKLOG) 0) {perror(listen failed);close(server_fd);exit(EXIT_FAILURE);}printf(Server is listening on port %d\n, PORT);// 接下来可以调用 accept() 来接收连接// ...// 关闭套接字close(server_fd);return 0; }注意事项 绑定后监听确保在调用 listen() 之前已经成功调用了 bind() 函数来绑定套接字到特定的地址和端口。选择合适的 backlog 值虽然 backlog 参数指定了监听队列的最大长度但实际的队列长度可能会受到操作系统的限制。一般来说除非有特殊需求否则不需要设置非常大的 backlog 值。非阻塞模式如果你希望 accept() 不会阻塞可以在调用 listen() 之后将套接字设置为非阻塞模式但这需要额外的处理逻辑来应对可能的 EAGAIN 或 EWOULDBLOCK 错误。 通过 listen() 函数服务器能够准备接受客户端的连接请求并通过后续的 accept() 调用来建立与客户端的实际连接。这使得服务器可以同时处理多个客户端的连接请求而不会因为等待某个客户端而导致其他客户端被忽视。 我们补全代码 #pragma once #includeiostream #includecstring #includesys/socket.h #includenetinet/in.h #includearpa/inet.hconst static uint16_t defaultport 8888; const static int BACKLOG 5; class TcpServer {public:TcpServer(const uint16_t port defaultport):_port(port){}void Init(){//创建套接字_listen_socketfd socket(AF_INET,SOCK_STREAM,0);if(_listen_socketfd 0){std::cout Create listensocket fail! std::endl;}//初始化本地服务器信息struct sockaddr_in local;local.sin_family AF_INET; //IPV4local.sin_port htons(_port);local.sin_addr.s_addr INADDR_ANY;//绑定if(bind(_listen_socketfd,(struct sockaddr*)local,sizeof(local))){std::cout Bind fail! std::endl;exit(1);}std::cout Bind successfully and the listensocketfd is _listen_socketfd std::endl;//监听if(listen(_listen_socketfd,BACKLOG) 0){std::cout Listen fail! std::endl;exit(1);}std::cout Listen successfully! and the listensocketfd is _listen_socketfd std::endl;}void Start(){while(true){}}~TcpServer(){}private://端口号uint16_t _port; //监听套接字int _listen_socketfd -1;};accpect 服务端 accept() 函数用于TCP服务器端编程中它从已完成连接队列中提取下一个连接请求并创建一个新的套接字来与客户端通信。这个新的套接字专用于与特定客户端之间的数据交换而原始的监听套接字则继续等待其他连接请求。 函数原型 #include sys/types.h #include sys/socket.hint accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);sockfd这是由 socket() 创建并已经调用 bind() 和 listen() 设置为监听状态的套接字描述符。addr可选这是一个指向 struct sockaddr 结构的指针用于接收客户端地址信息。如果不需要获取客户端地址信息可以传入 NULL。addrlen可选这是一个指向 socklen_t 类型变量的指针表示 addr 参数所指向结构的大小。调用 accept() 之前应该初始化这个值为结构体的大小函数返回时它会被更新为实际填充的地址结构的大小。如果 addr 是 NULL那么 addrlen 也应该是 NULL。 返回值 如果成功accept() 返回一个新套接字描述符该描述符用于与客户端进行通信。如果发生错误则返回 -1并设置 errno 以指示具体的错误原因。 注意事项 阻塞行为默认情况下accept() 是一个阻塞调用即如果没有待处理的连接请求它将一直等待直到有新的连接到来。如果你希望 accept() 不会阻塞可以在调用 accept() 之前将套接字设置为非阻塞模式。 多线程或多进程处理为了同时处理多个客户端连接通常需要在每次接受到新连接后启动一个新的线程或子进程来处理该连接这样主程序可以继续调用 accept() 来接收更多的连接。 关闭连接当与客户端的通信完成后记得关闭对应的客户端套接字 (new_socket)。监听套接字 (server_fd) 则保持打开状态继续接收新的连接请求。 #pragma once #includeiostream #includecstring #includesys/socket.h #includenetinet/in.h #includearpa/inet.hconst static uint16_t defaultport 8888; const static int BACKLOG 5; class TcpServer {public:TcpServer(const uint16_t port defaultport):_port(port){}void Init(){//创建套接字_listen_socketfd socket(AF_INET,SOCK_STREAM,0);if(_listen_socketfd 0){std::cout Create listensocket fail! std::endl;}//初始化本地服务器信息struct sockaddr_in local;local.sin_family AF_INET; //IPV4local.sin_port htons(_port);local.sin_addr.s_addr INADDR_ANY;//绑定if(bind(_listen_socketfd,(struct sockaddr*)local,sizeof(local))){std::cout Bind fail! std::endl;exit(1);}std::cout Bind successfully and the listensocketfd is _listen_socketfd std::endl;//监听if(listen(_listen_socketfd,BACKLOG) 0){std::cout Listen fail! std::endl;exit(1);}std::cout Listen successfully! and the listensocketfd is _listen_socketfd std::endl;}void Start(){while(true){//接收(抓取链接)struct sockaddr_in temp;memset(temp,0,sizeof(temp));socklen_t len sizeof(temp);int new_socketfd accept(_listen_socketfd,(struct sockaddr*)temp,len);char ip_str[INET_ADDRSTRLEN];const char* result inet_ntop(AF_INET, (temp.sin_addr), ip_str, sizeof(ip_str));std::string serverip result ? ip_str : Invalid address;if(new_socketfd 0){std::cout Accpect fail but try again std::endl;continue;}else{std::cout Accpect successfully and the new socketfd is new_socketfd std::endl;}}~TcpServer(){}private://端口号uint16_t _port; //监听套接字int _listen_socketfd -1;}; 通过 accept() 函数服务器能够有效地管理并发连接确保每个客户端都能得到及时的服务。 connect 客户端 connect() 函数用于TCP客户端编程中它尝试与指定的服务器建立连接。一旦成功建立了连接客户端就可以通过这个套接字与服务器进行数据交换。connect() 是一个阻塞调用意味着它会一直等待直到连接建立成功或失败。 函数原型 #include sys/types.h #include sys/socket.hint connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);sockfd这是由 socket() 创建的套接字描述符尚未与任何远程地址关联。addr这是一个指向 struct sockaddr 结构的指针包含要连接的服务器的地址信息。通常使用 struct sockaddr_in 或 struct sockaddr_in6 来表示IPv4或IPv6地址。addrlen这是 addr 参数所指向结构体的大小以字节为单位。对于 sockaddr_in这通常是 sizeof(struct sockaddr_in)。 返回值 如果成功connect() 返回 0。如果发生错误则返回 -1并设置 errno 以指示具体的错误原因。常见的错误包括ECONNREFUSED连接被服务器拒绝。ETIMEDOUT连接超时。EINPROGRESS在非阻塞模式下连接正在尝试建立但尚未完成。 #includeiostream #includesys/socket.h #includenetinet/in.h #includearpa/inet.h #includeunistd.h #includecerrno #includestdio.h #includecstringvoid Usage() {std::cout Usage ./TcpClient server_ip server_port std::endl; }int main(int argc,char* argv[]) {if(argc ! 3){Usage();return 1;}//创建客户端的套接字int socketfd socket(AF_INET,SOCK_STREAM,0);if(socketfd 0){std::cout Create socketfd fail std::endl;exit(1);}std::cout Create socketfd successfully and the socketfd is socketfd std::endl;//填充服务器端的信息uint16_t serverport std::stoi(argv[2]);std::string serverip argv[1];struct sockaddr_in server;memset(server,0,sizeof(server));server.sin_family AF_INET;server.sin_port htons(serverport);if(inet_pton(AF_INET,serverip.c_str(),server.sin_addr) 1){std::cout IPV4 converstion is successful! std::endl; }else{perror(Invalid IPv4 address);}//发起连接if(connect(socketfd,(struct sockaddr*)server,sizeof(server))!0){std::cout Connect fail! std::endl;exit(1);}else{std::cout Connect successfully! and the socketfd is socketfd std::endl;}close(socketfd);}注意事项 非阻塞模式如果你希望 connect() 不会阻塞可以在调用 connect() 之前将套接字设置为非阻塞模式。在这种情况下如果连接尚未完成connect() 会立即返回 -1 并设置 errno 为 EINPROGRESS。你需要使用 select()、poll() 或其他方法来检查连接是否已经建立成功。 错误处理确保对 connect() 的返回值进行适当的错误处理。特别是要注意处理那些可能导致连接失败的情况如服务器不可达或端口未开放等。 超时机制为了防止程序长时间卡在 connect() 上可以考虑实现超时机制。这可以通过设置套接字选项如 SO_RCVTIMEO 和 SO_SNDTIMEO或者使用 select() 或 poll() 来实现。 资源管理无论连接是否成功都应该确保在适当的时候关闭套接字以释放系统资源。 通过 connect() 函数客户端能够主动发起与服务器的连接请求从而开始双向的数据传输过程。这是TCP客户端编程中的关键步骤之一。 如果一切顺利就可以看到这样的结果 send 和 recv send() 和 recv() 是用于TCP套接字通信的两个重要函数分别用于发送和接收数据。它们是BSD套接字API的一部分在POSIX兼容的操作系统如Linux、macOS中广泛使用。 send() 函数 send() 用于通过已建立连接的套接字发送数据。它类似于标准文件I/O中的 write() 函数但提供了额外的控制选项。 函数原型 #include sys/types.h #include sys/socket.hssize_t send(int sockfd, const void *buf, size_t len, int flags);sockfd这是由 socket() 创建并已经通过 connect() 或 accept() 建立了连接的套接字描述符。buf指向要发送的数据缓冲区的指针。len要发送的数据长度以字节为单位。flags提供对行为的额外控制常用的标志包括MSG_DONTWAIT使操作非阻塞即使套接字本身是阻塞模式。MSG_NOSIGNAL防止SIGPIPE信号在写入已关闭的连接时生成。MSG_MORE指示有更多数据将被发送有助于优化Nagle算法的行为。 返回值 如果成功send() 返回实际发送的字节数。这个值可能小于请求发送的字节数例如当套接字缓冲区满时因此你可能需要循环调用 send() 直到所有数据都被发送。如果发生错误则返回 -1并设置 errno 以指示具体的错误原因。 recv() 函数 recv() 用于从已建立连接的套接字中读取数据。它类似于标准文件I/O中的 read() 函数也提供了额外的控制选项。 函数原型 #include sys/types.h #include sys/socket.hssize_t recv(int sockfd, void *buf, size_t len, int flags);sockfd这是由 socket() 创建并已经通过 connect() 或 accept() 建立了连接的套接字描述符。buf指向用来存储接收到的数据的缓冲区的指针。len要接收的最大数据量以字节为单位。flags提供对行为的额外控制常用的标志包括MSG_WAITALL等待直到接收到请求的所有数据。MSG_DONTWAIT使操作非阻塞即使套接字本身是阻塞模式。MSG_PEEK预览数据而不实际移除它即数据仍然保留在接收队列中。 返回值 如果成功recv() 返回实际接收到的字节数。如果返回值为0则表示对端已经关闭了连接。如果发生错误则返回 -1并设置 errno 以指示具体的错误原因。 我们将客户端和服务器端的代码补完 #pragma once #includeiostream #includecstring #includesys/socket.h #includenetinet/in.h #includearpa/inet.hconst static uint16_t defaultport 8888; const static int BACKLOG 5; class TcpServer {public:TcpServer(const uint16_t port defaultport):_port(port){}void Init(){//创建套接字_listen_socketfd socket(AF_INET,SOCK_STREAM,0);if(_listen_socketfd 0){std::cout Create listensocket fail! std::endl;}//初始化本地服务器信息struct sockaddr_in local;local.sin_family AF_INET; //IPV4local.sin_port htons(_port);local.sin_addr.s_addr INADDR_ANY;//绑定if(bind(_listen_socketfd,(struct sockaddr*)local,sizeof(local))){std::cout Bind fail! std::endl;exit(1);}std::cout Bind successfully and the listensocketfd is _listen_socketfd std::endl;//监听if(listen(_listen_socketfd,BACKLOG) 0){std::cout Listen fail! std::endl;exit(1);}std::cout Listen successfully! and the listensocketfd is _listen_socketfd std::endl;}void Start(){while(true){//接收(抓取链接)struct sockaddr_in temp;memset(temp,0,sizeof(temp));socklen_t len sizeof(temp);int new_socketfd accept(_listen_socketfd,(struct sockaddr*)temp,len);char ip_str[INET_ADDRSTRLEN];const char* result inet_ntop(AF_INET, (temp.sin_addr), ip_str, sizeof(ip_str));std::string serverip result ? ip_str : Invalid address;if(new_socketfd 0){std::cout Accpect fail but try again std::endl;continue;}else{std::cout Accpect successfully and the new socketfd is new_socketfd std::endl;}//开始服务while(true){char buffer[1024]; //缓冲区int n recv(new_socketfd,buffer,sizeof(buffer)-1,0);if(n 0){buffer[n] 0;std::cout [ serverip ]# buffer std::endl; }else if(n 0 || n 0){std::cout Client quit std::endl;break;}else{std::cout Read fail std::endl;break;}}}}~TcpServer(){}private://端口号uint16_t _port; //监听套接字int _listen_socketfd -1;};#includeiostream #includesys/socket.h #includenetinet/in.h #includearpa/inet.h #includeunistd.h #includecerrno #includestdio.h #includecstringvoid Usage() {std::cout Usage ./TcpClient server_ip server_port std::endl; }int main(int argc,char* argv[]) {if(argc ! 3){Usage();return 1;}//创建客户端的套接字int socketfd socket(AF_INET,SOCK_STREAM,0);if(socketfd 0){std::cout Create socketfd fail std::endl;exit(1);}std::cout Create socketfd successfully and the socketfd is socketfd std::endl;//填充服务器端的信息uint16_t serverport std::stoi(argv[2]);std::string serverip argv[1];struct sockaddr_in server;memset(server,0,sizeof(server));server.sin_family AF_INET;server.sin_port htons(serverport);if(inet_pton(AF_INET,serverip.c_str(),server.sin_addr) 1){std::cout IPV4 converstion is successful! std::endl; }else{perror(Invalid IPv4 address);}//发起连接if(connect(socketfd,(struct sockaddr*)server,sizeof(server))!0){std::cout Connect fail! std::endl;exit(1);}else{std::cout Connect successfully! and the socketfd is socketfd std::endl;}while(true){std::string inbuffer;std::getline(std::cin,inbuffer);//向服务端发送信息int n send(socketfd,inbuffer.c_str(),inbuffer.size(),0);}close(socketfd);}我们用本地回环测试一下 我们也可以用windows来测试一下 #define _CRT_SECURE_NO_WARNINGS 1 #include winsock2.h #include ws2tcpip.h #include iostream #includestring #includecstdio #includestdio.h#pragma comment(lib, Ws2_32.lib)int main() {// 初始化WinsockWSADATA wsaData;int iResult WSAStartup(MAKEWORD(2, 2), wsaData);if (iResult ! 0) {std::cerr WSAStartup failed: iResult std::endl;return 1;}// 创建套接字SOCKET SendSocket socket(AF_INET, SOCK_STREAM, 0);if (SendSocket INVALID_SOCKET) {std::cerr socket failed: WSAGetLastError() std::endl;WSACleanup();return 1;}// 设置服务器地址和端口sockaddr_in RecvAddr;RecvAddr.sin_family AF_INET;RecvAddr.sin_port htons(8888); // 假设服务器在12345端口监听// 将服务器地址从文本转换为二进制形式inet_pton(AF_INET, 43.138.14.12, RecvAddr.sin_addr); // 换成自己服务器的ip// 连接到服务器iResult connect(SendSocket, (SOCKADDR*)RecvAddr, sizeof(RecvAddr));if (iResult SOCKET_ERROR) {std::cerr connect failed: WSAGetLastError() std::endl;closesocket(SendSocket);WSACleanup();return 1;}// 发送消息到服务器while (true){std::string message;std::cout Please enter# ;std::getline(std::cin,message);iResult send(SendSocket, message.c_str(), message.size(), 0);if (iResult SOCKET_ERROR) {std::cerr send failed: WSAGetLastError() std::endl;closesocket(SendSocket);WSACleanup();return 1;}else {std::cout Message sent successfully: message std::endl;}}// 关闭套接字closesocket(SendSocket);// 清理WinsockWSACleanup();return 0; }accpect为啥要返回一个新的文件描述符 我们之前编写代码时我们一开始定义的socket是listen的socket但是我们执行accpect时会返回一个新的套接字描述符这是为什么呢 这里主要是为了支持并发连接 服务器通常需要同时处理多个客户端连接。如果 accept() 不返回新的文件描述符而是使用原始监听套接字进行通信那么每次只能与一个客户端通信其他客户端将被阻塞直到当前通信完成。通过为每个新连接创建一个新的文件描述符服务器可以同时与多个客户端保持独立的通信会话。 listen套接字是负责“揽客”的只负责抓客户端发来的连接有点像饭店门口招揽客人真正提供服务的是accpect执行后那个新的套接字饭店里面的服务员才是真正提供服务
http://www.w-s-a.com/news/947114/

相关文章:

  • 做影视网站违法莫品牌营销是什么
  • 全网最稳最低价自助下单网站wordpress电影网站主题
  • 域名更换网站温州建设工程网站
  • 网站如何优化推广连锁店管理网站开发
  • 伊宁市做网站功能性质网站
  • 北京哪个网站制作公司优化大师免费安装下载
  • 同江佳木斯网站设计做网站联系电话
  • 设计上海展会2023seo网站模板下载
  • 开发一个卖东西的网站多少站长工具永久
  • 公司网站怎么突然多了好多友情链接如何删除宁波有几个区
  • 临沂seo网站推广wordpress新编辑器
  • c2c网站设计店面logo设计制作
  • 网站建设任务执行书重庆今天新闻事件
  • 怎样发布自己的网站南宁制作网站公司
  • wordpress装多站点百度查一下
  • 怎么优化一个网站搭建网站免费空间
  • 山东建设和城乡建设厅注册中心网站首页wordpress安装教材
  • 个人风采网站制作毕节网站开发公司电话
  • 网络网站销售设计主题和设计理念
  • 做网站一般用什么服务器承德专业做网站
  • 松北区建设局网站网站建设分为几种
  • 网站建设的合同 体会智联招聘网站建设情况
  • 记的网站域名wordpress地方信息主题
  • 淄博好的建网站公司网站建设 海口
  • 有人做网站花了10几万2017做啥网站能致富
  • 做网站有什么软件cod建站平台
  • 合肥学校网站建设怎么做免费的产品图片网站
  • 营养早餐网站的设计与制作建设通网站怎么查项目经理在建
  • 浑南区建设局网站永州网站建设公司推荐
  • 做外贸都得有网站吗绵阳网站建设制作