日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Linux Socket編程-基礎(chǔ)知識點

 西北望msm66g9f 2021-08-09

套接字(Socket)按照操作類型可以分為三類:

1.流式套接字(SOCK_STREAM):面向連接的Socket,只能收發(fā) TCP 協(xié)議的數(shù)據(jù);

2.數(shù)據(jù)報式套接字(SOCK_DGRAM):面向無連接的Socket,只能收發(fā) UDP 協(xié)議的數(shù)據(jù);

3.原始套接字(SOCK_RAW)可以用來自行組裝數(shù)據(jù)包,可以接收本機(jī)網(wǎng)卡上所有的數(shù)據(jù)幀(數(shù)據(jù)包),直接操作系統(tǒng)網(wǎng)絡(luò)核心(Network Core)。

Socket基本數(shù)據(jù)結(jié)構(gòu)

1.套接字地址結(jié)構(gòu)

IPV4

A.新式機(jī)構(gòu)

<netinet/in.h>

struct sockaddr_in

{

   unsigned           short sin_len;      //IPv4地址長度

   short int          sin_family;   //指代協(xié)議簇,在TCP套接字編程只能是AF_INET

   unsigned           short sin_port;     //存儲端口號(使用網(wǎng)絡(luò)字節(jié)順序),數(shù)據(jù)類型是一個16為的無符號整形類型

   struct   in_addr   sin_addr;//存儲IP地址,IP地址是一個in_add結(jié)構(gòu)體(結(jié)構(gòu)在下面)

   unsigned char      sin_zero[8];     //為了讓sockaddr與sockaddr_in兩個數(shù)據(jù)結(jié)構(gòu)保持大小相同而保留的空字節(jié)

};

struct in_addr

{

   unsigned long s_addr;   //按照網(wǎng)絡(luò)字節(jié)順序存儲IP地址

};

大端模式和小端模式

  1)小端就是低位字節(jié)排放在內(nèi)存的低地址端,高位字節(jié)排放在內(nèi)存的高地址端。

  2)大端就是高位字節(jié)排放在內(nèi)存的低地址端,低位字節(jié)排放在內(nèi)存的高地址端。

  舉一個例子,比如數(shù)字0x12 34 56 78在內(nèi)存中的表示形式為:

  A. 大端模式:

  低地址 -----------------> 高地址

  0x12  |  0x34  |  0x56  |  0x78

  B. 小端模式:

  低地址 ------------------> 高地址

  0x78  |  0x56  |  0x34  |  0x12

B.老式結(jié)構(gòu)

struct sockaddr

{

   unsigned short  sa_family;  //套接字的協(xié)議簇地址類型,TCP/IP協(xié)議對于IPv4地址類型為AF_INET

   char            sa_data[14];//存儲具體的協(xié)議地址

};

IPV6

A.新式結(jié)構(gòu)

<netinet/in.h>

struct sockaddr_in6

{

   unsigned short int       sin6_len;   //IPv6結(jié)構(gòu)長度,是一個無符號的8為整數(shù),表示128為IPv6地址長度

   short int                sin6_family; //地址類型AF_INET6

   unsigned short int       sin6_port;   //存儲端口號,按網(wǎng)絡(luò)字節(jié)順序

   unsigned short int       sin6_flowinfo;  //低24位是流量標(biāo)號,然后是4位的優(yōu)先級標(biāo)志,剩下四位保留

   struct in6_addr          sin6_addr;      //IPv6地址,網(wǎng)絡(luò)字節(jié)順序

};

B.老式結(jié)構(gòu)

struct in6_addr

{

    unsigned long s6_addr;  //128位的IPv6地址,網(wǎng)絡(luò)字節(jié)順序

};

常用函數(shù)

1.socket函數(shù)?

函數(shù):int socket(int, int, int);

?功能:創(chuàng)建一個套接字

?解釋:int socket(int af, int type, int protocol);

  • af:表示一個地址家族,IPv4連接時填A(yù)F_INET,IPv6連接時對應(yīng)AF_INET6

  • type:表示套接字類型,如果是SOCK_STREAM表示創(chuàng)建面向連接的流式套接字;如果是SOCK_DGRAM表示面向無連接的數(shù)據(jù)包套接字;為SOCK_RAW表示創(chuàng)建原始套接字

  • protocol:表示套接口所用的協(xié)議,如果用戶不指定,可以設(shè)置為0

  • 返回值:int類型的一個指向傳輸提供者的句柄(套接字)

socket函數(shù)的family常值

socket函數(shù)的type常值

 socket函數(shù)的protocol常值

