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

网站标题几个字合适站长seo查询

网站标题几个字合适,站长seo查询,三星官网商城,网站规划设计报告背景知识 我们知道#xff0c; IP 地址用来标识互联网中唯一的一台主机#xff0c; port 用来标识该主机上唯一的一个网络进程#xff0c;IPPort 就能表示互联网中唯一的一个进程。所以通信的时候#xff0c;本质是两个互联网进程代表人来进行通信#xff0c;{srcIp IP 地址用来标识互联网中唯一的一台主机 port 用来标识该主机上唯一的一个网络进程IPPort 就能表示互联网中唯一的一个进程。所以通信的时候本质是两个互联网进程代表人来进行通信{srcIpsrcPort dstIp dstPort} 这样的 4 元组就能标识互联网中唯二的两个进程。所以网络通信的本质也是进程间通信我们把 ipport 叫做套接字 socket。 socket n.(电源 ) 插座 ( 电器上的 ) 插口插孔管座槽窝托座臼孔穴 vt.把… 装入插座给 … 配插座 套接字socket是一种通信机制它提供了一种在网络上进行进程间通信的方法。套接字可以被看作是网络通信的端点它允许不同主机上的进程通过网络进行通信。套接字屏蔽了各个协议的通信细节提供了TCP/IP协议的抽象对外提供了一套接口通过这个接口就可以统一、方便地使用TCP/IP协议的功能。 传输层的典型代表 如果我们了解系统也了解网络协议栈我们就会清楚传输层是属于内核的那么我们要通过网络协议栈进行通信必定调用的是传输层提供的系统调用来进行的网络通信。 TCP 协议 我们先对 TCP(Transmission Control Protocol 传输控制协议 ) 有一个直观的认识 传输层协议 有连接 可靠传输 面向字节流 UDP 协议 我们也对 UDP(User Datagram Protocol 用户数据报协议 ) 有一个直观的认识 传输层协议 无连接 不可靠传输 面向数据报 sockaddr 结构 套接字有很多类型主要分为以下几种 Unix Socket域套接字用于本地通信通常用于同一台机器上的不同进程间通信。Inet Socket网络套接字用于网络通信支持多种协议如TCP和UDP。Raw Socket原始套接字用于网络管理和底层网络编程。 sockaddr 结构是在网络编程中用于表示套接字地址的通用数据结构 它的作用是存储网络地址信息供套接字函数使用此时套接字函数就知道要对哪一台主机进行网络操作它被设计为一个抽象层允许应用程序通过同一接口处理不同类型的网络协议和地址族。 但是sockaddr结构体不能直接存储 IPv4 或 IPv6 的地址信息在实际使用中通常会用到它的具体子类型如 sockaddr_in用于 IPv4和 sockaddr_in6用于 IPv6sockaddr_un用于域套接。 为了管理多种套接字所有套接字的头部都是一个16位的地址类型用于辨别这个结构体表示哪一个套接字。当操作sockaddr的时候读取前16位就知道这个sockaddr具体是哪一种套接字随后再进行类型转化变成对应套接字类型的结构体此时就能对具体的套接字做操作了。 socket API 可以都用 struct sockaddr * 类型表示 , 在使用的时候需要强制转化成sockaddr_in; 这样的好处是程序的通用性 , 可以接收 IPv4, IPv6, 以及 UNIX Domain Socket 各种类型的 sockaddr 结构体指针做为参数 ; sockaddr 结构体定义在 sys/socket.h 头文件中其基本定义如下 struct sockaddr {sa_family_t sin_family; /* 地址家族AF_XXX */char sin_zero[14]; /* 填充字段实际用途取决于具体的地址家族 */ }; 其中sin_family 字段用来指定协议族即协议类型常见的取值有 AF_INETIPv4、AF_INET6IPv6和 AF_UNIXUNIX 域套接字等。 其中最常用的就是 AF_INET 进行IPv4通信。其对应的具体结构体为struct sockaddr_in定义如下 struct sockaddr_in {sa_family_t sin_family; /* 协议族AF_INET */uint16_t sin_port; /* TCP 或 UDP 端口号 */struct in_addr sin_addr; /* 32 位 IPv4 地址 */ }; 此处有一个小细节IPv4的地址占32位用一个int类型即可存储sin_addr的类型却是struct in_addr这其实是Linux对其进行了额外的一层封装 struct in_addr {uint32_t s_addr; };所以存储地址的时候要用sockaddr_in.sin_addr.s_addr此处嵌套了两层结构体。基于IP地址和端口号此时就可以定位到全世界的一个主机上的一个具体进程此时就可以进行后续的网络通信了。 bzero 我们知道struct sockaddr_in 的内部还有8字节填充这是为了以确保struct sockaddr_in的大小与struct sockaddr一致所以我们需要一开始时将其初始化为0。除此创建结构体时分配到的内存原先有可能存储了其他数据为了保证不被之前的数据影响我们也要把整个结构体的内存全部置为0。 所以我们可以使用bzero函数。 void bzero(void* s, size_t n);s要初始化内存的地址n要初始化的字节数 示例如下 struct sockaddr_in socket; bzero(socket,sizeof(socket)); 网络字节序(填sin_port) 我们知道 , 内存中的多字节数据相对于内存地址有大端和小端之分 , 磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分, 网络数据流同样有大端小端之分。 那么如何定义网络数据流的地址呢 ? 发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存因此, 网络数据流的地址应这样规定 : 先发出的数据是低地址 , 后发出的数据是高地址. TCP/IP 协议规定 , 网络数据流应采用大端字节序 , 即低地址高字节 . 不管这台主机是大端机还是小端机 都会按照这个 TCP/IP 规定的网络字节序来发送/ 接收数据如果当前发送主机是小端, 就需要先将数据转成大端 ; 否则就忽略 , 直接发送即可。 为使网络程序具有可移植性 , 使同样的 C 代码在大端和小端计算机上编译后都能正常运行, 可以调用以下库函数做网络字节序和主机字节序的转换使用以下函数需要包含头文件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 地址转换后准备发送。如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回如果主机是大端字节序,这些函数不做转换 , 将参数原封不动地返回。 假设我们有一个类型为 struct sockaddr_in 的套接字socket在填写内部端口号时内部数据的字节序就要使用网络字节序。因为 sin_port 类型为 uint16_t所以使用 htons 函数。 struct sockaddr_in socket; socket.sin_port8080;//错误 socket.sin_porthtons(8080);//正确 IP地址转换(填sin_addr) 在给 struct sockaddr_in 结构体填入数据时其IP地址 sin_addr 的格式也需要遵循特定的规则。我们知道IP地址有两种基本格式4字节序列以及点分十进制如果拿到的IP地址格式与自己所需的类型不符此时就要考虑两种格式之间转化的问题了。 inet_addr函数用于将一个点分十进制的IP地址字符串转换为网络字节序的32位整数。 in_addr_t inet_addr(const char *cp);参数cp是一个指向以点分十进制格式表示的IP地址字符串的指针例如127.0.0.1。函数返回一个32位的无符号整数表示转换后的IP地址。如果输入的字符串不是一个合法的IP地址函数将返回INADDR_NONE通常定义为-1。 示例如下 struct sockaddr_in socket; socket.sin_addr.s_addr inet_addr(127.0.0.1);我们知道存入 struct sockaddr_in 中的数据必须是网络字节序此处将点分十进制转化为四字节序列后应该还需要转成网络字节序。的确如此不过我们不需要手动转换因为 inet_addr 函数已经帮我们完成转换。 inet_ntoa函数用于将一个网络字节序的32位整数IP地址转换为点分十进制的字符串格式。这个函数的原型如下 char *inet_ntoa(struct in_addr in);参数in是一个struct in_addr类型的结构体其中包含了一个32位的无符号整数表示IP地址。inet_ntoa函数返回一个指向静态存储区的字符串该字符串包含了以点分十进制格式表示的IP地址。由于返回的字符串存储在静态存储区因此在多线程环境中可能会出现问题因为后续的调用可能会覆盖之前的结果所以在多线程环境下推荐使用ntop函数。 char *inet_ntop(int af, const void *src, char *dst, socklen_t size); 参数 af协议族可以是AF_INETIPv4或AF_INET6IPv6。src指向要转换的网络字节序IP地址的指针。dst指向存储转换后字符串的缓冲区的指针。size缓冲区的大小。 返回值成功时返回指向dst的非空指针。失败时返回NULL并且可以通过errno获取错误码。 综上我们就有一个类型为 struct sockaddr_in 比较完整的初始化过程了 struct sockaddr_in socket; bzero(socket,sizeof(socket)); socket.sin_familyAF_INET; socket.sin_porthtons(8080); socket.sin_addr.s_addrinet_addr(127.0.0.1); UDP socket UDPUser Datagram Protocol套接字是一种网络通信协议它提供了一种无连接、不可靠的传输服务。UDP套接字通常用于需要快速传输和实时响应的应用场景如在线游戏、视频会议和实时监控等。 UDP套接字的特点 无连接性UDP不需要在发送数据之前建立连接因此减少了通信延迟。不可靠性UDP不提供数据传输的可靠性保证数据包可能会丢失或乱序到达。面向数据报UDP以数据报为单位进行传输每个数据报都是独立的。全双工UDP支持双向通信允许同时进行数据的发送和接收。 socket 创建套接字 socket函数用于创建一个新的套接字需要头文件sys/types.hsys/socket.h函数原型如下 int socket(int domain, int type, int protocol); 参数 domain指定协议族对于UDP套接字通常使用AF_INETIPv4或者AF_INET6IPv6。type指定套接字类型创建UDP套接字时使用SOCK_DGRAMDGRAM为datagram缩写即数据报。protocol指定协议类型一般设置为0表示根据前面两个参数自动选择合适的协议对于AF_INET和SOCK_DGRAM会自动选择UDP协议。 返回值如果成功创建套接字返回一个非负的套接字描述符其本质也是一个文件描述符后续对网络的操作就是对这个文件的操作。比如向网络中发送消息其实就是向文件中写入数据如果失败返回 - 1并设置errno来指示错误类型。 使用示例如下 int sockfdsocket(AF_INET,SOCK_DGRAM,0); bind 绑定地址 当创建完套接字后这个套接字还没有指定和哪一个主机通信此时就需要IP地址和端口号之前讲的sockaddr_in就派上用场了bind函数用于给套接字绑定IP地址和端口号指定和哪一台主机通信函数原型如下 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 参数 sockfd由socket()函数返回的套接字描述符。addr一个指向sockaddr结构或者sockaddr_in对于IPv4或者sockaddr_in6对于IPv6的指针包含了要绑定的地址和端口信息。addrlen是addr所指向结构的长度。 返回值如果绑定成功返回0如果失败返回 - 1并设置errno来指示错误类型。 此处注意传入的是struct sockaddr *所以sockaddr_in类型的变量传入的时候要进行类型转化。 //创建UDP套接字 int sockfd socket(AF_INET, SOCK_DGRAM, 0);//初始化套接字要通信的目标主机地址 struct sockaddr_in socket; bzero(socket, sizeof(socket)); socket.sin_family AF_INET; socket.sin_port htons(8080); socket.sin_addr.s_addr inet_addr(127.0.0.1);//绑定地址到套接字 bind(sockfd, (struct sockaddr*)socket, sizeof(socket));sendto 发送数据 sendto函数用于发送数据报函数原型如下 ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); 参数 sockfd是要发送数据的套接字描述符。buf是一个指向要发送数据的缓冲区的指针。len是要发送数据的长度以字节为单位。flags一般设置为0或者可以使用一些特定的标志如MSG_DONTWAIT等。dest_addr是一个指向sockaddr结构或者sockaddr_in对于IPv4或者sockaddr_in6对于IPv6的指针包含了目标地址和端口信息。addrlen是dest_addr所指向结构的长度。 返回值如果成功发送数据返回实际发送的字节数如果失败返回 - 1并设置errno来指示错误类型。 //创建UDP套接字 int sockfd socket(AF_INET, SOCK_DGRAM, 0);//初始化套接字要通信的目标主机地址 struct sockaddr_in socket; bzero(socket, sizeof(socket)); socket.sin_family AF_INET; socket.sin_port htons(8080); socket.sin_addr.s_addr inet_addr(127.0.0.1);//给目标主机发送消息 const char* message hello; sendto(sockfd,message,sizeof(message),(struct sockaddr*)socket,sizeof(socket));此处给地址为127.0.0.1端口为8080发送了一个报文内容是”hello“。 我们可以看到以上代码中没有bind绑定地址因为该操作已经由操作系统自动完成了Linux会自动为其分配端口号并完成绑定随后通过随机分配的端口发送数据这种行为称为隐式绑定。在实际开发中一般服务端占用指定的端口这样客户端才知道往哪一个端口发送请求所以服务端要显式bind指定端口不能让操作系统分配。而客户端往往不在意端口号只需要能与服务端通信即可所以客户端一般不bind而是让系统随机分配一个端口。 recvfrom 接收数据 在Linux系统下recvfrom函数用于在UDP套接字上接收数据其函数原型如下 ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); 参数 sockfd是要接收数据的套接字描述符。buf是一个指向用于接收数据的缓冲区的指针。len是缓冲区的长度以字节为单位。flags一般设置为0或者可以使用一些特定的标志如MSG_DONTWAIT等。src_addr是一个指向sockaddr结构或者sockaddr_in对于IPv4或者sockaddr_in6对于IPv6的指针如果不为NULL则用于存储发送方的地址和端口信息。addrlen是一个指向socklen_t类型的指针如果src_addr不为NULL则在函数调用前*addrlen应设置为src_addr所指向结构的长度函数返回时*addrlen被更新为实际存储发送方地址信息的结构的长度。 返回值如果成功接收数据返回实际接收的字节数如果失败返回 - 1并设置errno来指示错误类型。 使用示例 //创建UDP套接字 int sockfd socket(AF_INET, SOCK_DGRAM, 0);//初始化套接字要通信的目标主机地址 struct sockaddr_in socket; bzero(socket, sizeof(socket)); socket.sin_family AF_INET; socket.sin_port htons(8080); socket.sin_addr.s_addr inet_addr(127.0.0.1);//接收消息 struct sockaddr_in sendsock; socklen_t len; char* buf[1024]; recvfrom(sockfd,buf,sizeof(buf)-1,(struct sockaddr*)sendsock,sizeof(len)); close 关闭套接字 在Linux系统下close函数用于关闭文件我们知道实际上在网络中通信其实也是对文件进行操作所以通信结束后我们需要关闭套接字其函数原型如下 int close(int fd); 参数fd是要关闭的套接字描述符也就是由socket函数创建的套接字描述符。 返回值如果关闭成功返回0如果失败返回 - 1并设置errno来指示错误类型。 案例echosever 简单的回显服务器和客户端代码 makefile .PHONY:all all:server client server:UdpServermain.ccg -o $ $^ -stdc17 client:UdpClientmain.ccg -o $ $^ -stdc17 .PHONY:clean clean:rm -f server client UdpServer.hpp #include common.hppconst uint16_t default_port 8080; class UdpServer { public:UdpServer(uint16_t port default_port): _port(port), _sockfd(-1){// 创建socket_sockfd socket(AF_INET, SOCK_DGRAM, 0);if (_sockfd 0){cout create socket error endl;exit(SOCKET_ERROR);}// 将socket绑定到ip和端口struct sockaddr_in local;bzero(local, sizeof(local));local.sin_family AF_INET;local.sin_port htons(_port);//local.sin_addr.s_addr inet_addr(_ip.c_str());//云服务器不允许直接 bind 公有IP我们也不推荐编写服务器的时候,bind 明确的 IP推荐直接写成 INADDR_ANY//在网络编程中当一个进程需要绑定一个网络端口以进行通信时可以使用INADDR_ANY 作为 IP 地址参数。//这样做意味着该端口可以接受来自任何 IP 地址的连接请求无论是本地主机还是远程主机。例如如果服务//器有多个网卡每个网卡上有不同的 IP 地址使用 INADDR_ANY 可以省去确定数据是从服务器上具体哪个//网卡/IP 地址上面获取的。local.sin_addr.s_addr INADDR_ANY;int n bind(_sockfd, (struct sockaddr *)local, sizeof(local));if (n 0){cout bind socket error endl;exit(BIND_ERROR);}}~UdpServer(){if (_sockfd 0)close(_sockfd);_sockfd -1;cout socket closed endl;}void start(){// 循环接收数据while (true){struct sockaddr_in from;socklen_t len sizeof(from);char buf[1024];int n recvfrom(_sockfd, buf, sizeof(buf) - 1, 0, (struct sockaddr *)from, len);if (n 0){buf[n] 0;string ip inet_ntoa(from.sin_addr);int port ntohs(from.sin_port);cout receive from [ ip : port ]# buf endl;sendto(_sockfd, buf, sizeof(buf), 0, (struct sockaddr *)from, len);}}}private:uint16_t _port;int _sockfd; };UdpServermain.cc #include UdpServer.hpp #include iostream using namespace std; //./server localport int main(int argc, char *argv[]) {if (argc ! 2){cout Usage:./server localport endl;return Usage_ERROR;}int port stoi(argv[1]);UdpServer server(port);server.start();return 0; } UdpClientmain.cc #include common.hpp //./client server_ip server_port int main(int argc, char *argv[]) {if (argc ! 3){cout Usage: argv[0] sever_ip sever_port endl;return Usage_ERROR;}// 创建socketint sockfd socket(AF_INET, SOCK_DGRAM, 0);if (sockfd 0){cout create socket error endl;exit(SOCKET_ERROR);}// 填充一下 server 信息string serverip argv[1];int serverport stoi(argv[2]);struct sockaddr_in serveraddr;bzero(serveraddr, sizeof(serveraddr));serveraddr.sin_family AF_INET;serveraddr.sin_port htons(serverport);serveraddr.sin_addr.s_addr inet_addr(serverip.c_str());// client 要不要进行 bind? 一定要 bind 的// 但是不需要显示 bindclient 会在首次发送数据的时候会自动进行bind// 为什么server 端的端口号一定是众所周知不可改变的client非常多,需要 bind 随机端口.while (true){cout please input message:;string message;getline(cin, message);sendto(sockfd, message.c_str(), message.size(), 0, (struct sockaddr *)serveraddr, sizeof(serveraddr));char buf[1024];struct sockaddr_in tmp;socklen_t len sizeof(tmp);int n recvfrom(sockfd, buf, sizeof(buf) - 1, 0, (struct sockaddr *)tmp, len);if (n 0){buf[n] 0;cout server say: buf endl;}elsebreak;}return 0; }以上为Linux版本Windows版本如下 #include iostream #include cstdio #include thread #include string #include cstdlib #include WinSock2.h #include Windows.h #pragma warning(disable : 4996) #pragma comment(lib, ws2_32.lib) using namespace std; string serverip 110.41.138.70;// 填写云服务器ip int serverport 8080;// 填写云服务开放的端口 int main( ) {WSADATA wsa;WSAStartup(MAKEWORD(2, 2), wsa);//创建socketint sockfd socket(AF_INET, SOCK_DGRAM, 0);if (sockfd 0){cout create socket error endl;return 1;}//填充server信息struct sockaddr_in serveraddr;memset(serveraddr, sizeof(serveraddr),0);serveraddr.sin_family AF_INET;serveraddr.sin_port htons(serverport);serveraddr.sin_addr.s_addr inet_addr(serverip.c_str());while (true){cout please input message:;string message;getline(cin, message);sendto(sockfd, message.c_str(), message.size(), 0, (struct sockaddr*)serveraddr, sizeof(serveraddr));char buf[1024];struct sockaddr_in tmp;int len sizeof(tmp);int n recvfrom(sockfd, buf, sizeof(buf) - 1, 0, (struct sockaddr*)tmp, len);if (n 0){buf[n] 0;cout server say: buf endl;}}closesocket(sockfd);WSACleanup();return 0; }WinSock2.h 是 Windows Sockets API 应用程序接口的头文件用于在 Windows 平台上进行网络编程。它包含了 Windows Sockets 2 Winsock2 所需的数据类型、函数声明和结构定义使得开发者能够创建和使用套接字sockets 进行网络通信。 在编写使用 Winsock2 的程序时需要在源文件中包含 WinSock2.h 头文件。这样编译器就能够识别并理解 Winsock2 中定义的数据类型和函数从而能够正确地编译和链接网络相关的代码。此外与 WinSock2.h 头文件相对应的是 ws2_32.lib 库文件。在链接阶段需要将这个库文件链接到程序中以确保运行时能够找到并调用 Winsock2 API 中实现的函数。 在 WinSock2.h 中定义了一些重要的数据类型和函数如 WSADATA保存初始化 Winsock 库时返回的信息。 SOCKET表示一个套接字描述符用于在网络中唯一标识一个套接字。 sockaddr_inIPv4 地址结构体用于存储 IP 地址和端口号等信息。 socket()创建一个新的套接字。 bind()将套接字与本地地址绑定。 listen()将套接字设置为监听模式等待客户端的连接请求。 accept()接受客户端的连接请求并返回一个新的套接字描述符用于与客户端进行通信。 WSAStartup 函数是 Windows Sockets API 的初始化函数它用于初始化 Winsock 库。该函数在应用程序或 DLL 调用任何 Windows 套接字函数之前必须首先执行它扮演着初始化的角色。 以下是 WSAStartup 函数的一些关键点 它接受两个参数 wVersionRequested 和 lpWSAData 。 wVersionRequested 用于指定所请求的 Winsock 版本通常使用 MAKEWORD(major, minor) 宏其中 major 和 minor 分别表示请求的主版本号和次版本号。 lpWSAData 是一个指向 WSADATA 结构的指针用于接收初始化信息。 如果函数调用成功它会返回 0 否则返回错误代码。 WSAStartup 函数的主要作用是向操作系统说明我们将使用哪个版本的 Winsock 库从而使得该库文件能与当前的操作系统协同工作。成功调用该函数后Winsock 库的状态会被初始化应用程序就可以使用 Winsock 提供的一系列套接字服务如地址家族识别、地址转换、名字查询和连接控制等。这些服务使得应用程序可以与底层的网络协议栈进行交互实现网络通信。在调用 WSAStartup 函数后如果应用程序完成了对请求的 Socket 库的使用应调用WSACleanup 函数来解除与 Socket 库的绑定并释放所占用的系统资源。
http://www.w-s-a.com/news/58654/

