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

Linux系統(tǒng)應(yīng)用編程(五)Linux網(wǎng)絡(luò)編程(上篇)

這篇具有很好參考價值的文章主要介紹了Linux系統(tǒng)應(yīng)用編程(五)Linux網(wǎng)絡(luò)編程(上篇)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

Linux系統(tǒng)應(yīng)用編程(五)Linux網(wǎng)絡(luò)編程(上篇)

一、網(wǎng)絡(luò)基礎(chǔ)

1.兩個網(wǎng)絡(luò)模型和常見協(xié)議

(1)OSI七層模型(物數(shù)網(wǎng)傳會表應(yīng))
  • 物理層、數(shù)據(jù)鏈路層、網(wǎng)絡(luò)層、傳輸層、會話層、表示層、應(yīng)用層(自下到上)
(2)TCP/IP四層模型(網(wǎng)網(wǎng)傳應(yīng))
  • 網(wǎng)絡(luò)接口層(鏈路層)、網(wǎng)絡(luò)層、傳輸層、應(yīng)用層
(3)常見網(wǎng)絡(luò)協(xié)議所屬層

Linux系統(tǒng)應(yīng)用編程(五)Linux網(wǎng)絡(luò)編程(上篇)

2.字節(jié)序

(1)兩種字節(jié)序

Linux系統(tǒng)應(yīng)用編程(五)Linux網(wǎng)絡(luò)編程(上篇)

(2)字節(jié)序轉(zhuǎn)換函數(shù)

Linux系統(tǒng)應(yīng)用編程(五)Linux網(wǎng)絡(luò)編程(上篇)

3.TCP通信時序(三次握手、四次揮手)

以下均為簡述,僅針對面試時能夠有東西掰扯

(1)什么是"三次握手"和"四次揮手"
  • "三次握手"意思是TCP客戶端和服務(wù)器建立連接需要3次通信的過程;
  • "四次揮手"意思是TCP客戶端和服務(wù)器斷開連接需要4次通信的過程。
(2)"三次握手"和"四次揮手"的過程
  • “三次握手”:客戶端主動向服務(wù)器發(fā)起連接請求,也就是發(fā)送建立連接的標志位SYN,服務(wù)器收到該請求同意后回復(fù)一個SYN和ACK(應(yīng)答標志位),表示服務(wù)器收到客戶端的連接請求,客戶端收到服務(wù)器SYN+ACK后,再向服務(wù)器發(fā)送ACK應(yīng)答標志位,等到服務(wù)器收到后就完成了三次握手建立連接。

  • “四次揮手”:一般由客戶端主動斷開,發(fā)送FIN標志位給服務(wù)器后,客戶端處于半關(guān)閉狀態(tài)(也就是只能接收服務(wù)器數(shù)據(jù),而不能發(fā)送數(shù)據(jù));服務(wù)器接收到FIN后回復(fù)客戶端ACK應(yīng)答;接著服務(wù)器也會發(fā)送FIN給客戶端,同時服務(wù)器也進入半關(guān)閉狀態(tài),直到客戶端回復(fù)ACK給到服務(wù)器,連接斷開。

    實際上,套接字在內(nèi)核中實現(xiàn)了讀、寫兩個緩沖區(qū),半關(guān)閉就是關(guān)閉了寫緩沖區(qū)

  • 【補充】上面說到客戶端處于半關(guān)閉,為什么可以在第四揮手時給服務(wù)器回復(fù)ACK?

    半關(guān)閉只是關(guān)閉socket中的寫緩沖區(qū),此時客戶端和服務(wù)器的socket連接并沒有關(guān)閉,因此,在半關(guān)閉狀態(tài)下,客戶端仍然可以通過已經(jīng)建立好的TCP連接給服務(wù)器回復(fù)ACK確認包來完成四次揮手的過程。

(3)為什么斷開連接需要"四次揮手"
  • 導(dǎo)致TCP連接關(guān)閉需要四次揮手的直接原因:半關(guān)閉
  • 為什么:為了確保雙方在關(guān)閉連接之前都能夠完成必要的操作,并盡可能地減少因網(wǎng)絡(luò)不穩(wěn)定性造成的影響,以保證數(shù)據(jù)的可靠性。

二、Socket網(wǎng)絡(luò)編程

