国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

linux并發(fā)服務(wù)器 —— IO多路復(fù)用(八)

這篇具有很好參考價值的文章主要介紹了linux并發(fā)服務(wù)器 —— IO多路復(fù)用(八)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

半關(guān)閉、端口復(fù)用

半關(guān)閉只能實現(xiàn)數(shù)據(jù)單方向的傳輸;當(dāng)TCP 接中A向 B 發(fā)送 FIN 請求關(guān)閉,另一端 B 回應(yīng)ACK 之后 (A 端進(jìn)入 FIN_WAIT_2 狀態(tài)),并沒有立即發(fā)送 FIN 給 A,A 方處于半連接狀態(tài) (半開關(guān)),此時 A 可以接收 B 發(fā)送的數(shù)據(jù),但是 A 已經(jīng)不能再向 B 發(fā)送數(shù)據(jù)

linux并發(fā)服務(wù)器 —— IO多路復(fù)用(八),服務(wù)器,運(yùn)維,c++,linux,網(wǎng)絡(luò)

close不會影響到其他進(jìn)程,shutdown會影響到其他進(jìn)程;

網(wǎng)絡(luò)信息相關(guān)的命令

netstat

? ? ? ? -a 所有的Socket

? ? ? ? -p 正在所用socket的程序名稱

? ? ? ? -n 直接使用IP地址,不通過域名服務(wù)器

端口復(fù)用

1. 防止服務(wù)器重啟時之前綁定的端口還沒釋放

2. 程序突然退出而系統(tǒng)沒有釋放端口

linux并發(fā)服務(wù)器 —— IO多路復(fù)用(八),服務(wù)器,運(yùn)維,c++,linux,網(wǎng)絡(luò)

IO多路復(fù)用簡介

I/O多路復(fù)用使程序可以同時監(jiān)聽多個文件描述符,提高程序性能;select/poll/epoll

阻塞等待:不占用CPU寶貴時間;但同一時刻只能處理一個操作,效率低。

非阻塞,忙輪詢:提高了程序執(zhí)行效率;但會占用更多的CPU資源。

select/poll:委托內(nèi)核進(jìn)行檢測,但仍需要進(jìn)行遍歷

epoll:同樣委托內(nèi)核,但無需進(jìn)行遍歷

select

主旨思想:

1. 構(gòu)造關(guān)于文件描述符的列表,將要監(jiān)聽的文件描述符添加到表中

2. 調(diào)用系統(tǒng)函數(shù),監(jiān)聽該列表中的文件描述符,知道描述符中的一個/多個進(jìn)行了I/O操作,函數(shù)才返回(該函數(shù)是阻塞的,且該函數(shù)對于文件描述符的檢測是由內(nèi)核完成的)

3. 返回時,告訴進(jìn)程有多少描述符要進(jìn)行I/O操作

linux并發(fā)服務(wù)器 —— IO多路復(fù)用(八),服務(wù)器,運(yùn)維,c++,linux,網(wǎng)絡(luò)

返回值: 失敗 - -1,成功 - 檢測到的描述符個數(shù)

linux并發(fā)服務(wù)器 —— IO多路復(fù)用(八),服務(wù)器,運(yùn)維,c++,linux,網(wǎng)絡(luò)

#include <iostream>
#include <cstdio>
#include <arpa/inet.h>
#include <cstdlib>
#include <string.h>
#include <sys/select.h>
#include  <unistd.h>

using namespace std;

