SOCKET 學(xué)習(xí)筆記

前言

面經(jīng)中提到的epoll,涉及到了socket編程。為了深入了解epoll原理,需要首先了解socket編程。socket是進(jìn)程間通信IPC,就算在網(wǎng)絡(luò)中也是如此,所以說網(wǎng)絡(luò)中通信的主體是進(jìn)程,而不是計(jì)算機(jī)。socket學(xué)習(xí)內(nèi)容一個(gè)是如何建立服務(wù)器和客戶端,一個(gè)是如何使用socket API。

fd=socket(domain, type, protocol);

socket調(diào)用可以用來創(chuàng)建一個(gè)socket,例如
domain可以用來指定ipv4,type可以用來指定tcp,protocol一般是0。

  • domain
    domain是通信范圍與通信地址的類型。有下面幾個(gè)經(jīng)典類型:
    UNIX IPV4 IPV6,分別對應(yīng)的參數(shù)是AF_UNIX AF_INET AF_INET6。
    domain 的參數(shù)都是以AF開頭的代表地址簇。PF開頭的代表協(xié)議簇。本來設(shè)計(jì)是地址簇和協(xié)議簇是多對多的,但是后來實(shí)現(xiàn)過程中,一個(gè)協(xié)議簇和地址簇是一一對應(yīng)的。所以基本上domain就是指定了協(xié)議簇,地址簇也被指定了。

  • type
    socket表示是流還是數(shù)據(jù)包,其實(shí)就是TCP還是UDP。如果是TCP就是SOCK_STREAM,如果是UDP就是SOCK_DGRAM

bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

該調(diào)用用于將socket綁定到一個(gè)地址上。之后可以發(fā)送TCP報(bào)文,在一些場合下也可以通過write發(fā)送UDP報(bào)文,但是只能在該socket上讀取對等socket數(shù)據(jù)。

  • sockaddr
    該結(jié)構(gòu)體有一個(gè)整形表示地址類型,然后后面跟著一個(gè)char數(shù)組。后面可以看到具體傳進(jìn)來的是根據(jù)使用場合的其他數(shù)據(jù)結(jié)構(gòu),但是是通用的

listen(int sockfd, int backlog)

將一個(gè)socket描述符標(biāo)記為被動(dòng)??梢员恢鲃?dòng)socket連接。backlog是用于限制等待連接的數(shù)量。

accept(int sockfd, struct sockaddr *addr, socklen_t * addrlen);

accept調(diào)用會阻塞并等待在文件描述符sockfd上的接入請求。一旦請求成功,會創(chuàng)建一個(gè)新的socket,這個(gè)新的socket與對方進(jìn)行連接。

  • addr
    返回對方的地址
  • addrlen
    傳入addr的長度,用于告知能夠?qū)懭胼斎氲淖畲箝L度。

connect(int sockfd, const struct sockaddr * addr, socklen_t addrlen);

將sockfd連接到addr所述的地址上。

close(int fd)

用于關(guān)閉連接

read write

用于對sockfd進(jìn)行讀入或讀出

recvfrom(int sockfd, void *buffer, size_t length, int flags, struct sockaddr *src_addr, socklen_t *addrlen);

sendto(int sockfd, const void *buffer, size_t length, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);

用于發(fā)送和接受udp報(bào)文。服務(wù)器端不能使用listen函數(shù)和accept函數(shù),客戶端不能使用connect函數(shù)。

unix domain

使用上面的API就可以實(shí)現(xiàn)本機(jī)上通過文件的通信。
unix domain所使用的sockaddr是sockaddr_run,如下表示:

struct sockaddr_un{
    sa_family_t sun_family;
    char sun_path[108];
}

網(wǎng)絡(luò)字節(jié)序

網(wǎng)絡(luò)字節(jié)順序是按照大端來的,x86是小端結(jié)構(gòu)。轉(zhuǎn)換使用的是如下的函數(shù)進(jìn)行的

  • htons
  • htonl
  • ntohs
  • ntohl
    h是host,n是net,s是16位,l是32位。s和l是short和long,雖然現(xiàn)在已經(jīng)不再使用這樣的標(biāo)準(zhǔn)了。

Internet socket 地址結(jié)構(gòu)

