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

Linux網(wǎng)絡(luò)編程:socket、客戶(hù)端服務(wù)器端使用socket通信(TCP)

這篇具有很好參考價(jià)值的文章主要介紹了Linux網(wǎng)絡(luò)編程:socket、客戶(hù)端服務(wù)器端使用socket通信(TCP)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

1. socket概念

socket(套接字),用于網(wǎng)絡(luò)中不同主機(jī)間進(jìn)程的通信。

socket是一個(gè)偽文件,包含讀緩沖區(qū)、寫(xiě)緩沖區(qū)。

socket必須成對(duì)出現(xiàn)。

socket可以建立主機(jī)進(jìn)程間的通信,但需要協(xié)議(IPV4、IPV6等)、port端口、IP地址。


2. 客戶(hù)端服務(wù)端socket網(wǎng)絡(luò)通信步驟(TCP)

Linux網(wǎng)絡(luò)編程:socket、客戶(hù)端服務(wù)器端使用socket通信(TCP)

2.1 服務(wù)器端步驟:

????????(1)創(chuàng)建流式socket套接字。

? ? ? ? ? ? ? ? a)此socket套接字一直用于后續(xù)的監(jiān)聽(tīng)連接。

? ? ? ? ? ? ? ? b)socket函數(shù)。

? ? ? ? (2)綁定本機(jī)IP地址和port。

? ? ? ? ? ? ? ? b)bind函數(shù)。

? ? ? ? (3)監(jiān)聽(tīng)。

? ? ? ? ? ? ? ? a)將socket套接字由主動(dòng)變?yōu)楸粍?dòng)。

? ? ? ? ? ? ? ? b)創(chuàng)建未完成連接隊(duì)列、已完成連接隊(duì)列;未完成連接接經(jīng)歷3次握手才變成已完成連接。

? ? ? ? ? ? ? ? c)listen函數(shù)。

? ? ? ? (4)提取。

? ? ? ? ? ? ? ? a)從已完成連接隊(duì)列提取連接,創(chuàng)建一個(gè)新的已連接socket套接字用于和客戶(hù)端通信。

? ? ? ? ? ? ? ? b)accept函數(shù)。

? ? ? ??(5)讀寫(xiě)數(shù)據(jù)。

? ? ? ? (6)關(guān)閉socket。

2.2 客戶(hù)端步驟:

? ? ? ? (1)創(chuàng)建流式socket套接字。

? ? ? ? ? ? ? ? a)socket函數(shù)。

? ? ?? ?(2)連接服務(wù)器。

? ? ? ? ? ? ? ? a)指定服務(wù)器的IP協(xié)議(IPV4或IPV6)、port、IP地址。

? ? ? ? ? ? ? ? b)connect函數(shù)(該函數(shù)包含TCP的三次握手)。

? ? ?? ?(3)讀寫(xiě)數(shù)據(jù)。

? ? ? ? (4)關(guān)閉socket。


3. socket相關(guān)結(jié)構(gòu)體和函數(shù)

3.1 socket相關(guān)結(jié)構(gòu)體

(1)IPV4套接字結(jié)構(gòu)體

#include<netinet/in.h>

struct sockaddr_in {
    sa_family_t    sin_family; /* 協(xié)議:AF_INET */
    in_port_t      sin_port;   /* 端口 */
    struct in_addr sin_addr;   /* IP地址 */
};

/* Internet address. */
struct in_addr {
    uint32_t       s_addr;     /* IP地址的網(wǎng)絡(luò)字節(jié)序 */
};

(2)IPV6套接字結(jié)構(gòu)體

#include<netinet/in6.h>

struct sockaddr_in6 {
    sa_family_t     sin6_family;   /* AF_INET6 */
    in_port_t       sin6_port;     /* port number */
    uint32_t        sin6_flowinfo; /* IPv6 flow information */
    struct in6_addr sin6_addr;     /* IPv6 address */
    uint32_t        sin6_scope_id; /* Scope ID (new in 2.4) */
};

struct in6_addr {
    unsigned char   s6_addr[16];   /* IPv6 address */
};

(3)通用套接字結(jié)構(gòu)體

