socket套接字
Socket套接字
?? ?Socket是一個(gè)編程接口(網(wǎng)絡(luò)編程接口)。
?? ?作用是用來實(shí)現(xiàn)網(wǎng)絡(luò)上不同主機(jī)上的應(yīng)用程序之間進(jìn)行雙向通信。
?? ?套接字是一種特殊的文件描述符,也就意味著我們使用套接字實(shí)現(xiàn)網(wǎng)絡(luò)通信可以使用write/read。
?? ?
?? ?要實(shí)現(xiàn)互聯(lián)網(wǎng)通信,至少需要一對套接字,其中一個(gè)運(yùn)行在客戶端(client socket),一個(gè)運(yùn)行
?? ?服務(wù)器端(server socket).
?? ??? ?
?? ?Socket可以分為三類:
?? ??? ?1)?? ?流式套接字(SOCK_STRAM)
?? ??? ??? ?流式套接字用于提供面向連接、可靠的數(shù)據(jù)傳輸服務(wù)。
?? ??? ??? ?主要針對傳輸層協(xié)議為TCP協(xié)議的應(yīng)用。
?? ??? ??? ?
?? ??? ?2)?? ?數(shù)據(jù)報(bào)套接字(SOCK_DGRAM)
?? ??? ??? ?數(shù)據(jù)報(bào)套接字提供一種無連接的服務(wù)(并不能保證數(shù)據(jù)傳輸?shù)目煽啃?。
?? ??? ??? ?主要針對傳輸層協(xié)議為UDP協(xié)議的應(yīng)用。
?? ??? ??? ?
?? ??? ?3)?? ?原始套接字(SOCK_RAW)
?? ??? ??? ?原始套接字可以直接跳過傳輸層讀取沒有處理的IP數(shù)據(jù)包。
?? ??? ??? ?而流式套接字只能讀取TCP協(xié)議的數(shù)據(jù),數(shù)據(jù)報(bào)套接字只能讀取UDP協(xié)議的數(shù)據(jù)。
?? ??? ??? ?因此,如果要訪問其他協(xié)議發(fā)送的數(shù)據(jù)必須要使用原始套接字。
?? ??? ??? ?
?? ?1.?? ?TCP套接字的編程流程
?? ??? ?1)?? ?TCP網(wǎng)絡(luò)應(yīng)用程序的數(shù)據(jù)傳輸?shù)拇蟾胚^程
?? ??? ??? ?建立連接:--->加微信
?? ??? ??? ??? ?三次握手
?? ??? ??? ??? ?
?? ??? ??? ?發(fā)送/接受網(wǎng)絡(luò)數(shù)據(jù):--->聊天
?? ??? ??? ??? ?write/send/sendto
?? ??? ??? ??? ?read/recv/recvfrom
?? ??? ??? ?
?? ??? ??? ?關(guān)閉連接:--->刪除好友
?? ??? ??? ??? ?四次揮手
?? ??? ??? ?
?? ??? ??? ?三次握手:
?? ??? ??? ??? ?客戶端?? ??? ??? ??? ??? ??? ??? ?服務(wù)器端
?? ??? ??? ??? ?你好,我希望和你建立連接
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?好的,我已經(jīng)準(zhǔn)備好了,可以建立連接
?? ??? ??? ??? ?好的,馬上和你連接
?? ??? ??? ??? ?連接成功
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ?為什么要有三次握手的機(jī)制?
?? ??? ??? ??? ?通信雙方成功通信的前提條件是雙方要能夠建立連接。
?? ??? ??? ??? ?那么雙方能夠成功建立連接的前提條件又是什么呢?
?? ??? ??? ??? ?必須雙方都能夠收和發(fā)。
?? ??? ??? ??? ?所以三次握手實(shí)際上就是一個(gè)測試能不能夠建立連接的過程。
?? ??? ??? ??? ?
?? ??? ??? ?三次握手的具體過程:
?? ??? ??? ??? ?1)?? ?序號:Seq(Sequence Number)
?? ??? ??? ??? ??? ?序號占32bits,用來標(biāo)識從計(jì)算機(jī)A發(fā)送到計(jì)算機(jī)B的數(shù)據(jù)包的序號
?? ??? ??? ??? ??? ?計(jì)算機(jī)發(fā)送數(shù)據(jù)時(shí)需要對此進(jìn)行標(biāo)記。
?? ??? ??? ??? ??? ?
?? ??? ??? ??? ?2)?? ?確認(rèn)號(ACK:Acknowledge Number)
?? ??? ??? ??? ??? ?確認(rèn)號也是占32bits,客戶端和服務(wù)器都可以發(fā)送,Ack = Seq + 1
?? ??? ??? ??? ??? ?
?? ??? ??? ??? ?3)?? ?標(biāo)志位
?? ??? ??? ??? ??? ?每一個(gè)標(biāo)志位占用一個(gè)bits,共有6個(gè)標(biāo)志位。
?? ??? ??? ??? ??? ?分別是URG,ACK,PSH,RST,SYN,FIN,具體的含義如下:
?? ??? ??? ??? ??? ??? ?ACK:確認(rèn)序號有效
?? ??? ??? ??? ??? ??? ?RST:重置連接
?? ??? ??? ??? ??? ??? ?SYN:建立一個(gè)新連接(synchronous)
?? ??? ??? ??? ??? ??? ?FIN:斷開一個(gè)連接(finish)
?? ??? ??? ??? ??? ??? ?
?? ??? ??? ?四次揮手:
?? ??? ??? ??? ?我們建立連接是需要消耗掉一些資源的,同樣的,我們在斷開連接的時(shí)候
?? ??? ??? ??? ?必須去釋放掉資源。
?? ??? ??? ??? ?
?? ??? ??? ?情景模擬:
?? ??? ??? ??? ?客戶端?? ??? ??? ??? ??? ??? ??? ??? ??? ?服務(wù)器端
?? ??? ??? ??? ?我發(fā)送完了,我想斷開連接
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?ok,我知道了,稍等一下,我要準(zhǔn)備一下
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?過一會兒之后
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?好的,我已經(jīng)處理完了,可以斷開連接了
?? ??? ??? ??? ?OK,拜拜,下次見
?? ??? ??? ??? ?成功斷開連接
?? ??? ??? ??? ?
?? ??? ??? ?具體的過程:
?? ??? ??? ??? ?請見圖<四次揮手原理機(jī)制>
?? ??? ??? ??? ?
?? ??? ?2)?? ?TCP編程的流程
?? ??? ??? ?TCP Server
?? ??? ??? ??? ?socket:創(chuàng)建套接字
?? ??? ??? ??? ?bind:把一個(gè)套接字和網(wǎng)絡(luò)地址綁定在一起
?? ??? ??? ??? ??? ?如果你想讓其他人來主動連接你或者聯(lián)系你,
?? ??? ??? ??? ??? ?你就需要綁定一個(gè)地址,并且需要把這個(gè)地址告訴要連接你的人
?? ??? ??? ??? ?listen:讓套接字進(jìn)行監(jiān)聽模式
?? ??? ??? ??? ?accept:接受客戶端的連接?
?? ??? ??? ??? ??? ?多次調(diào)用accept就可以與不同的客戶端建立連接。
?? ??? ??? ??? ??? ?
?? ??? ??? ??? ?write/send/sendto or read/recv/recvfrom
?? ??? ??? ??? ?
?? ??? ??? ??? ?close/shutdown:“四次揮手”
?? ??? ??? ??? ?
?? ??? ??? ?TCP Client:
?? ??? ??? ??? ?socket
?? ??? ??? ??? ?bind:可綁定可不綁定
?? ??? ??? ??? ?connect:主動與TCP server建立連接--->“三次握手”
?? ??? ??? ??? ?
?? ??? ??? ??? ?write/send/sendto or read/recv/recvfrom
?? ??? ??? ??? ?
?? ??? ??? ??? ?close/shutdown:“四次揮手”
?? ??? ??? ??? ?
?? ?2.?? ?socket具體的API函數(shù)
?? ??? ?1)?? ?socket : 創(chuàng)建一個(gè)套接字
?? ??? ??? ?int socket(int domain,int type,int protocol);
?? ??? ??? ??? ?domain:指定域或者協(xié)議域。
?? ??? ??? ??? ??? ?socket接口不僅僅只局限于TCP/IP,它也可以用于Bluetooth,本地通信。。
?? ??? ??? ??? ??? ?那么每一種網(wǎng)絡(luò)通信下面都有自己的許多協(xié)議,我們就把IPv4下面的所有的
?? ??? ??? ??? ??? ?網(wǎng)絡(luò)協(xié)議,歸到了一個(gè)域:
?? ??? ??? ??? ??? ??? ?AF_INET : IPv4協(xié)議族
?? ??? ??? ??? ??? ??? ?AF_INET6 :IPv6協(xié)議族
?? ??? ??? ??? ??? ??? ?AF_BULETOOTH
?? ??? ??? ??? ??? ??? ?AF_UNIX/AF_LOCAL:Unix域協(xié)議族
?? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ?type:指定要創(chuàng)建的套接字的類型
?? ??? ??? ??? ??? ?SOCK_STRAM : 流式套接字 ---> TCP
?? ??? ??? ??? ??? ?SOCK_DGRAM : 數(shù)據(jù)報(bào)套接字 ---> UDP
?? ??? ??? ??? ??? ?SOCK_RAW : 原始套接字
?? ??? ??? ??? ?
?? ??? ??? ??? ?protocol:指定具體的應(yīng)用層的協(xié)議,可以指定為0(不知名的私有應(yīng)用協(xié)議)
?? ??? ??? ??? ?
?? ??? ??? ??? ?返回值:成功返回一個(gè)套接字的描述符(> 0,文件描述符)
?? ??? ??? ??? ??? ?失敗返回-1,同時(shí)errno被設(shè)置。
?? ??? ??? ??? ??? ?
?? ??? ?2)?? ?網(wǎng)絡(luò)地址結(jié)構(gòu)體
?? ??? ??? ?socket接口它不僅僅可以用于以太網(wǎng)(IPv4),也可以用于IPv6,同時(shí)也可以用于bluetooth
?? ??? ??? ?,不同的協(xié)議族,他們的地址是不一樣的。
?? ??? ??? ?
?? ??? ??? ?但是我們在所有的socket進(jìn)行網(wǎng)絡(luò)編程時(shí),必須要指定對方的網(wǎng)絡(luò)地址,所以
?? ??? ??? ?我們需要有一個(gè)統(tǒng)一的標(biāo)準(zhǔn)對這些地址進(jìn)行一個(gè)描述。
?? ??? ?
?? ??? ??? ?struct sockaddr
?? ??? ??? ?{
?? ??? ??? ??? ?sa_family_t sa_family;//指定協(xié)議(地址)族
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?//sa_family_t--->unsigned short
?? ??? ??? ??? ?char sa_data[14];//包含套接字中的目標(biāo)地址和端口信息
?? ??? ??? ?};
?? ??? ??? ?缺陷:IP地址和端口號混在一起保存在sa_data這個(gè)數(shù)組中的。
?? ??? ??? ?
?? ??? ??? ?struct sockaddr_in
?? ??? ??? ?{
?? ??? ??? ??? ?sa_family_t sa_family;//指定協(xié)議(地址)族
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?//sa_family_t--->unsigned short
?? ??? ??? ??? ?u_int16_t sin_port;//端口號
?? ??? ??? ??? ?struct in_addr sin_addr;//IP地址
?? ??? ??? ??? ?char sin_zero[8];//填充8個(gè)字節(jié),無實(shí)際意義的,只是為了和其他協(xié)議族的地址
?? ??? ??? ??? ??? ??? ??? ??? ??? ?//結(jié)構(gòu)體大小一樣
?? ??? ??? ?};
?? ??? ??? ?typedef uint32_t in_addr_t;
?? ??? ??? ?struct in_addr
?? ??? ??? ?{
?? ??? ??? ??? ?in_addr_t s_addr;
?? ??? ??? ?}
?? ??? ??? ?
?? ??? ??? ?這個(gè)結(jié)構(gòu)體將端口號和IP地址分開保存的。
?? ??? ??? ?
?? ??? ??? ?如:
?? ??? ??? ?struct sockaddr_in local;
?? ??? ??? ?local.sin_family = AF_INET;
?? ??? ??? ?local.sin_addr.s_addr = "192.168.31.30";//error
?? ??? ??? ?
?? ??? ?3)?? ?IP地址轉(zhuǎn)換函數(shù)
?? ??? ??? ?IP地址是以點(diǎn)分十進(jìn)制的形式存在的。
?? ??? ??? ?
?? ??? ??? ?函數(shù)將點(diǎn)分十進(jìn)制形式存在IP地址轉(zhuǎn)換為in_addr_t類型
?? ??? ??? ??? ?
?? ??? ??? ?#include <sys/socket.h>
?? ??? ??? ?#include <netinet/in.h>
?? ??? ??? ?#include <arpa/inet.h>
?? ??? ??? ?a:addr 點(diǎn)分十進(jìn)制字符串
?? ??? ??? ?n:network 網(wǎng)絡(luò)地址
?? ??? ??? ?aton:將點(diǎn)分十進(jìn)制字符串IP地址---> struct in_addr
?? ??? ??? ?
?? ??? ??? ?int inet_aton(const char *cp, struct in_addr *inp);
?? ??? ??? ??? ?cp:指向要轉(zhuǎn)換的點(diǎn)分十進(jìn)制IP地址字符串
?? ??? ??? ??? ??? ?如:"192.168.31.30"
?? ??? ??? ??? ?inp:指向一個(gè)IP的地址結(jié)構(gòu)體
?? ??? ??? ??? ??? ?用來保存轉(zhuǎn)換后的IP地址(32bits的數(shù))。
?? ??? ??? ?in_addr_t inet_addr(const char *cp);
?? ??? ??? ??? ?inet_addr把cp指向的“點(diǎn)分十進(jìn)制形式的IP字符串”轉(zhuǎn)換成IP的網(wǎng)絡(luò)地址結(jié)構(gòu)體in_addr_t
?? ??? ??? ?in_addr_t inet_network(const char *cp);
?? ??? ??? ??? ?功能與inet_addr類似
?? ??? ??? ?char *inet_ntoa(struct in_addr in);
?? ??? ??? ??? ?把IP結(jié)構(gòu)體struct in_addr轉(zhuǎn)換成一個(gè)點(diǎn)分十進(jìn)制的IP字符串
?? ??? ??? ??? ?
?? ??? ??? ?例子:
?? ??? ??? ??? ?struct sockaddr_in local;
?? ??? ??? ??? ?local.sin_family = AF_INET;
?? ??? ??? ??? ?local.sin_addr.s_addr = "192.168.31.30";//error
?? ??? ??? ??? ?local.sin_addr.s_addr = inet_addr("192.168.31.30");
?? ??? ??? ??? ?inet_aton("192.168.31.30",&local.sin_addr);
?? ??? ??? ??? ?local.sin_port = 7878;//error
?? ??? ??? ??? ?
?? ??? ?4)?? ?整數(shù)在主機(jī)字節(jié)序與網(wǎng)絡(luò)字節(jié)序之間的轉(zhuǎn)換函數(shù)
?? ??? ??? ?#include <arpa/inet.h>
?? ??? ??? ?
?? ??? ??? ?h:host ?? ?n:network
?? ??? ??? ?l:long ?? ?s:short
?? ??? ??? ?uint32_t htonl(uint32_t hostlong);
?? ??? ??? ??? ?把一個(gè)32bits的整數(shù)的主機(jī)字節(jié)序轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)序
?? ??? ??? ?uint16_t htons(uint16_t hostshort);
?? ??? ??? ??? ?把一個(gè)16bits的整數(shù)的主機(jī)字節(jié)序轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)序
?? ??? ??? ?uint32_t ntohl(uint32_t netlong);
?? ??? ??? ??? ?把一個(gè)32bits的整數(shù)的網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)換成主機(jī)字節(jié)序
?? ??? ??? ?uint16_t ntohs(uint16_t netshort);
?? ??? ??? ??? ?把一個(gè)16bits的整數(shù)的網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)換成主機(jī)字節(jié)序
?? ??? ??? ??? ?struct sockaddr_in local;
?? ??? ??? ??? ?local.sin_family = AF_INET;
?? ??? ??? ??? ?local.sin_addr.s_addr = "192.168.31.30";//error
?? ??? ??? ??? ?local.sin_addr.s_addr = inet_addr("192.168.31.30");
?? ??? ??? ??? ?inet_aton("192.168.31.30",&local.sin_addr);
?? ??? ??? ??? ?local.sin_port = 7878;//error?? ??? ?
?? ??? ??? ??? ?local.sin_port = htons(7878);//error?? ??? ?
?? ??? ??? ?
?? ??? ?5)?? ?bind:把一個(gè)IPv4的網(wǎng)絡(luò)地址綁定到一個(gè)socket上面去
?? ??? ??? ?#include <sys/types.h> ? ? ? ? ?/* See NOTES */
?? ??? ??? ?#include <sys/socket.h>
?? ??? ??? ?int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
?? ??? ??? ??? ?sockfd:要綁定地址的套接字的描述符
?? ??? ??? ??? ?addr:通用網(wǎng)絡(luò)地址結(jié)構(gòu)的指針
?? ??? ??? ??? ?addrlen:指定第二個(gè)實(shí)參指向的地址結(jié)構(gòu)體的長度
?? ??? ??? ?
?? ??? ??? ??? ?返回值:成功返回0,失敗返回-1
?? ??? ??? ??? ?
?? ??? ?6)?? ?listen:讓套接字進(jìn)入監(jiān)聽模式
?? ??? ??? ?NAME
?? ??? ??? ??? ?listen - listen for connections on a socket
?? ??? ??? ?SYNOPSIS
?? ??? ??? ??? ?#include <sys/types.h> ? ? ? ? ?/* See NOTES */
?? ??? ??? ??? ?#include <sys/socket.h>
?? ??? ??? ??? ?int listen(int sockfd, int backlog);
?? ??? ??? ??? ??? ?sockfd:要進(jìn)入監(jiān)聽模式的套接字的描述符
?? ??? ??? ??? ??? ?backlog:同時(shí)能夠處理連接請求的數(shù)目
?? ??? ??? ??? ??? ??? ?比如:5,10.....
?? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ?返回值:成功返回0,失敗返回-1,同時(shí)errno被設(shè)置。
?? ??? ??? ??? ??? ?
?? ??? ??? ??? ?調(diào)用成功之后,套接字將會變成"監(jiān)聽套接字"。
?? ??? ??? ?
?? ??? ?7)?? ?accept?? ?
?? ??? ??? ?#include <sys/types.h> ? ? ? ? ?/* See NOTES */
?? ??? ??? ?#include <sys/socket.h>
?? ??? ??? ?int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
?? ??? ??? ??? ?用于TCP server接收一個(gè)來自客戶端的TCP連接建立的請求。
?? ??? ??? ??? ?sockfd:一個(gè)監(jiān)聽套接字
?? ??? ??? ??? ?addr:網(wǎng)絡(luò)地址結(jié)構(gòu)體的指針,用來保存客戶端的地址信息的。
?? ??? ??? ??? ?addrlen:網(wǎng)絡(luò)地址結(jié)構(gòu)體的長度類型的指針,
?? ??? ??? ??? ?用來保存客戶端地址結(jié)構(gòu)體的長度。
?? ??? ??? ??? ?返回值:成功返回與該客戶端的連接套接字描述符,后續(xù)與該客戶端進(jìn)行數(shù)據(jù)交換
?? ??? ??? ??? ?都是通過該連接套接字描述符。失敗返回-1,同時(shí)errno被設(shè)置。
?? ??? ?8)?? ?connect
?? ??? ?#include <sys/types.h> ? ? ? ? ?/* See NOTES */
?? ??? ?#include <sys/socket.h>
?? ??? ?int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
?? ??? ??? ?sockfd:套接字的文件描述符
?? ??? ??? ?addr:對方的地址,tcp server的地址。
?? ??? ??? ?addrlen:對方的地址結(jié)構(gòu)體的大小
?? ??? ??? ?返回值:成功返回0,失敗返回-1,同時(shí)errno被設(shè)置。
?? ??? ?
?? ??? ?9)?? ?往套接字上發(fā)送數(shù)據(jù)
?? ??? ??? ?write/send/sendto
?? ??? ??? ?TCP都可以使用這三個(gè)函數(shù),而UDP只能用sendto
?? ??? ??? ?1.?? ?write
?? ??? ??? ??? ?略
?? ??? ??? ?2.?? ?send
?? ??? ??? ??? ?#include <sys/types.h>
?? ??? ??? ??? ?#include <sys/socket.h>
?? ??? ??? ??? ?ssize_t send(int sockfd, const void *buf, size_t len, int flags);
?? ??? ??? ??? ??? ?sockfd:你要往哪一個(gè)套接字上發(fā)送數(shù)據(jù)
?? ??? ??? ??? ??? ?buf:你要發(fā)送的數(shù)據(jù)的地址
?? ??? ??? ??? ??? ?len:你要發(fā)送的數(shù)據(jù)的長度
?? ??? ??? ??? ??? ?flags:一般為0.
?? ??? ??? ??? ??? ?返回值:成功返回實(shí)際發(fā)送的字節(jié)數(shù),失敗返回-1,同時(shí)errno被設(shè)置。
?? ??? ??? ?
?? ??? ??? ?3.?? ?ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
?? ??? ??? ??? ?const struct sockaddr *dest_addr, socklen_t addrlen);
?? ??? ??? ??? ?前面四個(gè)參數(shù)與send一樣。
?? ??? ??? ??? ?dest_addr:指定接收方的地址,是一個(gè)網(wǎng)絡(luò)地址結(jié)構(gòu)體。
?? ??? ??? ??? ??? ?如果TCP協(xié)議通信,此處你可以省略。
?? ??? ??? ?
?? ??? ??? ??? ?addrlen:
?? ??? ??? ??? ??? ?dest_addr指向的那個(gè)地址結(jié)構(gòu)體的的長度
?? ??? ??? ??? ?返回值:成功返回實(shí)際發(fā)送的字節(jié)數(shù),失敗返回-1,同時(shí)errno被設(shè)置。
?? ??? ?10)?? ?從套接字上接收數(shù)據(jù)
?? ??? ??? ?read/read/recv/recvfrom
?? ??? ??? ?1.?? ?read
?? ??? ??? ??? ?略
?? ??? ??? ??? ?read(fd,buf,sizeof(buf))
?? ??? ??? ?
?? ??? ??? ?2.?? ?recv
?? ??? ??? ??? ?ssize_t recv(int sockfd, void *buf, size_t len, int flags);
?? ??? ??? ??? ??? ?recv前面的三個(gè)參數(shù)與read類似。
?? ??? ??? ??? ??? ?flags:一般為0。
?? ??? ??? ??? ??? ?返回值:成功返回讀取到的字節(jié)的個(gè)數(shù),失敗返回-1,同時(shí)errno被設(shè)置。
?? ??? ??? ??? ?
?? ??? ??? ??? ?ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
? ? ? ? ? ? ? ? ? ? ? ? struct sockaddr *src_addr, socklen_t *addrlen);
?? ??? ??? ??? ??? ?src_addr:用來保存發(fā)送發(fā)的地址
?? ??? ??? ??? ??? ?addrlen:用來保存發(fā)送者地址結(jié)構(gòu)體信息的長度
?? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ?返回值:成功返回實(shí)際接收到的字節(jié)數(shù),失敗返回-1.同時(shí)errno被設(shè)置。
?? ??? ??? ??? ??? ?
?? ??? ?11)?? ?關(guān)閉套接字(close/shutdown)
?? ??? ??? ?#include <sys/socket.h>
?? ??? ??? ?int shutdown(int sockfd, int how);
?? ??? ??? ??? ?sockfd:要關(guān)閉的套接字的文件描述符
?? ??? ??? ??? ?how:關(guān)閉方式,有以下三種:
?? ??? ??? ??? ??? ?SHUT_RD:關(guān)閉讀
?? ??? ??? ??? ??? ?SHUT_WR:關(guān)閉寫
?? ??? ??? ??? ??? ?SHUT_RDWR:關(guān)閉讀寫--->close(sockfd);
?? ??? ??? ??? ?返回值:
?? ??? ??? ??? ??? ?成功返回0,失敗返回-1,同時(shí)errno被設(shè)置。
總結(jié)