socket函數(shù)中family和type參數(shù)的組合

2.bind函數(shù)?

函數(shù):int bind(int, const struct sockaddr *, socklen_t)?

功能:將套接字綁定到指定端口和地址上?

解釋:

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

  • sockfd:表示套接字標(biāo)識

  • my_addr:是一個指向struct sockaddr結(jié)構(gòu)體類型的指針,一般綁定 IPv4地址傳入struct sockaddr_in指針,IPv6地址傳入struct sockaddr_in6指針(PS:這里我也不是很清楚,sockaddr_in結(jié)構(gòu)體里面有地址族,改變地址族為IPv6的不知道行不行,下面的演示和注釋以前面的struct sockaddr_in結(jié)構(gòu)體為主),都包含地址和端口號信息,強(qiáng)轉(zhuǎn)成需要的類型

  • addrlen:確定my_addr緩沖區(qū)的長度,就是前面結(jié)構(gòu)體的大小

  • 返回值:如果函數(shù)執(zhí)行成功,則返回值為0,失敗則為-1

3.listen函數(shù)

?函數(shù):int listen(int, int)?

功能:將套接字設(shè)置為監(jiān)聽模式,對于流式套接字,必須處入監(jiān)聽模式才能夠接收客戶端套接字的連接

?解釋:int listen(int sockfd, int backlog);

  • sockfd:表示套接字標(biāo)識

  • backlog:表示等待連接的最大隊列長度。例如:如果backlog被設(shè)置為2,此時有3個客戶端同時發(fā)出連接請求,那么前兩個客戶端會放置在等待連接隊列中,第三個客戶端會得到錯誤信息。

  • 返回值:成功則返回0,失敗則返回-1

4.accept函數(shù)?

函數(shù):int accept(int, struct sockaddr * __restrict, socklen_t * __restrict)?

功能:接受客戶端的連接,在流式套接字中,只有在套接字處入監(jiān)聽狀態(tài),才能接受客戶端的連接?

解釋:int accept(int sockfd, struct sockaddr *addr, int *addrlen);

  • sockfd:表示套接字標(biāo)識

  • addr:是一個sockaddr_in結(jié)構(gòu)體指針,接收連接端地址信息

  • addrlen:前面sockaddr_in結(jié)構(gòu)體地址長度指針,用來接收連接端地址信息結(jié)構(gòu)體長度

  • 返回值:一個新的套接字,它對應(yīng)于已經(jīng)接受的客戶端連接,對于該客戶端的所有后續(xù)操作,都應(yīng)使用這個新的套接字

5.close函數(shù)?函數(shù):int close(int)?

功能:關(guān)閉套接字

?解釋:int close(int sockfd);

6.connect函數(shù)?

函數(shù):int connect(int, const struct sockaddr *, socklen_t)?

功能:發(fā)送一個連接請求

解釋:int connect(int sockfd,const struct sockaddr * addr_server, int addrlen)

  • sockfd:表示一個正準(zhǔn)備連接的套接字??蛻舳诉B接套接字int socket_client

  • addr_server:存儲套接字要連接主機(jī)的地址信息結(jié)構(gòu)體指針

  • addrlen:前面結(jié)構(gòu)體的也就是addr_server結(jié)構(gòu)體緩沖區(qū)的長度

  • 返回值:成功則返回0,失敗則返回-1

connect函數(shù)將激發(fā)TCP的三次握手過程,而且僅在連接建立成功或出錯時才返回,其中出錯有如下幾種情況:

1).若TCP客戶沒有收到SYN包的響應(yīng),則返回ETIMEDOUT錯誤。如調(diào)用該函數(shù)時,內(nèi)核發(fā)送一個SYN,若無響應(yīng)則等待6s后再發(fā)一個,若仍無響應(yīng),則等待24s再發(fā)一個,若總共等了75s后仍未收到響應(yīng)消息則返回該錯誤(因內(nèi)核而異)。

2).若響應(yīng)時RST,表明該服務(wù)器主機(jī)在我們指定的端口上沒有進(jìn)程等待,客戶收到RST包后馬上返回ECONNREFUSED錯誤。

3).若客戶發(fā)出的SYN在中間的路由器上引發(fā)了一個“destination unreachable”的ICMP錯誤,則按第一種情形繼續(xù)發(fā)送SYN,若在規(guī)定的時間內(nèi)沒有收到回應(yīng),則將ICMP錯誤作為EHOSTUNREACH或ENETUNREACH錯誤返回。

7.recv函數(shù)

函數(shù):ssize_t recv(int, void *, size_t, int)

