1. 程式人生 > 其它 >linux高效能伺服器程式設計---第五章Linux網路程式設計基礎API (3)

linux高效能伺服器程式設計---第五章Linux網路程式設計基礎API (3)

通用讀寫函式
#inclued <sys/socket.h>
ssize_t recvmsg(int sockfd, struct msghdr* msg, int flags);
ssize_t sendmsg(int sockfd, struct msghdr* msg, int flags);

struct msghdr
{
/* socket address --- 指向socket地址結構變數, 對於TCP連線需要設定為NULL*/
    void* msg_name; 


    socklen_t msg_namelen;
    
    /* 分散的記憶體塊 --- 對於 recvmsg來說資料被讀取後將存放在這裡的塊記憶體中, 記憶體的位置和長度由
     * msg_iov指向的陣列指定, 稱為分散讀(scatter read)  ---對於sendmsg而言, msg_iovlen塊的分散記憶體中
     * 的資料將一併傳送稱為集中寫(gather write);
    
*/ struct iovec* msg_iov; int msg_iovlen; /* 分散記憶體塊的數量*/ void* msg_control; /* 指向輔助資料的起始位置*/ socklen_t msg_controllen; /* 輔助資料的大小*/ int msg_flags; /* 複製函式的flags引數, 並在呼叫過程中更新*/ }; struct iovec { void* iov_base /* 記憶體起始地址*/ size_t iov_len /* 這塊記憶體長度*/ }

其他Api

#include <sys/socket.h>
//
用於判斷 sockfd是否處於帶外標記, 即下一個被讀取到的資料是否是帶外資料, // 是的話返回1, 不是返回0 // 這樣就可以選擇帶MSG_OOB標誌的recv呼叫來接收帶外資料. int sockatmark(int sockfd); // getsockname 獲取sockfd對應的本端socket地址, 存入address指定的記憶體中, 長度存入address_len中 成功返回0失敗返回-1 // getpeername 獲取遠端的資訊, 同上 int getsockname(int sockfd, struct sockaddr* address, socklen_t* address_len);
int getpeername(int sockfd, struct sockaddr* address, socklen_t* address_len); /* 以下函式標頭檔案均相同*/ // sockfd 目標socket, level執行操作協議(IPv4, IPv6, TCP) option_name 引數指定了選項的名字. 後面值和長度 // 成功時返回0 失敗返回-1 int getsockopt(int sockfd, int level, int option_name, void* option_value, socklen_t restrict option_len); int setsockopt(int sockfd, int level, int option_name, void* option_value, socklen_t restrict option_len);
SO_REUSEADDR 重用本地地址 sock被設定此屬性後, 即使sock在被bind()後處於TIME_WAIT狀態, 此時與他繫結的socket地址依然能夠立即重用來繫結新的sock
SO_RCVBUF TCP接收緩衝區大小 最小值為256位元組. 設定完後系統會自動加倍你所設定的值. 多出來的一倍將用用作空閒緩衝區處理擁塞
SO_SNDBUF TCP傳送緩衝區大小 最小值為2048位元組
SO_RCVLOWAT 接收的低水位標記 預設為1位元組, 當TCP接收緩衝區中可讀資料的總數大於其低水位標記時, IO複用系統呼叫將通知應用程式可以從對應的socket上讀取資料
SO_SNDLOWAT 傳送的高水位標記 預設為1位元組, 當TCP傳送緩衝區中空閒空間大於低水位標記的時候可以寫入資料
SO_LINGER  
struct linger
{
    int l_onoff /* 開啟非0, 關閉為0*/
    int l_linger; /* 滯留時間*/
    /*
    * 當onoff為0的時候此項不起作用, close呼叫預設行為關閉socket
    * 當onoff不為0 且linger為0, close將立即返回, TCP將丟棄傳送緩衝區的殘留資料, 同時傳送一個復位報文段
    * 當onoff不為0 且linger大於0 . 當socket阻塞的時候close將會等待TCP模組傳送完殘留資料並得到確認後關 
    * 閉, 如果是處於非阻塞則立即關閉
    */
};

 

網路資訊API

#include <netdb.h>
// 通過主機名查詢ip
struct hostent* gethostbyname(const char* name);

// 通過ip獲取主機完整資訊 
// type為IP地址型別 AF_INET和AF_INET6
struct hostent* gethostbyaddr(const void* addr, size_t len, int type);

struct hostent
{
  char *h_name;            /* Official name of host.  */
  char **h_aliases;        /* Alias list.  */
  int h_addrtype;        /* Host address type.  */
  int h_length;            /* Length of address.  */
  char **h_addr_list;        /* List of addresses from name server.  */
}

int main(int argc, char* argv[])
{
    if (argc != 2)
    {
        printf("非法輸入\n");
        exit(0);
    }
    char* name = argv[1];

    struct hostent *hostptr{};

    hostptr = gethostbyname(name);
    if (hostptr == nullptr)
    {
        printf("輸入存在錯誤 或無法獲取\n");
        exit(0);
    }

    printf("Official name of hostptr: %s\n", hostptr->h_name);

    char **pptr;
    char inet_addr[INET_ADDRSTRLEN];

    printf("Alias list:\n");
    for (pptr = hostptr->h_aliases; *pptr != nullptr; ++pptr)
    {
        printf("\t%s\n", *pptr);
    }

    switch (hostptr->h_addrtype)
    {
        case AF_INET:
        {
            printf("List of addresses from name server:\n");
            for (pptr = hostptr->h_addr_list; *pptr != nullptr; ++pptr)
            {
                printf("\t%s\n",
                        inet_ntop(hostptr->h_addrtype, *pptr, inet_addr, sizeof(inet_addr)));
            }
            break;
        }
        default:
        {
            printf("unknow address type\n");
            exit(0);
        }
    }
    return 0;
}

/*
./run baidu.com
Official name of hostptr: baidu.com
Alias list:
List of addresses from name server:
    39.156.69.79
    220.181.38.148
*/