如何制作一個注冊網(wǎng)站建個網(wǎng)站需要多少錢
TCP 通信三大步驟:
1 三次握手建立連接;
2 開始通信,進行數(shù)據(jù)交換;
3 四次揮手?jǐn)嚅_連接;
一、TCP內(nèi)部原理--三次握手
【第一次握手】套接字A∶"你好,套接字B。我這兒有數(shù)據(jù)要傳給你,建立連接吧。"
【第二次握手】套接字B∶"好的,我這邊已就緒。"
【第三次握手】套接字A∶"謝謝你受理我的請求。"
首先,請求連接的主機A 向主機B 傳遞如下信息∶
[SYN] SEQ:1000, ACK: -
該消息中SEQ 為1000,ACK 為空,而SEQ 為1000 的含義如下∶
"現(xiàn)傳遞的數(shù)據(jù)包序號為1000,如果接收無誤,請通知我向您傳遞1001 號數(shù)據(jù)包。"這是首
次請求連接時使用的消息,又稱SYN。SYN 是Synchronization 的簡寫,表示收發(fā)數(shù)據(jù)前傳輸
的同步消息。
接下來主機B 向A 傳遞如下消息∶
[SYN+ACK]SEQ:2000, ACK:1001
此時SEQ 為2000,ACK 為1001,而SEQ 為2000 的含義如下∶
"現(xiàn)傳遞的數(shù)據(jù)包序號為2000 如果接收無誤,請通知我向您傳遞2001 號數(shù)據(jù)包。"
而ACK1001 的含義如下∶
"剛才傳輸?shù)腟EQ 為1000 的數(shù)據(jù)包接收無誤,現(xiàn)在請傳遞SEQ 為1001 的數(shù)據(jù)包。"
對主機A 首次傳輸?shù)臄?shù)據(jù)包的確認(rèn)消息(ACK1001)和為主機B 傳輸數(shù)據(jù)做準(zhǔn)備的同步消息
(SEQ2000)擁綁發(fā)送,因此,此種類型的消息又稱SYN+ACK。
收發(fā)數(shù)據(jù)前向數(shù)據(jù)包分配序號,并向?qū)Ψ酵▓蟠诵蛱?#xff0c;這都是為防止數(shù)據(jù)丟失所做的準(zhǔn)備。
通過向數(shù)據(jù)包分配序號并確認(rèn),可以在數(shù)據(jù)丟失時馬上查看并重傳丟失的數(shù)據(jù)包。因此,TCP
可以保證可靠的數(shù)據(jù)傳輸。最后觀察主機A 向主機B 傳輸?shù)南ⅰ?br /> [ACK]SEQ:1001, ACK:2001
TCP 連接過程中發(fā)送數(shù)據(jù)包時需分配序號。
在之前的序號1000 的基礎(chǔ)上加1,也就是分配1001。此時該數(shù)據(jù)包傳遞如下消息∶
"已正確收到傳輸?shù)腟EQ 為2000 的數(shù)據(jù)包,現(xiàn)在可以傳輸SEQ 為2001 的數(shù)據(jù)包。"
這樣就傳輸了添加ACK2001 的ACK 消息。至此,主機A 和主機B 確認(rèn)了彼此均就緒。
特么的,文字太復(fù)雜了,來個通俗易懂的。
TCP 三次握手好比在一個夜高風(fēng)黑的夜晚,你一個人在小區(qū)里散步,不遠處看見小區(qū)里的
一位漂亮妹子迎面而來,但是因為路燈有點暗等原因不能100%確認(rèn),所以要通過招手的方
式來確定對方是否認(rèn)識自己。
你首先向妹子招手(syn),妹子看到你向自己招手后,向你點了點頭擠出了一個微笑
(ack)。你看到妹子微笑后確認(rèn)了妹子成功辨認(rèn)出了自己(進入established 狀態(tài))。
但是妹子有點不好意思,向四周看了一看,有沒有可能你是在看別人呢,她也需要確認(rèn)一下。
妹子也向你招了招手(syn),你看到妹子向自己招手后知道對方是在尋求自己的確認(rèn),于是
也點了點頭擠出了微笑(ack),妹子看到對方的微笑后確認(rèn)了你就是在向自己打招呼(進入
established 狀態(tài))。
二、TCP內(nèi)部原理--四次揮手
三、UDP編程--UDP基本原理
????????在4 層TCP/IP 模型中,第二層傳輸(Transport)層分為TCP 和UDP 這2 種。數(shù)據(jù)交換
過程可以分為通過TCP 套接字完成的TCP 方式和通過UDP 套接字完成的UDP 方式。
UDP 套接字的特點:
????????我們可以通過信件說明UDP 的工作原理,這是講解UDP 時使用的傳統(tǒng)示例,它與UDP
特性完全相符。寄信前應(yīng)先在信封上填好寄信人和收信人的地址,之后貼上郵票放進郵筒
即可。當(dāng)然,信件的特點使我們無法確認(rèn)對方是否收到。另外,郵寄過程中也可能發(fā)生信件
丟失的情況。也就是說,信件是一種不可靠的傳輸方式。與之類似,UDP 提供的同樣是不可
靠的數(shù)據(jù)傳輸服務(wù)。
"既然如此,TCP 應(yīng)該是更優(yōu)質(zhì)的協(xié)議吧?"
????????如果只考慮可靠性,TCP 的確比UDP 好。但UDP 在結(jié)構(gòu)上比TCP 更簡潔。UDP 不會發(fā)
送類似ACK 的應(yīng)答消息,也不會像SEQ 那樣給數(shù)據(jù)包分配序號。因此,UDP 的性能有時比
TCP 高出很多。編程中實現(xiàn)UDP 也比TCP 簡單。另外,UDP 的可靠性雖比不上TCP,但也不
會像想象中那么頻繁地發(fā)生數(shù)據(jù)損毀。因此,在更重視性能而非可靠性的情況下,UDP 是一
種很好的選擇。
????????既然如此,UDP 的作用到底是什么呢?為了提供可靠的數(shù)據(jù)傳輸服務(wù),TCP 在不可靠的
IP 層進行流控制,而UDP 就缺少這種流控制機制。
????????流控制是區(qū)分UDP 和TCP 的最重要的標(biāo)志。但若從TCP 中除去流控制,所剩內(nèi)容也屈
指可數(shù)。也就是說,TCP 的生命在于流控制。
????????如果把TCP 比喻為電話,把UDP 比喻為信件。但這只是形容協(xié)議工作方式,并沒有包
含數(shù)據(jù)交換速率。請不要誤認(rèn)為"電話的速度比信件快,因此TCP 的數(shù)據(jù)收發(fā)速率也比UDP
快"。實際上正好相反。TCP 的速度無法超過UDP,但在收發(fā)某些類型的數(shù)據(jù)時有可能接近
UDP。例如,每次交換的數(shù)據(jù)量越大,TCP 的傳輸速率就越接近UDP 的傳輸速率。
????????從上圖可以看出,IP 的作用就是讓離開主機B 的UDP 數(shù)據(jù)包準(zhǔn)確傳遞到主機A。但把
UDP 包最終交給主機A 的某一UDP 套接字的過程則是由UDP 完成的。UDP 最重要的作用就
是根據(jù)端口號將傳到主機的數(shù)據(jù)包交付給最終的UDP 套接字。
????????其實在實際的應(yīng)用場景中,UDP 也具有一定的可靠性。網(wǎng)絡(luò)傳輸特性導(dǎo)致信息丟失頻發(fā),
可若要傳遞壓縮文件(發(fā)送1 萬個數(shù)據(jù)包時,只要丟失1 個就會產(chǎn)生問題),則必須使用
TCP,因為壓縮文件只要丟失一部分就很難解壓。但 通過網(wǎng)絡(luò)實時傳輸視頻或音頻時的情況
有所不同。對于多媒體數(shù)據(jù)而言,丟失一部分也沒有太大問題,這只會引起短暫的畫面抖動,
或出現(xiàn)細微的雜音。但因為需要提供實時服務(wù),速度就成為非常重要的因素,此時需要考慮
使用UDP。但UDP 并非每次都快于TCP,TCP 比UDP 慢的原因通常有以下兩點。
1 收發(fā)數(shù)據(jù)前后進行的連接設(shè)置及清除過程。
2 收發(fā)數(shù)據(jù)過程中為保證可靠性而添加的流控制。
尤其是收發(fā)的數(shù)據(jù)量小但需要頻繁連接時,UDP 比TCP 更高效。?
四、UDP服務(wù)端(上)
UDP 中的服務(wù)器端和客戶端沒有連接
????????UDP 服務(wù)器端/客戶端不像TCP 那樣在連接狀態(tài)下交換數(shù)據(jù),因此與TCP 不同,無需經(jīng)
過連接過程。也就是說,不必調(diào)用TCP 連接過程中調(diào)用的listen 函數(shù)和accept 函數(shù)。UDP 中
只有創(chuàng)建套接字的過程和數(shù)據(jù)交換過程。
UDP 服務(wù)器端和客戶端均只需1 個套接字
????????TCP 中,套接字之間應(yīng)該是一對一的關(guān)系。若要向10 個客戶端提供服務(wù),則除了守門
的服務(wù)器套接字外,還需要10 個服務(wù)器端套接字。但在UDP 中,不管是服務(wù)器端還是客戶
端都只需要1 個套接字。之前解釋UDP 原理時舉了信件的例子,收發(fā)信件時使用的郵筒可
以比喻為UDP 套接字。只要附近有1 個郵筒,就可以通過它向任意地址寄出信件。同樣,
只需1 個UDP 套接字就可以向任意主機傳輸數(shù)據(jù)
????????上圖展示了1 個UDP 套接字與2 個不同主機交換數(shù)據(jù)的過程。也就是說,只需1 個UDP
套接字就能和多臺主機通信。
????????創(chuàng)建好TCP 套接字后,傳輸數(shù)據(jù)時無需再添加地址信息。因為TCP 套接字將保持與對方
套接字的連接。換言之,TCP 套接字知道目標(biāo)地址信息。但UDP 套接字不會保持連接狀態(tài)(UDP
套接字只有簡單的郵筒功能),因此每次傳輸數(shù)據(jù)都要添加目標(biāo)地址信息。這相當(dāng)于寄信前
在信件中填寫地址。以下為:填寫地址并傳輸數(shù)據(jù)時調(diào)用的UDP 相關(guān)函數(shù)。?
發(fā)送:
#include<sys/socket.h>
ssize_t sendto(int sock,void*buff,size_t nbytes,int flags,struct sockaddr *to, socklen_t addrlen);
→成功時返回傳輸?shù)淖止?jié)數(shù),失敗時返回-1。
● sock
用于傳輸數(shù)據(jù)的UDP 套接字文件描述符。
● buff
保存待傳輸數(shù)據(jù)的緩沖地址值。
● nbytes
待傳輸?shù)臄?shù)據(jù)長度,以字節(jié)為單位。
● flags
可選項參數(shù),若沒有則傳遞0。
● to
存有目標(biāo)地址信息的sockaddr 結(jié)構(gòu)體變量的地址值。
● addrlen
傳遞給參數(shù)to 的地址值結(jié)構(gòu)體變量長度。
????????上述函數(shù)與之前的TCP 輸出函數(shù)最大的區(qū)別在于,此函數(shù)需要向它傳遞目標(biāo)地址信息。接
下來介紹接收UDP 數(shù)據(jù)的函數(shù)。UDP 數(shù)據(jù)的發(fā)送端并不固定,因此該函數(shù)定義為可接收發(fā)
送端信息的形式,也就是將同時返回UDP 數(shù)據(jù)包中的發(fā)送端信息。
接收:
#include<sys/socket.h>
ssize_t recvfrom(int sock, void *buff,size_t nbytes, int flags,struct sockaddr*from, socklen_t*addrlen);
→成功時返回接收的字節(jié)數(shù),失敗時返回-1。
●sock 用于接收數(shù)據(jù)的UDP 套接字文件描述符。
●buff 保存接收數(shù)據(jù)的緩存地址值
●nbytes 可接收的最大字節(jié)數(shù),故無法超過參數(shù)buf 所指的緩沖大小。
●flags 可選項參數(shù),若沒有則傳入0。
●from 存有發(fā)送端地址信息的sockaddr 結(jié)構(gòu)體變量的地址值。
●addrlen 保存參數(shù)from 的結(jié)構(gòu)體變量長度的變量地址值。
編寫UDP 程序時最核心的部分就在于上述兩個函數(shù),這也說明二者在UDP 數(shù)據(jù)傳輸中
的地位。
注意:UDP是DDOS攻擊的一個最主要的形式,因為他是無法拒收的。
五、UDP服務(wù)端(下)
int lession73(int argc, char* argv[])
{printf("server start");system("echo 'server start' > /output.txt");int ser_sock = -1;char message[1024] = "";struct sockaddr_in servaddr, clientaddr;socklen_t clientlen = 0;if (argc != 2) {printf("usage:% <port>\n", argv[0]);handle_error("argement is error:");}ser_sock = socket(PF_INET, SOCK_DGRAM, 0); //UDPif (ser_sock == -1) {handle_error("create socket failed:");}servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //127.0.0.1servaddr.sin_port = htons((short)atoi(argv[1]));if (bind(ser_sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1) {handle_error("bind failed:");}for (int i = 0; i < 50; i++) {system("echo 'server start 0' > /output.txt");clientlen = sizeof(clientaddr);ssize_t len = recvfrom(ser_sock, message, sizeof(message), 0, (struct sockaddr*)&clientaddr, &clientlen);system("echo 'server start 2' > /output.txt");sendto(ser_sock, message, len, 0, (struct sockaddr*)&clientaddr, clientlen);}printf("server ok");close(ser_sock);return 0;
}
六、UDP客戶端
int lession74(int argc, char* argv[]) {int client_sock;struct sockaddr_in serv_addr;socklen_t serv_len = sizeof(serv_addr);char massege[1024] = "";//校驗參數(shù)if (argc != 3) {printf("usge:%s ip port\n", argv[0]);handle_error("argement error!");}client_sock = socket(AF_INET, SOCK_DGRAM, 0);if (client_sock == -1) {handle_error("soket create failed!");}memset(&serv_addr, 0, sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = inet_addr(argv[1]);serv_addr.sin_port = htons((short)atoi(argv[2]));while (1) {printf("input massege(Q to quit):");scanf("%s", massege);if ((strcmp(massege, "Q") == 0) || (strcmp(massege, "q") == 0)) {break;}printf("Sending message: '%s' with length: %zu\n", massege, strlen(massege));//printf("Sending message: '%s' with length: %zu\n", massege, strlen(massege));printf("debug:%s", massege);ssize_t len=sendto(client_sock, massege, strlen(massege), 0, (sockaddr*)&serv_addr, serv_len);memset(massege, 0, (unsigned int)len);recvfrom(client_sock, massege, sizeof(massege), 0, (sockaddr*)&serv_addr, &serv_len);printf("recv:%s\n", massege);}close(client_sock);return 0;}
七、UDP的傳輸特性和調(diào)用??
????????前面講解了UDP 服務(wù)器端/客戶端的實現(xiàn)方法。但如果仔細觀察UDP 客戶端會發(fā)現(xiàn),它
缺少把IP 和端口分配給套接字的過程。TCP 客戶端調(diào)用connect 函數(shù)自動完成此過程,而
UDP 中連能承擔(dān)相同功能的函數(shù)調(diào)用語句都沒有。究竟在何時分配IP 和端口號呢?
UDP 程序中,調(diào)用sendto 函數(shù)傳輸數(shù)據(jù)前應(yīng)完成對套接字的地址分配工作,因此調(diào)用bind
函數(shù)。當(dāng)然,bind 函數(shù)在TCP 程序中出現(xiàn)過,但bind 函數(shù)不區(qū)分TCP 和UDP,也就是說,
在UDP 程序中同樣可以調(diào)用。另外,如果調(diào)用sendto 函數(shù)時發(fā)現(xiàn)尚未分配地址信息,則在
首次調(diào)用sendto 函數(shù)時給相應(yīng)套接字自動分配IP 和端口。而且此時分配的地址一直保留到
程序結(jié)束為止,因此也可用來與其他UDP 套接字進行數(shù)據(jù)交換。當(dāng)然,IP 用主機IP,端口
號選尚未使用的任意端口號。
綜上所述,調(diào)用sendto 函數(shù)時自動分配IP 和端口號,因此,UDP 客戶端中通常無需額
外的地址分配過程。
八、SO_REUSEADDR
void client78() {int client = socket(PF_INET, SOCK_STREAM, 0);struct sockaddr_in servaddr;memset(&servaddr, 0, sizeof(servaddr)); //清零 防止意外servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");servaddr.sin_port = htons(33005);int ret = connect(client, (struct sockaddr*)&servaddr, sizeof(servaddr));while (ret == 0) {printf("%s(%d):%s\r\n", __FILE__, __LINE__, __FUNCTION__);char buffer[256] = "";fputs("input message(Q to quit):", stdout);//輸出提示符fgets(buffer, sizeof(buffer), stdin/*標(biāo)準(zhǔn)輸入流*/);//讀入一行if ((strcmp(buffer, "Q\n") == 0) || (strcmp(buffer, "q\n") == 0)) {break;}size_t len = strlen(buffer);size_t send_len = 0;while (send_len < len) {ssize_t ret = write(client, buffer + send_len, len - send_len);//發(fā)給服務(wù)器if (ret <= 0){fputs("write failed!\n", stdout);//close(client);std::cout << "client done!" << std::endl;return;}send_len += (size_t)ret;}memset(buffer, 0, sizeof(buffer));size_t read_len = 0;while (read_len < len){ssize_t ret = read(client, buffer + read_len, len - read_len);if (ret <= 0){fputs("read failed!\n", stdout);//close(client);std::cout << "client done!" << std::endl;return;}send_len += (size_t)ret;}std::cout << "from server:" << buffer;}//close(client);std::cout << "client done!" << std::endl;
}
void server78() {printf("%s(%d):%s\r\n", __FILE__, __LINE__, __FUNCTION__);int sock,client,optval=0;struct sockaddr_in addr,cli;socklen_t addrlen=sizeof(addr);char message[256] = "";sock = socket(PF_INET, SOCK_STREAM, 0);getsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, &addrlen);printf("SO_REUSEADDR=%d\n", optval);optval = 1;setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));getsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, &addrlen);printf("SO_REUSEADDR=%d\n", optval);memset(&addr, 0, sizeof(addr));addr.sin_family = AF_INET;addr.sin_addr.s_addr = inet_addr("127.0.0.1");addr.sin_port = htons(33005);addrlen = sizeof(addr);if (bind(sock, (struct sockaddr*)&addr, addrlen) == -1) {handle_error("bind failed!");}listen(sock, 3);client = accept(sock, (struct sockaddr*)&cli, &addrlen);read(client, message, sizeof(message));close(client);close(sock);return;
}
void lession78(char*option){if (strcmp(option, "1") == 0) {//服務(wù)器server78();server78();server78();server78();server78();server78();server78();}else {//客戶端client78();}}
九、TCP_NODELAY
"什么是Nagle 算法?使用該算法能夠獲得哪些數(shù)據(jù)通信特性?"
Nagle 算法是以他的發(fā)明人John Nagle 的名字命名的,它用于自動連接許多的小緩沖
器消息;這一過程(稱為nagling)通過減少必須發(fā)送包的個數(shù)來增加網(wǎng)絡(luò)軟件系統(tǒng)的效率。
從上圖中可以得到如下結(jié)論:
????????"只有收到前一數(shù)據(jù)的ACK 消息時,Nagle 算法才發(fā)送下一數(shù)據(jù)。"
????????TCP 套接字默認(rèn)使用Nagle 算法交換數(shù)據(jù),因此最大限度地進行緩沖,直到收到ACK。
上圖左側(cè)正是這種情況。為了發(fā)送字符串"Nagle",將其傳遞到輸出緩沖。這時頭字符"N"之
前沒有其他數(shù)據(jù)(沒有需接收的ACK),因此立即傳輸。之后開始等待字符"N"的ACK 消息,
等待過程中,剩下的"agle"填入輸出緩沖。接下來,收到字符"N"的ACK 消息后,將輸出緩沖
的"agle"裝入一個數(shù)據(jù)包發(fā)送。也就是說,共需傳遞4 個數(shù)據(jù)包以傳輸1 個字符串。
????????接下來分析未使用Nagle 算法時發(fā)送字符串"Nagle"的過程。假設(shè)字符"N"到"e"依序傳到
輸出緩沖。此時的發(fā)送過程與ACK 接收與否無關(guān),因此數(shù)據(jù)到達輸出緩沖后將立即被發(fā)送
出去。從上圖右側(cè)可以看到,發(fā)送字符串"Nagle"時共需10 個數(shù)據(jù)包。由此可知,不使用Nagle
算法將對網(wǎng)絡(luò)流量產(chǎn)生負面影響。即使只傳輸1 個字節(jié)的數(shù)據(jù),其頭信息都有可能是幾十個
字節(jié)。因此,為了提高網(wǎng)絡(luò)傳輸效率,必須使用Nagle 算法。
????????在程序中將字符串傳給輸出緩沖時并不是逐字傳遞的,故發(fā)送字符串"Nagle"的實際情
況并非如上圖所示。但如果隔一段時間再把構(gòu)成字符串的字符傳到輸出緩沖(如果存在此
類數(shù)據(jù)傳遞)的話,則有可能產(chǎn)生類似上圖的情況。上圖中就是隔一段時間向輸出緩沖傳遞
待發(fā)送數(shù)據(jù)的。
????????但Nagle 算法并不是什么時候都適用。根據(jù)傳輸數(shù)據(jù)的特性,網(wǎng)絡(luò)流量未受太大影響時,
不使用Nagle 算法要比使用它時傳輸速度快。最典型的是"傳輸大文件數(shù)據(jù)"。將文件數(shù)據(jù)傳
入輸出緩沖不會花太多時間,因此,即便不使用Nagle 算法,也會在裝滿輸出緩沖時傳輸數(shù)
據(jù)包。這不僅不會增加數(shù)據(jù)包的數(shù)量,反而會在無需等待ACK 的前提下連續(xù)傳輸,因此可
以大大提高傳輸速度。
????????一般情況下,不適用Nagle 算法可以提高傳輸速度。但如果無條件放棄使用Nagle 算法,
就會增加過多的網(wǎng)絡(luò)流量,反而會影響傳輸。因此,未準(zhǔn)確判斷數(shù)據(jù)特性時不應(yīng)禁用Nagle
算法。
????????剛才說過的"大文件數(shù)據(jù)"應(yīng)禁用Nagle 算法。換言之,如果有必要,就應(yīng)禁用Nagle 算
法。"Nagle 算法使用與否在網(wǎng)絡(luò)流量上差別不大,使用Nagle 算法的傳輸速度更慢"禁用方
法非常簡單。
十、IO緩存大小
????????我們進行套接字編程時往往只關(guān)注數(shù)據(jù)通信,而忽略了套接字具有的不同特性。但是,理解
這些特性并根據(jù)實際需要進行更改也十分重要。
????????從上表可以看出,套接字可選項是分層的。IPPROTOIP 層可選項是IP 協(xié)議相關(guān)事項,
IPPROTO_TCP 層可選項是TCP 協(xié)議相關(guān)的事項,SOL_SOCKET 層是套接字相關(guān)的通用可選項。
????????也許有人看到表格會產(chǎn)生畏懼感,但我們真的無需全部背下來或理解,因此不必有負擔(dān)。實
際能夠設(shè)置的可選項數(shù)量是上表的好幾倍,也無需一下子理解所有可選項,實際開發(fā)中逐一
掌握即可。接觸的可選項多了,自然會掌握大部分重要的。
getsockopt & setsockopt
????????我們幾乎可以針對上表中的所有可選項進行讀取(Get)和設(shè)置(Set)(當(dāng)然,有些可選項
只能進行一種操作)??蛇x項的讀取和設(shè)置通過如下2 個函數(shù)完成。
#include<sys/socket.h>
int getsockopt(int sock, int level,int optname, void *optval, socklen_t *optlen);
→成功時返回0,失敗時返回-1。
●sock :用于查看選項套接字文件描述符。
●level 要查看的可選項的協(xié)議層。
●optname 要查看的可選項名。
●optval 保存查看結(jié)果的緩沖地址值。
●optlen 向第四個參數(shù)optval 傳遞的緩沖大小。調(diào)用函數(shù)后,該變量中保存通過第四個參數(shù)
返回的可選項信息的字節(jié)數(shù)。
#include<sys/socket.h>
int setsockopt(int sock, int level, int optname, const void*optval, socklen_t optlen);
→成功時返回0,失敗時返回-1。
●sock 用于更改可選項的套接字文件描述符。
●level 要更改的可選項協(xié)議層。
●optname 要更改的可選項名。
●optval 保存要更改的選項信息的緩沖地址值。
●optlen 向第四個參數(shù)optval 傳遞的可選項信息的字節(jié)數(shù)。