精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

bind系統調用背后的端口管理復用

麥辣雞腿堡 ? 來源:技術簡說 ? 作者:董旭 ? 2023-07-31 10:45 ? 次閱讀

很久之前寫過以上:套接字socket的底層來龍去脈、sockfs文件系統的實現,可以作為本文的前置知識進行學習瀏覽。

先來一張本文中核心的一張圖,具體可以看后面文章的解釋:

圖片

本文從socket的bind系統調用進行分析,主要是了解一下bind背后,Linux內核是如何進行端口綁定、如何管理本地眾多的端口號。

先直觀感受bind系統調用背后的端口管理、端口復用

#include < stdio.h >
#include < stdlib.h >
#include < string.h >
#include < unistd.h >
#include < sys/socket.h >
#include < netinet/in.h >
#include < arpa/inet.h >
 
int main(int argc, char *argv[])
{
    int sockfd_one;
    int err_log;
    sockfd_one = socket(AF_INET, SOCK_STREAM, 0); //創建TCP套接字one
    if(sockfd_one < 0)
    {
    perror("sockfd_one");
    exit(-1);
    }
 
    // 設置本地網絡信息
    struct sockaddr_in my_addr;
    bzero(&my_addr, sizeof(my_addr));
    my_addr.sin_family = AF_INET;
    my_addr.sin_port = htons(8000);        // 端口為8000
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
 
    // 綁定,端口為8000
    err_log = bind(sockfd_one, (struct sockaddr*)&my_addr, sizeof(my_addr));
    if(err_log != 0)
    {
        perror("bind sockfd_one");
        close(sockfd_one);        
        exit(-1);
    }
 
    int sockfd_two;
    sockfd_two = socket(AF_INET, SOCK_STREAM, 0);  //創建TCP套接字two
    if(sockfd_two < 0)
    {
        perror("sockfd_two");
        exit(-1);
    }
 
    // 新套接字sockfd_two,繼續綁定8000端口,綁定失敗
    // 因為8000端口已被占用,默認情況下,端口沒有釋放,無法綁定
    err_log = bind(sockfd_two, (struct sockaddr*)&my_addr, sizeof(my_addr));
    if(err_log != 0)
    {
        perror("bind sockfd_two");
        close(sockfd_two);        
        exit(-1);
    }
 
    close(sockfd_one);
    close(sockfd_two);
 
    return 0;
}

圖片

可以看到端口重復綁定導致了第二個套接字創建失敗,我們通過setsockopt系統調用在創建socket后設置端口可復用:

int opt = 1;
// sockfd為需要端口復用的套接字
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(opt));

具體如下:

#include < stdio.h >
#include < stdlib.h >
#include < string.h >
#include < unistd.h >
#include < sys/socket.h >
#include < netinet/in.h >
#include < arpa/inet.h >
 
int main(int argc, char *argv[])
{
    int sockfd_one;
    int err_log;
    sockfd_one = socket(AF_INET, SOCK_STREAM, 0); //創建UDP套接字one
    if(sockfd_one < 0)
    {
    perror("sockfd_one");
    exit(-1);
    }
 
    // 設置本地網絡信息
    struct sockaddr_in my_addr;
    bzero(&my_addr, sizeof(my_addr));
    my_addr.sin_family = AF_INET;
    my_addr.sin_port = htons(8000);        // 端口為8000
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    
    // 在sockfd_one綁定bind之前,設置其端口復用
    int opt = 1;
    setsockopt( sockfd_one, SOL_SOCKET,SO_REUSEADDR, 
                    (const void *)&opt, sizeof(opt) );
 
    // 綁定,端口為8000
    err_log = bind(sockfd_one, (struct sockaddr*)&my_addr, sizeof(my_addr));
    if(err_log != 0)
    {
        perror("bind sockfd_one");
        close(sockfd_one);        
        exit(-1);
    }
 
    int sockfd_two;
    sockfd_two = socket(AF_INET, SOCK_STREAM, 0);  //創建UDP套接字two
    if(sockfd_two < 0)
    {
        perror("sockfd_two");
        exit(-1);
    }
 
    // 在sockfd_two綁定bind之前,設置其端口復用
    opt = 1;
    setsockopt( sockfd_two, SOL_SOCKET,SO_REUSEADDR, 
                    (const void *)&opt, sizeof(opt) );
    
    // 新套接字sockfd_two,繼續綁定8000端口,成功
    err_log = bind(sockfd_two, (struct sockaddr*)&my_addr, sizeof(my_addr));
    if(err_log != 0)
    {
        perror("bind sockfd_two");
        close(sockfd_two);        
        exit(-1);
    }
    printf("two socket create success!n");
    close(sockfd_one);
    close(sockfd_two);
 
    return 0;
}