相关文章:

  • 网站宣传的劣势域名注册长沙有限公司
  • 怎样联系自己建设网站企业怎样做好网站建设
  • 网站制作需求分析电商网站建设浩森宇特
  • 淄博网站建设招聘摄影网站建设的论文
  • 怎么把凡科网里做的网站保存成文件网站建设研究的意义
  • 服务器2003怎么做网站网站建设服务器的配置
  • 高校网站建设方案网站推广软件下载安装免费
  • 重庆没建网站的企业网站开发软件 连接SQL数据库
  • 百度申诉网站沉默是金
  • 如何自己建网站wordpress图片延时加载
  • 甘肃省住房和城乡建设厅注册中心网站千博企业网站管理系统2013
  • 西餐厅网站模板seo搜索引擎优化ppt
  • 什么做的网站吗wordpress注册可见插件
  • 献县做网站价格可以提升自己的网站
  • 如何修改网站title建设网站只能是公司
  • 网站推广效果怎么样建设工程公司组织架构图
  • 成都制作网站价格表网站安全证书过期怎么办
  • 高校图书馆网站的建设方案湖南常德市
  • 房地产怎么做网站推广wordpress插件汉化下载
  • 一般pr做视频过程那个网站有无锡网络公司平台
  • 安徽网站推广系统网站根目录权限设置
  • 班级网站建设需求智慧校园登录入口
  • asp.net网站发布到虚拟主机电商设计网站哪个好
  • 做的网站怎么转成网址链接企业为什么要找会计
  • 关于建设网站的情况说明书文化建设方面的建议
  • 订票网站开发公司大通证券手机版下载官方网站下载
  • 网店美工的意义与发展佛山推广seo排名
  • 网站在建设中模板自助云商城
  • 珠海网站设计建建建设网站公司网站
  • 广州高端网站制作公司哪家好网页制作公司 软件