為了接口通用,出現(xiàn)通用套接字結(jié)構(gòu)體。

#include<sys/socket.h>

struct sockaddr {
    sa_family_t sa_family; /* AF_INET 或 AF_INET6 */
    char sa_data[14]; /* address data */
};

3.2 socket相關(guān)函數(shù)

(1)?socke函數(shù):創(chuàng)建套接字

#include<sys/socket.h>

int socket(int domain, int type, int protocol);
/*
功能:
    創(chuàng)建套接字
參數(shù):
    domain:
        AF_INET
        AF_INET6
        等等
    type:
        SOCK_STREAM:TCP流式套接字
        SOCK_DGRAM:UDP報(bào)式套接字
        SOCK_RAW:組包更多
        等等
    protocol:0,自動(dòng)填充
返回值:
    成功:文件描述符
    失?。?1
*/

(2)connect函數(shù):客戶(hù)端連接服務(wù)器

#include<sys/socket.h>

int connect(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
/*
功能:
    連接服務(wù)器
參數(shù):
    sockfd:套接字文件描述符
    addr:IPV4套接字結(jié)構(gòu)體地址 強(qiáng)轉(zhuǎn)為通用套接字結(jié)構(gòu)體
              包含目的主機(jī)的IP和port
    addrlen:IPV4套接字結(jié)構(gòu)體大小
返回值:
    成功:0
    失?。?1,并設(shè)置errno
        EACCES:權(quán)限不足或被防火墻拒絕
        EADDRINUSE:本地地址已被其他套接字使用
        ECONNREFUSED:遠(yuǎn)程主機(jī)拒絕連接
        ETIMEDOUT:連接超時(shí)
*/

(3)bind函數(shù):服務(wù)器端綁定自己固定的IP和port

#include<sys/socket.h>

int bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
/*
功能:
    給套接字sockfd綁定固定的的IP地址和port
參數(shù):
    sockfd:套接字文件描述符
    addr:IPV4套接字結(jié)構(gòu)體地址
    addrlen:IPV4套接字結(jié)構(gòu)體大小
返回值:
    成功:0
    失?。?1
*/

(4)listen函數(shù):服務(wù)器端監(jiān)聽(tīng)是否有連接請(qǐng)求

#include<sys/socket.h>

int listen(int sockfd, int backlog);
/*
功能:
    監(jiān)聽(tīng)是否有客戶(hù)端請(qǐng)求連接
參數(shù):
    sockfd:套接字文件描述符
    backlog:已完成連接數(shù)量與未完成連接數(shù)量之和的最大值,一般寫(xiě)128
返回值:
    成功:0
    失?。?1
*/

(5)accept函數(shù):?從已完成連接隊(duì)列提取連接

#include<sys/socket.h>

int accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen);
/*
功能:
    從已完成連接隊(duì)列提取連接
參數(shù):
    sockfd:套接字文件描述符
    addr:IPV4套接字結(jié)構(gòu)體地址,以獲取的客戶(hù)端IP和port信息
    addrlen:存儲(chǔ)IPV4套接字結(jié)構(gòu)體大小的變量的地址。
返回值:
    成功:新連接socket的文件描述符
    失敗:-1
*/

3.3 socket通信示例

(1)TCP客戶(hù)端連接服務(wù)器示例:

#include<arpa/inet.h>
#include<stdio.h>
#include<sys/socket.h>
#include<unistd.h>

int main() {

    /* 1.創(chuàng)建socket */
    int sock_fd;
    sock_fd = socket(AF_INET, SOCK_STREAM, 0);

    /* 2.連接服務(wù)器 */
    // IPV4套接字結(jié)構(gòu)體
    struct sockaddr_in addr;
    // IPV4
    addr.sin_family = AF_INET;
    // 服務(wù)器的port,轉(zhuǎn)為網(wǎng)絡(luò)字節(jié)序
    addr.sin_port = htons(8888);
    // 服務(wù)器IP地址,轉(zhuǎn)為網(wǎng)絡(luò)字節(jié)序存入addr.sin_addr.s_addr
    inet_pton(AF_INET, "192.168.0.11", &addr.sin_addr.s_addr);
    // 連接
    connect(sock_fd, (struct sockaddr*)&addr, sizeof(addr));

    /* 3.讀寫(xiě)數(shù)據(jù) */
    char buf[1024] = "";
    while (1) {
        int n = read(STDIN_FILENO, buf, sizeof(buf));  // 從終端讀入buf
        write(sock_fd, buf, n);
        n = read(sock_fd, buf, sizeof(buf));
        write(STDOUT_FILENO, buf, n);
    }

    /* 4.關(guān)閉 */
    close(sock_fd);

    return 0;
}