功能:從流式套接字中接受數(shù)據(jù),平時開發(fā)針對TCP套接字接收數(shù)據(jù)

解釋:ssize_t recv(int sockfd,  void *buff,  size_t nbytes,   int flags)

  • sockfd表示流式套接字

  • buff用來存放recv函數(shù)接收到的數(shù)據(jù)的緩沖區(qū)

  • nbytes緩沖區(qū)的長度

  • flags 表示函數(shù)的調(diào)用方式,一般填0

成功時返回接收的字節(jié)數(shù)(收到EOF是返回0),失敗是返回-1

8.send函數(shù)

函數(shù):ssize_t send(int, const void *, size_t, int)

功能:在流式套接字中發(fā)送數(shù)據(jù)

解釋:ssize_t send(int sockfd, const void *buff, size_t nbytes, int flags          //表示函數(shù)的調(diào)用方式,一般填0,具體看下面表格

            )

  • sockfd表示流式套接字

  • buff存放要發(fā)送數(shù)據(jù)的緩沖區(qū)

  • nbytes實際要改善的數(shù)據(jù)的字節(jié)數(shù)

  • int flags 表示函數(shù)的調(diào)用方式,一般填0

返回值:成功返回發(fā)送的字節(jié)數(shù),錯誤返回-1

9.recvfrom函數(shù)

函數(shù):ssize_t recvfrom(int, void *, size_t, int, struct sockaddr * __restrict, socklen_t * __restrict)

功能:用于接收一個數(shù)據(jù)包,并保存源地址

解釋:

ssize_t recvfrom(int sockfd,  void * buff, size_t nbytes, int flags,  struct sockaddr * __restrict from,  socklen_t * __restrict fromLen)

  • sockfd表示準(zhǔn)備接收的套接字

  • buff指向緩沖區(qū)的指針,用來接收數(shù)據(jù)

  • nbytes表示緩沖區(qū)的長度

  • flags表示調(diào)用方式,一般填0

  • __restrict from是一個指向地址結(jié)構(gòu)體的指針,用來接收發(fā)送數(shù)據(jù)方的地址信息

  • __restrict fromLen 前面結(jié)構(gòu)體長度指針

返回值:如果正確接收返回接收到的字節(jié)數(shù),失敗返回-1.

10.sendto函數(shù)

函數(shù):ssize_t sendto(int, const void *, size_t, int, const struct sockaddr *, socklen_t)

功能:向指定的目的地方發(fā)送數(shù)據(jù)

解釋:ssize_t sendto(int sockfd, const void * buff, size_t nbytes,  int  flags,  const struct sockaddr *  to, socklen_t  tolen)

  • sockfd表示準(zhǔn)備發(fā)送數(shù)據(jù)的套接字

  • buff指向緩沖區(qū)的指針,該緩沖區(qū)包含將要發(fā)送的數(shù)據(jù)

  • nbytes緩沖區(qū)數(shù)據(jù)長度

  • flags表示調(diào)用方式,一般填0

  • to指向目標(biāo)套接字地址的結(jié)構(gòu)體指針

  • tolen前面結(jié)構(gòu)體長度

成功則返回實際傳送出去的字符數(shù),失敗返回-1,錯誤原因存于errno 中

輔助函數(shù)

1.htons() 函數(shù)ntohs()函數(shù)?

函數(shù):u_short htons(u_short hostshort)?功能:將一個16位的無符號端整形數(shù)據(jù)由主機(jī)排列方式轉(zhuǎn)換成網(wǎng)絡(luò)排列方式,所謂的網(wǎng)絡(luò)排列方式就是大端排列方式,MacOS是采用小端的存儲方式存儲數(shù)據(jù)?

使用地方:在有關(guān)主機(jī)地址和端口號結(jié)構(gòu)體中struct sockaddr_in里面,屬性in_port_t sin_port表示端口號,因為端口號要用網(wǎng)絡(luò)排列方式,使用該函數(shù)轉(zhuǎn)換后賦值

函數(shù): u_short ntohs(u_short netshort)?功能: 與htons()功能相反,將16位無符網(wǎng)絡(luò)排列端口轉(zhuǎn)換成主機(jī)排列方式,也就是將16位大端排列數(shù)字轉(zhuǎn)換成小端排列方式?

使用地方: 得到地址結(jié)構(gòu)體struct sockaddr_in,將里面的in_port_t sin_port轉(zhuǎn)換成我們平時看到的小端排列的端口號

2.htonl() 函數(shù)ntohl()函數(shù)