int main(){

    // 創(chuàng)建socket
    int lfd = socket(PF_INET , SOCK_STREAM , 0);
    struct sockaddr_in saddr;
    saddr.sin_port = htons(9999);
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = INADDR_ANY;
    // 綁定
    bind(lfd , (struct sockaddr*)&saddr , sizeof(saddr));
    // 監(jiān)聽
    listen(lfd , 8);

    fd_set rdset , tmp;
    FD_ZERO(&rdset);
    FD_SET(lfd , &rdset);
    int maxfd = lfd+1;
    while(1){
        tmp = rdset;
        // 調(diào)用select 系統(tǒng)檢測
        int ret = select(maxfd+1 , &tmp , NULL , NULL , NULL);
        if(ret == -1){
            perror("select");
            exit(-1);
        }
        else if(ret == 0){
            continue;
        }
        else{
            // 檢測到了文件描述符的數(shù)據(jù)發(fā)生了改變
            if(FD_ISSET(lfd , &tmp)){
                // 有客戶端連接進(jìn)來
                struct sockaddr_in caddr;
                socklen_t len = sizeof(caddr);
                int cfd = accept(lfd , (struct sockaddr*)&caddr , &len);
                // 添加進(jìn)去
                FD_SET(cfd , &rdset);

                maxfd = maxfd>cfd?maxfd:cfd+1;
            }
            for(int i = lfd+1 ; i <= maxfd ; i++){
                if(FD_ISSET(i , &tmp)){
                    // 說明客戶端發(fā)來了數(shù)據(jù)
                    char buf[1024];
                    int len = read(i , buf , sizeof(buf));
                    if(len == -1){
                        perror("read");
                        exit(-1);
                    }
                    else if(len == 0){
                        cout<<"client close..."<<endl;
                        close(i);
                        FD_CLR(i,&rdset);
                    }
                    else{
                        cout<<"發(fā)來了數(shù)據(jù):"<<buf<<endl;
                        write(i , buf , strlen(buf)+1);
                    }
                }
            }
        }
    }
    close(lfd);
    return 0;
}

poll

linux并發(fā)服務(wù)器 —— IO多路復(fù)用(八),服務(wù)器,運(yùn)維,c++,linux,網(wǎng)絡(luò)

#include <iostream>
#include <cstdio>
#include <arpa/inet.h>
#include <cstdlib>
#include <string.h>
#include <poll.h>
#include  <unistd.h>

using namespace std;

int main(){

    // 創(chuàng)建socket
    int lfd = socket(PF_INET , SOCK_STREAM , 0);
    struct sockaddr_in saddr;
    saddr.sin_port = htons(9999);
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = INADDR_ANY;
    // 綁定
    bind(lfd , (struct sockaddr*)&saddr , sizeof(saddr));
    // 監(jiān)聽
    listen(lfd , 8);

    // 初始化檢測文件描述符數(shù)組
    struct pollfd fds[1024];
    for(int i = 0 ; i<1024 ; i++){
        fds[i].fd = -1;
        fds[i].events = POLLIN;
    }
    fds[0].fd = lfd;

    int nfds = 0;

    while(1){
        // poll 系統(tǒng)檢測
        int ret = poll(fds , nfds+1 , -1);
        if(ret == -1){
            perror("poll");
            exit(-1);
        }
        else if(ret == 0){
            continue;
        }
        else{
            // 檢測到了文件描述符的數(shù)據(jù)發(fā)生了改變
            if(fds[0].revents & POLLIN){
                // 有客戶端連接進(jìn)來
                struct sockaddr_in caddr;
                socklen_t len = sizeof(caddr);
                int cfd = accept(lfd , (struct sockaddr*)&caddr , &len);
                // 添加進(jìn)去
                for(int i = 1 ; i < 1024 ; i++){
                    if(fds[i].fd == -1){
                        fds[i].fd = cfd;
                        fds[i].events = POLLIN;
                        break;
                    }
                }

                nfds = nfds>cfd?nfds:cfd;
            }
            for(int i = 1 ; i <= nfds ; i++){
                if(fds[i].revents & POLLIN){
                    // 說明客戶端發(fā)來了數(shù)據(jù)
                    char buf[1024];
                    int len = read(fds[i].fd , buf , sizeof(buf));
                    if(len == -1){
                        perror("read");
                        exit(-1);
                    }
                    else if(len == 0){
                        cout<<"client close..."<<endl;
                        close(fds[i].fd);
                        fds[i].fd = -1;
                    }
                    else{
                        cout<<"發(fā)來了數(shù)據(jù):"<<buf<<endl;
                        write(fds[i].fd , buf , strlen(buf)+1);
                    }
                }
            }
        }
    }
    close(lfd);
    return 0;
}