圖片

如上,兩個套接字綁定同一個端口都創建成功。下面將從bind出發分析bind是如何端口管理、復用的。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 內核
    +關注

    關注

    3

    文章

    1363

    瀏覽量

    40228
  • Linux
    +關注

    關注

    87

    文章

    11230

    瀏覽量

    208937
  • 系統
    +關注

    關注

    1

    文章

    1008

    瀏覽量

    21316
收藏 人收藏

    評論

    相關推薦

    從Linux源碼分析bind系統調用

    眾所周知,一個Server端Socket的建立,需要socket、bind、listen、accept四個步驟。
    的頭像 發表于 10-16 11:08 ?3235次閱讀
    從Linux源碼分析<b class='flag-5'>bind</b><b class='flag-5'>系統</b><b class='flag-5'>調用</b>

    udp_bind這個綁定的端口怎么解除?

    請教下,udp_bind 這個綁定的端口,剛開始是可以的,但是重新綁定時返回錯誤,有什么方法可以在 重新綁定前解除之前的綁定 ?
    發表于 04-22 07:41

    TCP server 不能 bind 80 端口

    后程序只開一個 AP 模式下的 TCP server ,測試。 ?但是發現 80 端口沒法 bind ,錯誤碼是 -98 ,意思是端口已被占用? 換一個其它端口號(比如 12345)就
    發表于 05-14 00:33

    如何去使用STM32的端口復用

    STM32的端口復用映射原理是什么?如何去使用STM32的端口復用呢?
    發表于 11-01 06:45

    端口復用映射原理及GPIO外設復用功能配置過程

    文章目錄端口復用端口復用映射原理原理示意圖映射配置系統功能GPIO外設復用功能配置過程GPIO
    發表于 12-09 07:20

    STM32的端口復用映射原理是什么

    STM32的端口復用映射原理是什么?STM32的端口復用配置過程是怎樣的?
    發表于 12-15 07:03

    什么叫端口復用?如何配置端口

    端口復用和重映射什么叫端口復用?一個引腳既能當IO用又有其他的第二功能那么如何配置端口呢?1.IO口使能2.
    發表于 01-11 08:12

    端口復用概念

    記錄一下,方便以后翻閱~主要內容:1)端口復用;2)端口重映射;官方資料:《STM32中文參考手冊V10》第8章 通用和復用功能IO(GPIO和AFIO)1.
    發表于 01-11 07:43

    Bind源代碼包安裝

    先到官方下載Bind的安裝包 wgetftp://ftp.isc.org/isc/bind9/9.6.0-P1/bind-9.6.0-P1.tar.gz tar xzvf
    發表于 04-04 20:30 ?23次下載

    STM32單片機端口復用端口重映射

    STM32單片機端口復用端口重映射STM32單片機上有很多I/O口,也有很多的內置外設,比如I2C、ADC、DAC、USART等都屬于內置外設。這些內置外設基本都是與I/O口共用管腳的,也就是I
    發表于 12-28 19:23 ?8次下載
    STM32單片機<b class='flag-5'>端口</b><b class='flag-5'>復用</b>和<b class='flag-5'>端口</b>重映射

    STM32學習筆記--端口復用&重映射

    目錄:一、端口復用二、端口重映射一、端口復用? STM32 有很多的內置外設,這些外設的外部引腳都是與 GPIO
    發表于 12-28 19:35 ?14次下載
    STM32學習筆記--<b class='flag-5'>端口</b><b class='flag-5'>復用</b>&重映射

    什么是bind?你真的熟悉bind嗎?

    bind()方法創建一個新的函數,在bind()被調用時,這個新函數的this被指定 bind()的第一個參數,而其余參數將作為新函數的參數,供調用
    的頭像 發表于 07-13 09:56 ?2688次閱讀

    網絡系統調用網絡套接字入口函數

    網絡套接字入口函數 //所有的網絡套接字系統調用函數(socket bind listen connect )都使用一個共同的入口函數:sys_socketcall /* 第一個參數call表示被
    的頭像 發表于 07-24 11:02 ?452次閱讀

    Linux bind的核心執行函數

    bind的核心執行函數 bind系統調用的核心函數調用流程如下: SYSCALL_DEFINE3( bi
    的頭像 發表于 07-31 10:51 ?551次閱讀

    Linux內核分析 bind端口選擇

    bind 傳 遞的地址參數中,port 字段為 0,那么就會自動選擇參數。 如代碼所示,當端口port沒有指定時,調用inet_csk_find_open_port(sk, port): if (!port) { head
    的頭像 發表于 07-31 11:08 ?912次閱讀