函數(shù):u_long htonl(u_long hostlong)

功能:將一個32位無符號整形由主機(jī)排列方式轉(zhuǎn)換成網(wǎng)絡(luò)排列方式,所謂的網(wǎng)絡(luò)排列方式就是大端排列方式

使用地方:在有關(guān)主機(jī)地址和端口號結(jié)構(gòu)體中struct sockaddr_in里面,結(jié)構(gòu)體屬性struct in_addr sin_addr中的in_addr_t s_addr屬性表示IP地址信息,因為IP地址信息要用網(wǎng)絡(luò)排列方式,使用該函數(shù)轉(zhuǎn)換后賦值

函數(shù):u_long ntohl(u_long netlong)

功能:與函數(shù) htonl()功能相反,將網(wǎng)絡(luò)排列的32位無符數(shù)據(jù)轉(zhuǎn)換成主機(jī)排列,就是將32位大端排列數(shù)字轉(zhuǎn)換成小段排列數(shù)據(jù)

使用地方:得到地址結(jié)構(gòu)體struct sockaddr_in,將里面的in_addr_t s_addr轉(zhuǎn)換成我們平時看到的小端排列32位IP地址

3.inet_addr 函數(shù)

函數(shù):in_addr_t inet_addr(const char *)

功能:將存儲IP地址的char字符串轉(zhuǎn)換成網(wǎng)絡(luò)排列方式的32位無符號整形,跟上面htonl()函數(shù)功能一樣

使用地方:轉(zhuǎn)換的結(jié)果可直接用來給地址信息結(jié)構(gòu)體里面的IP地址賦值,因為轉(zhuǎn)換出來的結(jié)果是網(wǎng)絡(luò)排列的

4.inet_aton 函數(shù)

函數(shù):int inet_aton(const char *, struct in_addr *);

功能:與函數(shù)inet_addr功能一樣,將char字符串IP地址轉(zhuǎn)換成網(wǎng)絡(luò)排序的無符整形,傳入struct in_addr結(jié)構(gòu)體指針,直接賦給結(jié)構(gòu)體

5.inet_pton 函數(shù)

函數(shù):int inet_pton(int, const char *, void *);

功能:與輔助函數(shù)htonl()、inet_addr()、inet_aton()的功能一樣,將char字符串IP地址轉(zhuǎn)換成網(wǎng)絡(luò)排序的無符整形,直接賦給struct in_addr結(jié)構(gòu)體指針里面,不一樣的是可以根據(jù)地址族的不同轉(zhuǎn)換IPv6還是IPv4的地址

6.inet_ntoa 函數(shù)

函數(shù):char *inet_ntoa(struct in_addr)

功能:正好與上面的函數(shù)inet_aton功能相反,需要傳入一個關(guān)于地址信息的結(jié)構(gòu)體,解析出來C字符串的IP地址

7.inet_ntop 函數(shù)

函數(shù):const char *inet_ntop(int, const void *, char *, socklen_t);

功能:跟上面函數(shù)inet_ntoa()功能相似,于函數(shù)inet_pton()功能相反,不一樣的是他可以傳入地址族,傳入AF_INET則解析出IPv4的地址,傳入AF_INET6則解析

8.getpeername 函數(shù)?

函數(shù):int getpeername(int, struct sockaddr * __restrict, socklen_t * __restrict)?功能:獲取socket套接字對方的地址信息,返回0時正常,否則錯誤?

解釋:int getpeername(int sockfd, struct sockaddr * peerAddr, socklen_t * addrLen)

  • sockfd:表示套接字

  • peerAddr:接收地址信息結(jié)構(gòu)體,傳入結(jié)構(gòu)體指針外面申明里面賦值,獲取到的是連接對象的地址信息

  • addrLen:地址信息結(jié)構(gòu)體的長度指針

  • 返回值:返回0時可以通過地址信息指針取里面的信息,<0時錯誤

8.getsockname 函數(shù)?

函數(shù):int getsockname(int, struct sockaddr * __restrict, socklen_t * __restrict)?功能:獲取socket套接字的地址信息,返回0時正常,否則錯誤?

解釋:int getsockname(int sockfd, struct sockaddr * addr, socklen_t *addrLen)

  • sockfd:表示套接字

  • addr:接收地址信息結(jié)構(gòu)體,傳入結(jié)構(gòu)體指針外面申明里面賦值,獲取到的是sockfd的地址信息

  • addrLen:地址信息結(jié)構(gòu)體的長度指針

  • 返回值:返回0時可以通過地址信息指針取里面的信息,<0時錯誤

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多