epoll

內(nèi)核,紅黑樹記錄要檢測的文件描述符,避免了用戶態(tài)到內(nèi)核態(tài)的數(shù)據(jù)拷貝開銷;

內(nèi)核,雙鏈表存放數(shù)據(jù)改變的文件描述符

linux并發(fā)服務(wù)器 —— IO多路復(fù)用(八),服務(wù)器,運(yùn)維,c++,linux,網(wǎng)絡(luò)

linux并發(fā)服務(wù)器 —— IO多路復(fù)用(八),服務(wù)器,運(yùn)維,c++,linux,網(wǎng)絡(luò)

linux并發(fā)服務(wù)器 —— IO多路復(fù)用(八),服務(wù)器,運(yùn)維,c++,linux,網(wǎng)絡(luò)

linux并發(fā)服務(wù)器 —— IO多路復(fù)用(八),服務(wù)器,運(yùn)維,c++,linux,網(wǎng)絡(luò)

#include <iostream>
#include <cstdio>
#include <arpa/inet.h>
#include <cstdlib>
#include <string.h>
#include <sys/epoll.h>
#include  <unistd.h>

using namespace std;

int main(){
    // 創(chuàng)建socket
    int lfd = socket(PF_INET , SOCK_STREAM , 0);
    struct sockaddr_in saddr;
    saddr.sin_port = htons(9999);
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = INADDR_ANY;
    // 綁定
    bind(lfd , (struct sockaddr*)&saddr , sizeof(saddr));
    // 監(jiān)聽
    listen(lfd , 8);
    // 創(chuàng)建epoll實例
    int epfd = epoll_create(100);
    // 添加監(jiān)聽文件描述符
    struct epoll_event epev;
    epev.events = EPOLLIN;
    epev.data.fd = lfd;
    epoll_ctl(epfd , EPOLL_CTL_ADD , lfd , &epev);

    struct epoll_event epevs[1024];
    while(1){
        int ret = epoll_wait(epfd , epevs , 1024 , -1);
        if(ret == -1){
            perror("epoll");
            exit(-1);
        }
        cout<<ret<<"個發(fā)生了改變"<<endl;
        for(int i = 0 ; i<ret ; i++){
            int curfd = epevs[i].data.fd;
            if(curfd == lfd){
                // 監(jiān)聽的文件描述符有客戶端連接
                struct sockaddr_in caddr;
                socklen_t len = sizeof(caddr);
                int cfd = accept(lfd , (struct sockaddr*)&caddr , &len);
                epev.events = EPOLLIN;
                epev.data.fd = cfd;
                epoll_ctl(epfd , EPOLL_CTL_ADD , cfd , &epev);
            }
            else{
                // 有數(shù)據(jù)到達(dá)
                char buf[1024];
                int len = read(curfd , buf , sizeof(buf));
                if(len == -1){
                    perror("read");
                    exit(-1);
                }
                else if(len == 0){
                    cout<<"client close..."<<endl;
                    epoll_ctl(epfd , EPOLL_CTL_DEL , curfd , NULL);
                    close(curfd);
                }
                else{
                    cout<<"發(fā)來了數(shù)據(jù):"<<buf<<endl;
                    write(curfd , buf , strlen(buf)+1);
                }
            }
        }
    }
    close(lfd);
    close(epfd);

    return 0;
}

epoll的兩種工作模式

LT模式 - 水平觸發(fā)

默認(rèn)的工作模式,支持block/no-block;,內(nèi)核告訴你一個文件描述符是否就緒了,然后你可以對這個就緒的 fd 進(jìn)行IO操作。如果你不作任何操作,內(nèi)核還是會繼續(xù)通知你

linux并發(fā)服務(wù)器 —— IO多路復(fù)用(八),服務(wù)器,運(yùn)維,c++,linux,網(wǎng)絡(luò)