1.網(wǎng)絡(luò)地址結(jié)構(gòu)體

Linux系統(tǒng)應(yīng)用編程(五)Linux網(wǎng)絡(luò)編程(上篇)

2.Socket編程API

(1)創(chuàng)建套接字socket( )

Linux系統(tǒng)應(yīng)用編程(五)Linux網(wǎng)絡(luò)編程(上篇)

(2)綁定地址bind( )

Linux系統(tǒng)應(yīng)用編程(五)Linux網(wǎng)絡(luò)編程(上篇)

(3)設(shè)置監(jiān)聽listen( )

Linux系統(tǒng)應(yīng)用編程(五)Linux網(wǎng)絡(luò)編程(上篇)

(4)等待連接accept( )

Linux系統(tǒng)應(yīng)用編程(五)Linux網(wǎng)絡(luò)編程(上篇)

(5)發(fā)起連接connect( )

Linux系統(tǒng)應(yīng)用編程(五)Linux網(wǎng)絡(luò)編程(上篇)

(6)設(shè)置地址復(fù)用setsockopt( )

Linux系統(tǒng)應(yīng)用編程(五)Linux網(wǎng)絡(luò)編程(上篇)

三、案例程序

本案例參考于抖音up@小飛有點東西《python全棧高級篇》,up的python視頻很nb;以下為筆者學(xué)習后用C語言描述的版本

1.簡易"模擬Linux終端"v1.0

【開發(fā)環(huán)境】 ubuntu22.04、CLion

【核心技術(shù)】 TCP網(wǎng)絡(luò)編程、服務(wù)器多進程/多線程并發(fā)、解決粘包問題

【案例描述】 client接入server后,通過命令行輸入Linux命令,由server執(zhí)行后的結(jié)果發(fā)送給client。

【v1.0代碼】 多進程實現(xiàn)服務(wù)器并發(fā),父進程回收子進程避免僵尸進程,子進程和客戶端通信。

至此,程序還有BUG未解決——粘包問題

#include "temp.h"   //many head files in it

/* 服務(wù)器socket結(jié)構(gòu)體 */
struct ServerSocket{
    int sockfd;       //服務(wù)器socket文件描述符
    void (* socketBind)(int ,char *,int);   //給sockfd綁定地址函數(shù)
    void (* serverListen)(int , int);       //監(jiān)聽sockfd函數(shù)
    struct ClientSocket (* serverAccept)(int);  //建立連接函數(shù)
};

/* 客戶端socket結(jié)構(gòu)體 */
struct ClientSocket{
    int cfd;    //建立連接的socket文件描述符
    char ip[32];    //客戶端IP
    int port;   //客戶端Port
};

/* 服務(wù)器socket綁定地址信息函數(shù)實現(xiàn) */
void socketBind(int sockfd,char *ip,int port){
    int retn;
    /* 初始化地址結(jié)構(gòu)體sockaddr_in */
    struct sockaddr_in serAddr = {
            .sin_port = htons(port),
            .sin_family = AF_INET
    };
    inet_pton(AF_INET,ip,&serAddr.sin_addr.s_addr);
    /* 調(diào)用bind()綁定地址 */
    retn = bind(sockfd,(struct sockaddr *)&serAddr,sizeof(serAddr));
    if(retn == -1){
        perror("bind");
        exit(-1);
    }
    printf("<Server> bind address: %s:%d\n",ip,port);
}

/* 服務(wù)器socket監(jiān)聽函數(shù)實現(xiàn) */
void serverListen(int sockfd,int n){
    int retn;
    retn = listen(sockfd,n);
    if(retn == -1){
        perror("listen");
        exit(-1);
    }
    printf("<Server> listening...\n");
}

/* 服務(wù)器建立連接函數(shù)實現(xiàn),返回值為struct ClientSocket結(jié)構(gòu)體 *
 * (包括建立連接的socket文件描述符、客戶端信息) */
struct ClientSocket serverAccept(int sockfd){
    struct sockaddr_in clientAddr;
    socklen_t addrLen = sizeof(clientAddr);
    struct ClientSocket c_socket;
    c_socket.cfd = accept(sockfd,(struct sockaddr *)&clientAddr,&addrLen);
    if(c_socket.cfd == -1){
        perror("accept");
        exit(-1);
    }else{
        c_socket.port = ntohs(clientAddr.sin_port);
        inet_ntop(AF_INET,&clientAddr.sin_addr.s_addr,c_socket.ip,sizeof(clientAddr));
        return c_socket;
    }
}