運(yùn)行結(jié)果:

Linux網(wǎng)絡(luò)編程:socket、客戶(hù)端服務(wù)器端使用socket通信(TCP)


(2)TCP服務(wù)器端示例:

#include<stdio.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>

int main(int argc, const char* argv[]) {

    /* 1.創(chuàng)建socket */
    int lfd = socket(AF_INET, SOCK_STREAM, 0);

    /* 2.綁定本機(jī)IP地址和port */
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8000);
    // INADDR_ANY為0,表示綁定通配地址,即本地所有IP地址
    // addr.sin_addr.s_addr = INADDR_ANY; 
    inet_pton(AF_INET, "192.168.124.128", &addr.sin_addr.s_addr);
    int ret = bind(lfd, (struct sockaddr*)&addr, sizeof(addr));
    if(ret < 0) {
        perror("bind");
        exit(0);
    }

    /* 3.監(jiān)聽(tīng) */
    listen(lfd, 128);

    /* 4.提取 */
    struct sockaddr_in cliaddr;
    socklen_t len = sizeof(cliaddr);
    int cfd = accept(lfd, (struct sockaddr*)&cliaddr, &len);
    char ip[16] = "";
    printf("新連接到來(lái)!IP:%s, port:%d\n", 
                inet_ntop(AF_INET, &(cliaddr.sin_addr.s_addr), ip, 16), 
                ntohs(cliaddr.sin_port));

    /* 5.讀寫(xiě) */
    char buf[1024] = "";
    while (1) {
        bzero(buf, sizeof(buf));
        int n = read(STDIN_FILENO, buf, sizeof(buf));  // 從終端讀入buf
        write(cfd, buf, n);
        n = read(cfd, buf, sizeof(buf));
        printf("%s", buf);
    }

    /* 6.關(guān)閉 */
    close(lfd);
    close(cfd);

    return 0;
}

運(yùn)行結(jié)果:

Linux網(wǎng)絡(luò)編程:socket、客戶(hù)端服務(wù)器端使用socket通信(TCP)

注意:服務(wù)器進(jìn)程被殺死,其占用的端口不會(huì)立即釋放,再次連接會(huì)出現(xiàn)如下錯(cuò)誤:

Linux網(wǎng)絡(luò)編程:socket、客戶(hù)端服務(wù)器端使用socket通信(TCP)

因?yàn)橄到y(tǒng)防止短時(shí)間內(nèi)頻繁開(kāi)關(guān)相同的端口而將端口設(shè)置為T(mén)IME_WAIT狀態(tài)(一般為2MSL,MSL一般為30s),因此TIME_WAIT大概持續(xù)60s;過(guò)了TIME_WAIT狀態(tài)才可使用該端口。

若要立即使用該端口,可使用端口復(fù)用機(jī)制。


4. 補(bǔ)充:

4.1 recv和send

讀寫(xiě)時(shí),除了使用read、write函數(shù),還可使用recv和send函數(shù),用法類(lèi)似于read和write,flags默認(rèn)寫(xiě)0即可:

#include<sys/types.h>
#include<sys/socket.h>

ssize_t recv(int sockfd, void* buf, size_t len, int flags);

ssize_t send(int sockfd, const void* buf, size_t len, int flags);

4.2 socket包裹函數(shù)

將socket編程常用函數(shù)中的錯(cuò)誤判斷等封裝為函數(shù),使用更方便:?mayueming1/socket-wrap-func: socket常用的包裹函數(shù) (github.com)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-500003.html

到了這里,關(guān)于Linux網(wǎng)絡(luò)編程:socket、客戶(hù)端服務(wù)器端使用socket通信(TCP)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

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

相關(guān)文章

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包