#include <iostream>
#include <cstdio>
#include <arpa/inet.h>
#include <cstdlib>
#include <string.h>
#include <sys/epoll.h>
#include  <unistd.h>

using namespace std;

int main(){
    // 創(chuàng)建socket
    int lfd = socket(PF_INET , SOCK_STREAM , 0);
    struct sockaddr_in saddr;
    saddr.sin_port = htons(9999);
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = INADDR_ANY;
    // 綁定
    bind(lfd , (struct sockaddr*)&saddr , sizeof(saddr));
    // 監(jiān)聽
    listen(lfd , 8);
    // 創(chuàng)建epoll實例
    int epfd = epoll_create(100);
    // 添加監(jiān)聽文件描述符
    struct epoll_event epev;
    epev.events = EPOLLIN;
    epev.data.fd = lfd;
    epoll_ctl(epfd , EPOLL_CTL_ADD , lfd , &epev);

    struct epoll_event epevs[1024];
    while(1){
        int ret = epoll_wait(epfd , epevs , 1024 , -1);
        if(ret == -1){
            perror("epoll");
            exit(-1);
        }
        cout<<ret<<"個發(fā)生了改變"<<endl;
        for(int i = 0 ; i<ret ; i++){
            int curfd = epevs[i].data.fd;
            if(curfd == lfd){
                // 監(jiān)聽的文件描述符有客戶端連接
                struct sockaddr_in caddr;
                socklen_t len = sizeof(caddr);
                int cfd = accept(lfd , (struct sockaddr*)&caddr , &len);
                epev.events = EPOLLIN;
                epev.data.fd = cfd;
                epoll_ctl(epfd , EPOLL_CTL_ADD , cfd , &epev);
            }
            else{
                // 有數(shù)據(jù)到達(dá)
                char buf[5];
                int len = read(curfd , buf , sizeof(buf));
                if(len == -1){
                    perror("read");
                    exit(-1);
                }
                else if(len == 0){
                    cout<<"client close..."<<endl;
                    epoll_ctl(epfd , EPOLL_CTL_DEL , curfd , NULL);
                    close(curfd);
                }
                else{
                    cout<<"發(fā)來了數(shù)據(jù):"<<buf<<endl;
                    write(curfd , buf , strlen(buf)+1);
                }
            }
        }
    }
    close(lfd);
    close(epfd);

    return 0;
}
ET模式 - 邊沿觸發(fā)

告訴工作方式,只支持no-block,在這種模式下,當(dāng)描述符從未就緒變?yōu)榫途w時,內(nèi)核通過epol告訴你。然后它會假設(shè)你知道文件描述符已經(jīng)就緒,并且不會再為那個文件描述符發(fā)送更多的就緒通知,直到你做了某些操作導(dǎo)致那個文件描述符不再為就緒狀態(tài)了。但是請注意如果一直不對這個 fd 作IO操作,內(nèi)核不會發(fā)送更多的通知 (only once) 。但是緩沖區(qū)中的數(shù)據(jù)不會丟失

linux并發(fā)服務(wù)器 —— IO多路復(fù)用(八),服務(wù)器,運(yùn)維,c++,linux,網(wǎng)絡(luò)

ET模式效率比LT模式高,ET模式下必須使用非阻塞套接口,避免由于一個描述符的阻塞讀/阻塞寫操作把處理多個文件描述符的任務(wù)餓死;

要設(shè)置邊沿觸發(fā)

1. 需要在epoll_event中設(shè)置EPOLLET

2.?

linux并發(fā)服務(wù)器 —— IO多路復(fù)用(八),服務(wù)器,運(yùn)維,c++,linux,網(wǎng)絡(luò)

UDP通信實現(xiàn) - 無需多進(jìn)程/多線程的并發(fā)實現(xiàn)

linux并發(fā)服務(wù)器 —— IO多路復(fù)用(八),服務(wù)器,運(yùn)維,c++,linux,網(wǎng)絡(luò)

linux并發(fā)服務(wù)器 —— IO多路復(fù)用(八),服務(wù)器,運(yùn)維,c++,linux,網(wǎng)絡(luò)

