Linux C 網絡_建立連接函數

當使用 socket 函數建立一個套接字並且綁定了地址之後,即可使用 connect 函數來和服務器建立一個連接。

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

其中參數 sockfd 是套接字創建函數 socket 返回的套接字描述符,參數 addr 指定遠程服務器的套接字地址,包括服務器的 IP 地址和端口號;參數 addrlen 指定這個套接字地址的長度;當調用成功後返回0,否則返回 -1。

在調用 connect 函數建立連接之前,客戶端應用代碼需要指定服務器端進程的有套接字地址,而
客戶端通常不會指定自己的套接字地址,Linux 會自動從1024 ~ 5000 的端口範圍之中爲客戶端分配一個未被使用的端口號,然後將該端口號和本機的 IP 地址結合在一起放入套接字地址中。

當客戶端調用函數 connet 來主動建立連接時,這個函數將啓動 TCP 協議的 3 次握手過程,在連接建立之後或發生錯誤時,函數返回。連接過程中可能有如下幾種錯誤情況:

  • 如果客戶機 TCP 協議沒有接收到對它的 SYN 數據段確認,則函數以錯誤返回,錯誤類型爲 ETIMEOUT。通常情況下,TCP 協議在發送 SYN 數據段失敗之後,會多次發送 SYN 數據段,在所有的發送都宣告失敗之後,函數以錯誤返回。
  • 如果遠程 TCP 協議返回一個 RST 數據段,則函數立即以錯誤返回,錯誤類型爲 ECONNREFUSED。當遠程機器在 SYN 數據段指定的目的端口號處沒有服務器進程在等待連接時,遠程機器的 TCP 協議將發送一個 RST 數據段,向客戶機報告這個錯誤。客戶機的 TCP 協議在接收到 RST 數據段之後,不再繼續發送 SYN 數據段,函數立即以錯誤返回。
  • 如果客戶機的 SYN 數據段導致某個路由器產生 “目的地不可到達” 類型的 ICMP 消息,則函數以錯誤返回,錯誤類型爲 EHOSTUNREACH 或 ENETUNREACH。通常情況下,TCP 協議在接收到這個 ICMP 消息之後,記錄這個消息,然後繼續幾次發送 SYN 數據段,在所有的發送都宣告失敗之後,TCP 協議檢查這個 ICMP 消息,函數以錯誤返回。

如果調用函數 connect 失敗,應該用函數 close 關閉這個套接字描述符,不能再次用這個套接字描述符來調用函數 connect。

【例3】使用 connect 函數建立連接
應用代碼使用 PORT 和 REMOTE_IP 來分別定義一個端口號和一個 IP 地址,然後分別調用 socket 和 bind 函數來創建套接字和綁定套接字,最後使用 connect 函數來連接 argv[1] 參數中所指定的 IP 地址。

實例的應用代碼如下:

#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fentl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#define PORT 80  //定義一個端口號
#define REMOTE_IP "59.175.132.70"  //定義一個IP地址

int main(int argc, char *argv[])
{
    int sockfd;
    struct sockaddr_in addr;  //定義 IPV4 套接字地址數據結構 addr
    if(argc != 2)
    {
        printf("請輸入正確的IP地址字符串。\n");
        return 2;
    }
    if(sockd = socket(A_INET, SOCK_STRAMOY, 0))<0) //建立一個 socket
    {
        printf("創建套接字失敗!\n");
        return 1;
    }
    bzero(&addr,sizeof(struct sockaddr_in));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    addr.sin_addr.s_addr = inet_addr(argv[1]);  //從argv[1]中獲得目標的IP地址
    if(connect(sockfd, (struct sockaddr *)(&addr), sizeof(struct sckaddr))<0)
    {
        printf("連接失敗!\n");
        return;
    }
    else
    {
        printf("連接成功!\n");
    }
    return 0;
}

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