/* 信號處理函數(shù):回收子進程 */
void waitChild(int signum){
    wait(NULL);
}

int main(){
    /* 初始化服務(wù)器socket */
    struct ServerSocket ss = {
            .serverAccept = serverAccept,
            .socketBind = socketBind,
            .serverListen = serverListen
    };
    /* 設(shè)置端口復(fù)用 */
    int optval = 1;
    setsockopt(ss.sockfd,SOL_SOCKET,SO_REUSEPORT,&optval,sizeof(optval));

    ss.sockfd = socket(AF_INET,SOCK_STREAM,0);
    ss.socketBind(ss.sockfd,"192.168.35.128",8880);
    ss.serverListen(ss.sockfd,128);
    
    /* 多進程實現(xiàn)服務(wù)器并發(fā) */
    struct ClientSocket cs; //客戶端socket
    pid_t pid = 1;
    int nread;
    while(1){   //循環(huán)等待客戶端接入
        cs = ss.serverAccept(ss.sockfd);
        printf("<Server> client connected.(%s:%d)\n",cs.ip,cs.port);
        pid = fork();   //創(chuàng)建父子進程
        if(pid > 0){    //父進程
            close(cs.cfd);  //關(guān)閉通信的套接字
            signal(SIGCHLD,waitChild);  //注冊信號
            continue;
        }else if(pid == 0){     //子進程
            close(ss.sockfd);  //關(guān)閉建立連接的socket
            while(1){
                char *writeBuff = (char *) malloc(2048);    //寫buff
                char *readBuff = (char *) malloc(128);      //讀buff
                FILE *buffFile = NULL;          //文件流
                while(1) {
                    nread = read(cs.cfd, readBuff, 128);   //讀取客戶端發(fā)過來的命令
                    /* 對read判空,防止客戶端退出后一直收空數(shù)據(jù)的死循環(huán) */
                    if (nread == 0) {
                        printf("<server> client disconnected (%s:%d)\n",cs.ip,cs.port);
                        break;
                    }
                    /* 執(zhí)行客戶端發(fā)過來的命令 */
                    buffFile = popen(readBuff, "r");
                    fread(writeBuff, 2048, 1, buffFile);    //命令執(zhí)行成功結(jié)果讀取到writeBuff
                    if (strlen(writeBuff) == 0) {
                        write(cs.cfd, "\n", 1);
                    }else{
                        write(cs.cfd, writeBuff, strlen(writeBuff));   //結(jié)果寫回給客戶端
                    }
                    /* 清空緩存數(shù)據(jù),關(guān)閉流 */
                    memset(writeBuff, '\0', strlen(writeBuff));
                    memset(readBuff, '\0', strlen(readBuff));
                    pclose(buffFile);
                }
                return 0;
            }
        }else{
            perror("fork");
            exit(-1);
        }
    }
}

Linux系統(tǒng)應(yīng)用編程(五)Linux網(wǎng)絡(luò)編程(上篇)

Linux系統(tǒng)應(yīng)用編程(五)Linux網(wǎng)絡(luò)編程(上篇)

2.TCP粘包問題