linux并發(fā)服務(wù)器 —— IO多路復(fù)用(八),服務(wù)器,運(yùn)維,c++,linux,網(wǎng)絡(luò)

// server
#include <iostream>
#include <stdio.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
using namespace std;

int main(){
    // 創(chuàng)建socket
    int fd = socket(PF_INET , SOCK_DGRAM , 0);
    if(fd == -1){
        perror("socket");
        exit(-1);
    }
    // 綁定
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(9999);
    addr.sin_addr.s_addr = INADDR_ANY;
    
    int ret = bind(fd ,(struct sockaddr*) &addr , sizeof(addr));
    if(ret == -1){
        perror("bind");
        exit(-1);
    }

    // 通信
    while(1){
        // 接收數(shù)據(jù)
        char buf[128];
        char ip[16];
        struct sockaddr_in caddr;
        socklen_t len = sizeof(caddr);
        int num = recvfrom(fd , buf , sizeof(buf) , 0 , (struct sockaddr*)&caddr , &len);
        string s1 = "IP: ";
        s1 += inet_ntop(AF_INET , &caddr.sin_addr.s_addr , ip , sizeof(ip));
        string s2 = "Port: ";
        s2 += ntohs(caddr.sin_port);
        cout<<s1<<" "<<s2<<endl;
        cout<<"rcv data: "<<buf<<endl;

        sendto(fd , buf , strlen(buf)+1 , 0 , (struct sockaddr*)&caddr , len);
    }

    close(fd);
    return 0;
}
// client
#include <iostream>
#include <stdio.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
using namespace std;

int main(){
    // 創(chuàng)建socket
    int fd = socket(PF_INET , SOCK_DGRAM , 0);
    if(fd == -1){
        perror("socket");
        exit(-1);
    }

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(9999);
    inet_pton(AF_INET , "127.0.0.1" , &addr.sin_addr.s_addr);

    // 通信
    int num = 0;
    socklen_t len = sizeof(addr);
    while(1){
        char buf[128];
        sprintf(buf , "hello 647 %d" , num++);
        sendto(fd , buf , strlen(buf)+1 , 0 , (struct sockaddr*)&addr , len);
        // 接收數(shù)據(jù)
        int num = recvfrom(fd , buf , sizeof(buf) , 0 , NULL , NULL);
        cout<<"rcv data: "<<buf<<endl;

        sleep(1);

    }

    close(fd);
    return 0;
}

廣播和組播 - 只能使用UDP

廣播 - 向子網(wǎng)中多臺計算機(jī)發(fā)送消息,每個廣播消息都包含一個特殊的IP地址,這個IP中子網(wǎng)內(nèi)主機(jī)標(biāo)志部分的二進(jìn)制全部為1;

1. 只能在局域網(wǎng)中使用

2. 客戶端需要綁定服務(wù)器廣播使用的端口,才能接收到廣播消息

linux并發(fā)服務(wù)器 —— IO多路復(fù)用(八),服務(wù)器,運(yùn)維,c++,linux,網(wǎng)絡(luò)

組播 (多播) - 標(biāo)識一組IP接口,是在單播和廣播之間的一種折中方案,多播數(shù)據(jù)包只由對其感興趣的接口接收;

1. 組播可以用于局域網(wǎng)和廣域網(wǎng)

2. 客戶端需要加入多播組才能接收到

linux并發(fā)服務(wù)器 —— IO多路復(fù)用(八),服務(wù)器,運(yùn)維,c++,linux,網(wǎng)絡(luò)

本地套接字通信

作用:用于進(jìn)程間的通信;實現(xiàn)流程和網(wǎng)絡(luò)套接字類似,一般采用TCP的通信流程

linux并發(fā)服務(wù)器 —— IO多路復(fù)用(八),服務(wù)器,運(yùn)維,c++,linux,網(wǎng)絡(luò)文章來源地址http://www.zghlxwxcb.cn/news/detail-704697.html

服務(wù)器端