網(wǎng)絡(luò)下使用的socket地址是sockaddr_in,定義如下

struct sockaddr_in{
    sa_family_t sin_family;
    in_port_t sin_port;
    struct in_addr sin_addr;
    unsigned char __pad[X];
}

可以看出不一樣的地方是后面的char數(shù)組變成了一個(gè)端口和地址。sin是socket Internet的簡寫,簡寫的和sun一樣很差。

Internet socket 地址轉(zhuǎn)換

字符串式的地址格式和二進(jìn)制地址格式轉(zhuǎn)換API:

inet_pton(int domain, const char *src, void *addrptr);

該函數(shù)用于將src中包含的字符串轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)的二進(jìn)制地址,存入addrptr。p是presentation的意思,就是人類方便的地址。

const char * inet_ntop(int domain, const void *addrptr, char *dst_str, size_t len);

該函數(shù)執(zhí)行網(wǎng)絡(luò)字節(jié)的二進(jìn)制地址轉(zhuǎn)換為人類可讀的地址,寫入到dst_str中,緩沖區(qū)的大小有l(wèi)en傳入。

getaddrinfo(const char *host, const char *service, const struct addrinfo *hints, struct **result);

該函數(shù)給定一個(gè)主機(jī)名和服務(wù)器名,返回socket地址和端口號。
getaddrinfo以host、service、hints參數(shù)作為輸入,其中host參數(shù)包括一個(gè)主機(jī)名或一個(gè)以IPV4字符串。service是服務(wù)名或者是端口號。該函數(shù)的調(diào)用之后需要使用freeaddrinfo來釋放空間。

getnameinfo(const struct sockaddr *addr, socklen_t addrlen, char *host, size_t hostlen, char *service, size_t servlen, int flags);

給定一個(gè)socket地址結(jié)構(gòu),返回一個(gè)主機(jī)和服務(wù)器名的字符串。

setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);

sockfd是代表指向套接字的文件描述符。參數(shù)level制定了套接字選項(xiàng)所適用的協(xié)議。例如TCP或者是IP,這表示選項(xiàng)作用的套接字API層。一般來說,該選項(xiàng)會設(shè)置為SOL_SOCKET,表示作用于套接字API層。參數(shù)optname表示了我們期待設(shè)置的選項(xiàng),optvalue是用來設(shè)置剛剛的選項(xiàng)的值,可以是整數(shù)或者是結(jié)構(gòu)體的指針,指向了一個(gè)緩沖區(qū),而參數(shù)optlen是剛剛那個(gè)指針?biāo)赶騾^(qū)域的大小。

例如,要設(shè)置sockfd為reuseaddr屬性時(shí),可以如下調(diào)用:

    int reuse = 1;
    if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1)
    {
        err_exit("setsockopt");
    }

getsockopt(int sockfd, int level, int optname, void *optval, socklen_t optlen);

用法和上面一樣,只是獲取而已。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 大綱 一.Socket簡介 二.BSD Socket編程準(zhǔn)備 1.地址 2.端口 3.網(wǎng)絡(luò)字節(jié)序 4.半相關(guān)與全相...
    VD2012閱讀 2,705評論 0 5
  • 下面為Daytime這個(gè)服務(wù)的源代碼例子,同時(shí)兼容IPV6和IPV4的地址,最后部分有更多說明。 單播模式下的Se...
    天楚銳齒閱讀 6,044評論 0 2
  • 套接字是網(wǎng)絡(luò)通信的基石,是網(wǎng)絡(luò)通信的基本構(gòu)建,最初是由加利福利亞大學(xué)Berkeley分校為UNIX開發(fā)的網(wǎng)絡(luò)通信編...
    Super超人閱讀 4,743評論 0 26
  • 研究IPv6 socket編程原因: Supporting IPv6 in iOS 9 WWDC2015蘋果宣布在...
    li大鵬閱讀 7,643評論 7 15
  • 網(wǎng)絡(luò)模型 物理層 物理層表示的是比特流傳輸,通常包括串口/COM口、并行/LPT口、USB、網(wǎng)線接口、電話線接口;...
    秋風(fēng)弄影閱讀 829評論 0 2

友情鏈接更多精彩內(nèi)容