(1)粘包問題引入
  • v1.0的服務(wù)器代碼,只執(zhí)行了ls、dir執(zhí)行結(jié)果較短的命令,看似沒有BUG,但是如果執(zhí)行的是像ps -aux命令結(jié)果較長的,就可以發(fā)現(xiàn),由于返回的結(jié)果較長,客戶端一次讀取并沒有讀取完(或者讀取太快、緩存太?。?,當下一條命令執(zhí)行后,結(jié)果就會和上一條命令沒有讀取完的內(nèi)容連在一起。如圖:

Linux系統(tǒng)應(yīng)用編程(五)Linux網(wǎng)絡(luò)編程(上篇)

  • 針對客戶端讀取數(shù)據(jù)太快,或客戶端設(shè)置的緩存太小,雖然我們在代碼中,用延時避免讀取數(shù)據(jù)太快、設(shè)置較大的緩存區(qū)可以一定程度避免粘包問題,但是這種解決方法并不好,延時難免影響用戶體驗,過大的緩存區(qū)也不切實際。所以,需要從其他角度解決TCP的粘包問題。
(2)TCP粘包產(chǎn)生原因
  • TCP協(xié)議基于字節(jié)流傳輸數(shù)據(jù),并不是基于消息,數(shù)據(jù)類似水流傳輸著,數(shù)據(jù)之間難以區(qū)分,所以不可避免出現(xiàn)將多個獨立的數(shù)據(jù)包粘成一個數(shù)據(jù)包的情況;
  • TCP為了避免網(wǎng)絡(luò)擁塞,減少網(wǎng)絡(luò)負載而設(shè)計的底層優(yōu)化算法Nagle算法,通過將多個小數(shù)據(jù)包合并成一個大數(shù)據(jù)包進行發(fā)送,以減少網(wǎng)絡(luò)流量和傳輸延遲。當有大量小數(shù)據(jù)包需要發(fā)送時,Nagle算法會將這些數(shù)據(jù)包先緩存起來,并在緩存區(qū)中嘗試組裝成一個更大的數(shù)據(jù)包再進行發(fā)送。所以如果接收方不能及時地處理接收到的數(shù)據(jù)包,或者發(fā)送方的緩存區(qū)未被填滿,那么就會導(dǎo)致TCP粘包問題的產(chǎn)生。
(3)解決粘包問題
  • 固定數(shù)據(jù)包的長度:每次發(fā)送讀取都固定大小
  • 在數(shù)據(jù)頭部加入數(shù)據(jù)的總長度:接收方先讀取消息頭中的長度信息,再根據(jù)長度信息讀取對應(yīng)長度的數(shù)據(jù)(實際上也就是<自定義協(xié)議>)
  • 特殊分割符:使用特殊的分割符(如\n或者\r\n)來分割每條數(shù)據(jù)
(4)自定義協(xié)議
  • 自定義協(xié)議通常包含兩部分內(nèi)容:

    1. 消息頭:用于描述數(shù)據(jù)包的基本信息,如數(shù)據(jù)包類型、數(shù)據(jù)包長度等。

      例如:<文件傳輸>頭部可以包括文件類型、文件的md5值、文件的大小等

    2. 消息體:用于存儲具體的數(shù)據(jù),如文本、圖片、音頻等。

  • 設(shè)計自定義協(xié)議時,需要遵循以下幾個原則:

    1. 協(xié)議必須是可擴展的,能夠容易地添加新的消息類型或字段。
    2. 消息的格式必須明確并符合規(guī)范,可以使用固定長度、分隔符、標記等方式來辨別消息的開始和結(jié)束。
    3. 在消息頭中要包含足夠的元信息,能夠讓接收方對消息進行正確的處理。
    4. 協(xié)議設(shè)計必須考慮網(wǎng)絡(luò)上的安全問題,避免數(shù)據(jù)泄露和信息篡改等風險。
  • 自定義協(xié)議通常用于特定領(lǐng)域的應(yīng)用,如游戲開發(fā)、嵌入式系統(tǒng)、金融交易等場景。自定義協(xié)議的設(shè)計和實現(xiàn)需要結(jié)合具體場景進行考慮,需要對網(wǎng)絡(luò)協(xié)議有一定的了解,并且需要注意協(xié)議的可靠性、可擴展性和安全性等問題。

3.簡易"模擬Linux終端"v2.0

【Server v2.0】 通過在數(shù)據(jù)頭部加入數(shù)據(jù)的總長度,客戶端先讀取數(shù)據(jù)的總長度,決定本次讀取的大小,解決粘包問題

#include "temp.h"   //many head files in it

/* 服務(wù)器socket結(jié)構(gòu)體 */
struct ServerSocket{
    int sockfd;       //服務(wù)器socket文件描述符
    void (* socketBind)(int ,char *,int);   //給sockfd綁定地址函數(shù)
    void (* serverListen)(int , int);       //監(jiān)聽sockfd函數(shù)
    struct ClientSocket (* serverAccept)(int);  //建立連接函數(shù)
};

/* 客戶端socket結(jié)構(gòu)體 */
struct ClientSocket{
    int cfd;    //建立連接的socket文件描述符
    char ip[32];    //客戶端IP
    int port;   //客戶端Port
};

/* 數(shù)據(jù)結(jié)構(gòu)體 */
struct Data{
    int headerLenth;	//數(shù)據(jù)頭部長度
    long dataLenth;	//數(shù)據(jù)長度(命令執(zhí)行成功的結(jié)果長度)
    char *dataBody;	//數(shù)據(jù)正文(命令執(zhí)行成功的結(jié)果)
};

/* 服務(wù)器socket綁定地址信息函數(shù)實現(xiàn) */
void socketBind(int sockfd,char *ip,int port){
    int retn;
    /* 初始化地址結(jié)構(gòu)體sockaddr_in */
    struct sockaddr_in serAddr = {
            .sin_port = htons(port),
            .sin_family = AF_INET
    };
    inet_pton(AF_INET,ip,&serAddr.sin_addr.s_addr);
    /* 調(diào)用bind()綁定地址 */
    retn = bind(sockfd,(struct sockaddr *)&serAddr,sizeof(serAddr));
    if(retn == -1){
        perror("bind");
        exit(-1);
    }
    printf("<Server> bind address: %s:%d\n",ip,port);
}

/* 服務(wù)器socket監(jiān)聽函數(shù)實現(xiàn) */
void serverListen(int sockfd,int n){
    int retn;
    retn = listen(sockfd,n);
    if(retn == -1){
        perror("listen");
        exit(-1);
    }
    printf("<Server> listening...\n");
}

/* 服務(wù)器建立連接函數(shù)實現(xiàn),返回值為struct ClientSocket結(jié)構(gòu)體 *
 * (包括建立連接的socket文件描述符、客戶端信息) */
struct ClientSocket serverAccept(int sockfd){
    struct sockaddr_in clientAddr;
    socklen_t addrLen = sizeof(clientAddr);
    struct ClientSocket c_socket;
    c_socket.cfd = accept(sockfd,(struct sockaddr *)&clientAddr,&addrLen);
    if(c_socket.cfd == -1){
        perror("accept");
        exit(-1);
    }else{
        c_socket.port = ntohs(clientAddr.sin_port);
        inet_ntop(AF_INET,&clientAddr.sin_addr.s_addr,c_socket.ip,sizeof(clientAddr));
        return c_socket;
    }
}

/* 信號處理函數(shù):回收子進程 */
void waitChild(int signum){
    wait(NULL);
}

/* 處理數(shù)據(jù)的函數(shù),返回值為struct Data */
struct Data dataDealWith(FILE *file){
    char *tempBuff = (char *)malloc(8192);		//臨時buff
    long readBytes = 0;			//讀取的字節(jié)數(shù)
    struct Data data = {
            .dataLenth = 0,
            .dataBody = NULL
    };
    /* 處理數(shù)據(jù):計算數(shù)據(jù)正文大小,并保留管道中的數(shù)據(jù)到data.dataBody(需要動態(tài)調(diào)整大小) */
    while(fread(tempBuff,sizeof(char),8192,file) > 0){
        readBytes = strlen(tempBuff)+1;   //讀到臨時buff的字節(jié)數(shù)
        data.dataLenth += readBytes;      //數(shù)據(jù)長度累加readBytes
        if(data.dataLenth <= readBytes){	//如果數(shù)據(jù)長度小于設(shè)置的tempBuff大小,直接拷貝
            data.dataBody = (char *)malloc(readBytes);	
            strcpy(data.dataBody,tempBuff);
        }else if(data.dataLenth > readBytes){	//如果數(shù)據(jù)長度大于設(shè)置的tempBuff大小,擴容后拼接到后面
            data.dataBody = realloc(data.dataBody,data.dataLenth);
            strcat(data.dataBody,tempBuff);
        }
        data.dataBody[strlen(data.dataBody)+1] = '\0';
        memset(tempBuff,'\0',8192);
    }
    free(tempBuff); //釋放臨時buff
    return data;
}

int main(){

    /* 初始化服務(wù)器socket */
    struct ServerSocket ss = {
            .serverAccept = serverAccept,
            .socketBind = socketBind,
            .serverListen = serverListen
    };

    /* 設(shè)置端口復(fù)用 */
    int optval = 1;
    setsockopt(ss.sockfd,SOL_SOCKET,SO_REUSEPORT,&optval,sizeof(optval));

    ss.sockfd = socket(AF_INET,SOCK_STREAM,0);
    ss.socketBind(ss.sockfd,"192.168.35.128",8880);
    ss.serverListen(ss.sockfd,128);

    /* 多進程實現(xiàn)服務(wù)器并發(fā) */
    struct ClientSocket cs; //客戶端socket
    pid_t pid = 1;
    int nread;
    while(1){   //循環(huán)等待客戶端接入
        cs = ss.serverAccept(ss.sockfd);
        printf("<Server> client connected.(%s:%d)\n",cs.ip,cs.port);
        pid = fork();   //創(chuàng)建父子進程
        if(pid > 0){    //父進程
            close(cs.cfd);  //關(guān)閉通信的套接字
            signal(SIGCHLD,waitChild);  //注冊信號
            continue;
        }else if(pid == 0){     //子進程
            close(ss.sockfd);  //關(guān)閉建立連接的socket
            while(1){
                char *readBuff = (char *) malloc(128);      //讀buff
                FILE *buffFile = NULL;          //文件流
                struct Data data;
                char head[8];
                while(1) {
                    nread = read(cs.cfd, readBuff, 128);   //讀取客戶端發(fā)過來的命令
                    /* 對read判空,防止客戶端退出后一直收空數(shù)據(jù)的死循環(huán) */
                    if (nread == 0) {
                        printf("<server> client disconnected (%s:%d)\n",cs.ip,cs.port);
                        break;
                    }
                    /* 執(zhí)行客戶端發(fā)過來的命令 */
                    buffFile = popen(readBuff, "r");    //命令執(zhí)行成功結(jié)果讀取到writeBuff
                    data = dataDealWith(buffFile);
                    sprintf(head,"%ld",data.dataLenth);
                    write(cs.cfd,head, 8);
                    write(cs.cfd,data.dataBody,data.dataLenth);
                    memset(readBuff, '\0', strlen(readBuff));
                    memset(&data,0,sizeof(data));
                    pclose(buffFile);
                }
                exit(1);
            }
        }else{
            perror("fork");
            exit(-1);
        }
    }
}

【Client v2.0】

#include "temp.h"

int main(){
    int fd = socket(AF_INET,SOCK_STREAM,0);
    if(fd == -1){
        perror("socket");
        exit(-1);
    }

    struct sockaddr_in serAddr = {
            .sin_family = AF_INET,
            .sin_port = htons(8880)
    };
    inet_pton(AF_INET,"192.168.35.128",&serAddr.sin_addr.s_addr);

    int retn = connect(fd,(struct sockaddr *)&serAddr,sizeof(serAddr) );
    if(retn == -1){
        perror("connect");
        exit(-1);
    }

    char *writeBuff = (char *)malloc(128);
    char *readBuff = (char *)malloc(1024);
    char *header = (char *)malloc(8);
    int nread = 0;
    int dataLength = 0;
    while(1){
        printf("user@ubuntu-22.04:");
        fgets(writeBuff,128,stdin);
        if(*writeBuff == ' ' || *writeBuff == '\n'){
            continue;
        }
        write(fd,writeBuff, strlen(writeBuff));
        read(fd,header,8);
        if(atol(header) == 0)continue;
        printf("header:%ld\n", atol(header));
        while(dataLength <= atol(header)){
            read(fd,readBuff,1024);
            dataLength += strlen(readBuff)+1;
            printf("%s",readBuff);
            memset(readBuff,'\0', 1024);
            if(dataLength >= atol(header)){
                dataLength = 0;
                break;
            }
        }
        memset(header,'\0', strlen(header));
        memset(writeBuff,'\0', strlen(writeBuff));
        printf("done\n");
    }
}

Linux系統(tǒng)應(yīng)用編程(五)Linux網(wǎng)絡(luò)編程(上篇)
Linux系統(tǒng)應(yīng)用編程(五)Linux網(wǎng)絡(luò)編程(上篇)
Linux系統(tǒng)應(yīng)用編程(五)Linux網(wǎng)絡(luò)編程(上篇)文章來源地址http://www.zghlxwxcb.cn/news/detail-424762.html

到了這里,關(guān)于Linux系統(tǒng)應(yīng)用編程(五)Linux網(wǎng)絡(luò)編程(上篇)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

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

相關(guān)文章

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包