1. 創(chuàng)建監(jiān)聽的套接字

? ? ? int lfd = socket(AF_UNIX/AF_LOCAL , SOCK_STREAM , 0);

2. 監(jiān)聽套接字綁定本地的套接字文件

? ? ? ? struct sockaddr_un addr;

? ? ? ? bind(lfd, addr, len); // 綁定成功后sun_path中的套接字文件會自動生成

3. 監(jiān)聽

4. 等待并接受客戶端請求

5. 通信

6. 關(guān)閉連接
客戶端

1. 創(chuàng)建通信的套接字

2. 綁定本地IP端口

3. 連接服務(wù)器

4. 通信

5. 關(guān)閉連接
// 服務(wù)端
#include <iostream>
#include <stdio.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/un.h>
using namespace std;

int main(){
    unlink("server.sock");
    // 創(chuàng)建監(jiān)聽套接字
    int lfd = socket(AF_LOCAL , SOCK_STREAM , 0);
    if(lfd == -1){
        perror("socket");
        exit(-1);
    }
    // 綁定本地套接字文件
    struct sockaddr_un addr;
    addr.sun_family = AF_LOCAL;
    strcpy(addr.sun_path , "server.sock");
    int ret = bind(lfd , (struct sockaddr*)&addr , sizeof(addr));
    if(ret == -1){
        perror("bind");
        exit(-1);
    }
    // 監(jiān)聽
    ret = listen(lfd , 100);
    if(ret == -1){
        perror("listen");
        exit(-1);
    }
    // 等待客戶端連接
    struct sockaddr_un caddr;
    socklen_t len = sizeof(caddr);
    int cfd = accept(lfd , (struct sockaddr*)&caddr , &len);
    if(cfd == -1){
        perror("accept");
        exit(-1);
    }

    cout<<"客戶端文件:"<<caddr.sun_path<<endl;
    // 通信
    while(1){
        char buf[128];
        int len = recv(cfd , buf , sizeof(buf) , 0);
        if(len ==  -1){
            perror("recv");
            exit(-1);
        }
        else if(len == 0){
            cout<<"client close..."<<endl;
            break;
        }
        else{
            cout<<"recv data: "<<buf<<endl;
            send(cfd , buf , len , 0);
        }
    }
    close(cfd);
    close(lfd);
    return 0;
}
// 客戶端
#include <iostream>
#include <stdio.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/un.h>
using namespace std;

int main(){
    unlink("client.sock");
    // 創(chuàng)建監(jiān)聽套接字
    int cfd = socket(AF_LOCAL , SOCK_STREAM , 0);
    if(cfd == -1){
        perror("socket");
        exit(-1);
    }
    // 綁定本地套接字文件
    struct sockaddr_un addr;
    addr.sun_family = AF_LOCAL;
    strcpy(addr.sun_path , "client.sock");
    int ret = bind(cfd , (struct sockaddr*)&addr , sizeof(addr));
    if(ret == -1){
        perror("bind");
        exit(-1);
    }
    // 連接服務(wù)器
    struct sockaddr_un saddr;
    saddr.sun_family = AF_LOCAL;
    strcpy(saddr.sun_path , "server.sock");
    ret = connect(cfd , (struct sockaddr*)&saddr , sizeof(saddr));
    if(ret == -1){
        perror("connect");
        exit(-1);
    }

    // 通信
    int num = 0;
    while(1){
        char buf[128];
        sprintf(buf , "hello 647 %d\n" , num++);
        send(cfd , buf , strlen(buf)+1 , 0);

        int len = recv(cfd , buf , sizeof(buf) , 0);
        if(len ==  -1){
            perror("recv");
            exit(-1);
        }
        else if(len == 0){
            cout<<"Server close..."<<endl;
            break;
        }
        else{
            cout<<"recv data: "<<buf<<endl;
        }
        sleep(1);
    }
    close(cfd);
    return 0;
}

到了這里,關(guān)于linux并發(fā)服務(wù)器 —— IO多路復(fù)用(八)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包