Linux C 網絡_綁定套接字函數

在創立了套接字之後需要將本地地址和套接字綁定在一起,此時可以調用 bind 函數。

#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

參數 sockfd 是使用 socket 函數創建的套接字對應的套接字描述符,addr 是本地地址,addrlen 是套接字對應的地址結構長度;如果 bind 函數執行成功,則返回 0,否則返回 -1。

在網絡通信中服務器和客戶端都可以使用 bind 函數來設置套接字地址,通常來說有以下5種模式:

  • 服務器指定套接字地址的公認端口號,不指定IP地址,服務器調用函數bind時,如果設置套接字的IP地址爲特殊的INADDR ANY, 表示它願意接收來自任何網絡設備接口的客戶端連接,這是服務器最經常使用的綁定方式。
  • 服務器指定套接字地址的公認端口號和IP地址,服務器調用函數bind時,如果設置套接字的 IP 地址爲某個本地 IP 地址,則表示服務器只接收來自對應於這個 IP 地址的特定網絡設備接口的客戶端連接。如果這臺機器只有一個網絡設備接口,則這和第一種情況是沒有區別的,但當這臺機器有多個網絡設備接口時,我們可以用這種方式來限制服務器的接收範圍。
  • 客戶端指定套接字地址的連接端口號,在一般情況下,客戶端不用指定自己的套接字地址的端口號,當客戶端調用函數 connect 進行 TCP 連接時,系統會自動爲它選擇一個未用的端口號,並且用本地的 IP 地址來填充套接字地址中的相應項,但在有的情況下,客戶端需要使用特定端口號。
  • 指定客戶端的 IP 地址和連接端口號,表示客戶端使用指定的網絡設備接口和端口號進行通信。
  • 指定客戶端的 IP 地址,表示客戶端使用指定的網絡設備接口進行通信,系統自動爲客戶端選擇一個未用的端口號。一般情況下,只有在主機有多個網絡設備接口時使用。
C/S IP port 說明
服務器 INADDR_ANY 非 0 值 指定服務器的公認端口號
服務器 本地 IP 地址 非 0 值 指定服務器的 IP 地址和公認端口號
客戶端 INADDR_ANY 非 0 值 指定客戶端的連接端口號
客戶端 本地 IP 地址 非 0 值 指定客戶端的 IP 地址和連接端口號
客戶端 本地 IP 地址 0 指定客戶端的 IP 地址

在編寫客戶端程序時,通常不要使用固定的客戶端端口號,除非是在必須使用特定端口的情況下,因爲固定客戶機端口號會帶來一些不便, 例如:

  • 服務器執行主動關閉操作:服務器最後進入 TIME_WAIT 狀態。當客戶機再次與這個服務器進行連接時,仍使用相同的客戶機端口號,於是這個連接與前次連接的套接字對完全相同,但是因爲前次連接處於 TIME_WAIT 狀態,並未消失,所以這次連接請求被拒絕,函數 connect 以錯誤返回。
  • 客戶端執行手動關閉操作:客戶端最後進入 TIME_WAIT 狀態,當立刻再次執行這個客戶機程序時,客戶機將繼續與這個固定客戶機端口號綁定,但因爲前次連接處於 TIME_WAIT 狀態,並未消失,系統會發現這個端口號仍被佔用,所以這次綁定操作失敗,函數 bind 以錯誤返回。

【例2】使用 bind 函數綁定套接字
應用代碼定義了一個 IPv4 的套接字地址數據結構變量 addr,首先使用 socket 函數創建一個套接字,然後使用 bzero 函數將結構變量 addr 的值清空,分別設置結構體的各個分量,最後調用函數將這個變量綁定到剛剛創建的套接字上。

實例的應用代碼如下:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

#define PORT 5555    //定義端口號

int main(int argc, char *argv[])
{
    int sockfd;     //定義套接口描述符
    struct sockaddr_in addr;   //定義 IPv4 套接口地址數據結構 addr 
    int addr_len = sizeof(struct sockaddr_in);   
    if(sockfd = socket(AF_INET, SOCK_STREAM,0) < 0)   //建立一個 socket
    {
        printf("創建套接字失敗!\n");
        return 1;
    }
    bzero(&addr, sizeof(struct sockaddr_in));  //清空表示地址的結構體變量
    addr.sin_family = AF_INET;    //設置 addr 的成員信息
    addr.sin_port = htons(PORT);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);  //IP地址設爲本機IP
    if(bind(sockfd, (struct sockaddr *)(&addr), sizeof(strut sockaddr))<0)
    {
        printf("綁定端口失敗!");
        return 1;
    }
    return 0;
}

該程序沒有輸出。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章