中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

南京金九建設(shè)集團(tuán)網(wǎng)站aso優(yōu)化貼吧

南京金九建設(shè)集團(tuán)網(wǎng)站,aso優(yōu)化貼吧,12306網(wǎng)站如何做火車(chē)票候補(bǔ),株洲網(wǎng)站建設(shè)推廣報(bào)價(jià)原始套接字(Raw Socket) 原始套接字(Raw Socket)是一種提供較低級(jí)別網(wǎng)絡(luò)訪問(wèn)的套接字。通過(guò)使用原始套接字,應(yīng)用程序可以直接發(fā)送或接收網(wǎng)絡(luò)層如IP的數(shù)據(jù)包,或者傳輸層如TCP、UDP的段,而無(wú)需通…

原始套接字(Raw Socket)

原始套接字(Raw Socket)是一種提供較低級(jí)別網(wǎng)絡(luò)訪問(wèn)的套接字。通過(guò)使用原始套接字,應(yīng)用程序可以直接發(fā)送或接收網(wǎng)絡(luò)層如IP的數(shù)據(jù)包,或者傳輸層如TCP、UDP的段,而無(wú)需通過(guò)常規(guī)的套接字API提供的協(xié)議處理。

以下是原始套接字的一些關(guān)鍵點(diǎn):

  1. 協(xié)議獨(dú)立性:使用原始套接字,我們可以操作或構(gòu)建自己的協(xié)議,或者直接與現(xiàn)有協(xié)議(如ICMP)交互。

  2. 繞過(guò)內(nèi)核處理:通常,當(dāng)發(fā)送或接收數(shù)據(jù)包時(shí),操作系統(tǒng)內(nèi)核會(huì)為我們處理很多細(xì)節(jié),例如TCP的三次握手或IP頭的填充。但是,使用原始套接字,我們可以直接構(gòu)建或解析這些協(xié)議,從而繞過(guò)標(biāo)準(zhǔn)的內(nèi)核處理。

  3. 特權(quán):由于原始套接字提供了對(duì)網(wǎng)絡(luò)的低級(jí)訪問(wèn),使用它們通常需要特權(quán),例如root權(quán)限。

  4. 應(yīng)用場(chǎng)景

    • 網(wǎng)絡(luò)診斷和測(cè)試工具:例如,ping使用原始套接字發(fā)送和接收ICMP回顯請(qǐng)求和回顯響應(yīng)。
    • 定制協(xié)議的實(shí)現(xiàn):例如,如果我們想實(shí)驗(yàn)一個(gè)新的傳輸層協(xié)議。
    • 安全研究和網(wǎng)絡(luò)攻擊:例如,執(zhí)行某些類型的DoS攻擊或網(wǎng)絡(luò)掃描。
  5. 創(chuàng)建原始套接字:在Linux中,我們可以使用socket函數(shù)并為其提供AF_INET(對(duì)于IPv4)或AF_INET6(對(duì)于IPv6)以及SOCK_RAW來(lái)創(chuàng)建一個(gè)原始套接字。

  6. 手動(dòng)頭部處理:使用原始套接字,需要手動(dòng)構(gòu)建或解析協(xié)議頭部。例如,如果我們正在發(fā)送一個(gè)TCP段,我們需要手動(dòng)構(gòu)建IP和TCP頭部,并設(shè)置所有必要的字段。同樣,當(dāng)從一個(gè)原始套接字接收數(shù)據(jù)時(shí),我們將獲取整個(gè)數(shù)據(jù)包,需要自己解析它。

  7. 混雜模式:如果我們想使用原始套接字捕獲一個(gè)接口上的所有流量(而不僅僅是發(fā)給特定地址的流量),我們需要將接口設(shè)置為混雜模式。

需要注意的是,雖然原始套接字提供了強(qiáng)大的功能,但也需要小心使用。手動(dòng)處理協(xié)議細(xì)節(jié)容易導(dǎo)致錯(cuò)誤,并可能引起網(wǎng)絡(luò)問(wèn)題或安全隱患。

Socket()

socket()函數(shù)是計(jì)算機(jī)網(wǎng)絡(luò)編程中的核心函數(shù)之一,用于創(chuàng)建一個(gè)新的套接字。套接字是端到端的通信鏈路,是進(jìn)程之間進(jìn)行網(wǎng)絡(luò)通信的主要手段。

下面詳細(xì)介紹socket()函數(shù):

函數(shù)原型

int socket(int domain, int type, int protocol);

參數(shù)

  1. domain(或稱為family):指定使用哪種地址族。常見(jiàn)的選擇包括:

    • AF_INET:IPv4 地址族。用于IPv4網(wǎng)絡(luò)通信。
    • AF_INET6:IPv6 地址族。用于IPv6網(wǎng)絡(luò)通信。
    • AF_UNIX:本地套接字(UNIX 域套接字)地址族。用于同一機(jī)器上的進(jìn)程間通信。
  2. type:指定套接字的類型。常見(jiàn)的選擇包括:

    • SOCK_STREAM:提供面向連接、可靠、雙向的字節(jié)流服務(wù)。典型的協(xié)議有TCP。
    • SOCK_DGRAM:提供無(wú)連接的、不可靠的數(shù)據(jù)報(bào)服務(wù)。典型的協(xié)議有UDP。
    • SOCK_RAW:提供原始套接字訪問(wèn),允許直接發(fā)送或接收協(xié)議如IP的數(shù)據(jù)包。
    • SOCK_SEQPACKET:提供面向連接的、可靠的、固定最大長(zhǎng)度的記錄序列。
  3. protocol:指定要使用的協(xié)議。通常,當(dāng)給定了套接字的類型時(shí),可以將此參數(shù)設(shè)置為0,讓系統(tǒng)自動(dòng)選擇合適的協(xié)議。例如,當(dāng)typeSOCK_STREAM時(shí),系統(tǒng)通常選擇TCP作為協(xié)議。

返回值

  • 成功:返回一個(gè)非負(fù)描述符,代表新創(chuàng)建的套接字。
  • 失敗:返回-1,并設(shè)置相應(yīng)的錯(cuò)誤碼。

使用示例

創(chuàng)建一個(gè)用于IPv4 TCP通信的套接字:

int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {perror("socket creation failed");exit(EXIT_FAILURE);
}

創(chuàng)建一個(gè)用于IPv4 UDP通信的套接字:

int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1) {perror("socket creation failed");exit(EXIT_FAILURE);
}

注意事項(xiàng)

  1. 創(chuàng)建套接字只是第一步。為了實(shí)際上進(jìn)行通信,還需要其他函數(shù),如bind(), listen(), accept(), connect(), send(), 和 recv(),來(lái)配置并操作這個(gè)套接字。
  2. 對(duì)于TCP服務(wù)端,通常在socket()之后會(huì)調(diào)用bind(), listen()accept()來(lái)綁定地址、監(jiān)聽(tīng)連接和接受連接。
  3. 對(duì)于TCP客戶端,通常在socket()之后會(huì)調(diào)用connect()來(lái)連接到服務(wù)器。
  4. 對(duì)于UDP,沒(méi)有建立或接受連接的概念,所以只需創(chuàng)建套接字,然后可以直接使用sendto()recvfrom()進(jìn)行通信。

socket()函數(shù)是網(wǎng)絡(luò)編程中的基礎(chǔ),幾乎所有的網(wǎng)絡(luò)應(yīng)用程序都會(huì)在某個(gè)地方使用它來(lái)開(kāi)始其網(wǎng)絡(luò)通信。

bind()

bind() 是套接字編程中的一個(gè)關(guān)鍵函數(shù),用于將套接字與特定的IP地址和端口號(hào)綁定。它通常在服務(wù)器設(shè)置期間使用,以指定服務(wù)器將在哪個(gè)地址和端口監(jiān)聽(tīng)即將到來(lái)的客戶端連接。

函數(shù)原型:

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

參數(shù):

  1. sockfd: 這是一個(gè)套接字描述符,它表示要綁定的套接字。

  2. addr: 這是一個(gè)指向struct sockaddr的指針,該結(jié)構(gòu)定義了套接字的地址(IP和端口)。在實(shí)踐中,通常使用特定于協(xié)議的結(jié)構(gòu)(如struct sockaddr_in對(duì)于IPv4)來(lái)填充這個(gè)參數(shù),并將其指針類型強(qiáng)制轉(zhuǎn)換為struct sockaddr *。

  3. addrlen: 這是地址結(jié)構(gòu)的大小(例如,對(duì)于IPv4,這將是sizeof(struct sockaddr_in))。

返回值:

  • 成功時(shí),bind() 返回0。
  • 失敗時(shí),返回-1,并設(shè)置errno以指示錯(cuò)誤的原因。

常見(jiàn)的使用模式:

在服務(wù)器中,通常首先創(chuàng)建一個(gè)套接字,然后使用bind()將它綁定到一個(gè)地址和端口。以下是一個(gè)簡(jiǎn)化的示例,演示如何使用bind()為IPv4地址綁定套接字:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>int main() {int sockfd = socket(AF_INET, SOCK_STREAM, 0); // Create a TCP socketif (sockfd < 0) {perror("Error creating socket");return 1;}struct sockaddr_in server_addr;server_addr.sin_family = AF_INET;            // Address family for IPv4server_addr.sin_addr.s_addr = INADDR_ANY;    // Listen on any interfaceserver_addr.sin_port = htons(8080);          // Listen on port 8080if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {perror("Error binding socket");return 1;}// ... the server can then proceed to listen and accept connectionsreturn 0;
}

常見(jiàn)錯(cuò)誤和注意事項(xiàng):

  1. Address already in use: 如果嘗試綁定到已被另一個(gè)套接字使用的地址和端口,將會(huì)出現(xiàn)此錯(cuò)誤。這通常發(fā)生在服務(wù)器崩潰并嘗試重新啟動(dòng),但由于之前的套接字仍處于“TIME_WAIT”狀態(tài),所以它不能立即綁定。使用setsockopt()SO_REUSEADDR可以幫助解決此問(wèn)題。

  2. Permission denied: 通常,只有root用戶才能綁定到低于1024的端口。

  3. 確保在綁定套接字之前填充了整個(gè)sockaddr_in結(jié)構(gòu),并正確設(shè)置了sin_family、sin_addr.s_addrsin_port字段。

  4. 使用htons()函數(shù)確保端口號(hào)是網(wǎng)絡(luò)字節(jié)順序。

通過(guò)合理地使用bind()函數(shù),開(kāi)發(fā)人員可以確保他們的服務(wù)器監(jiān)聽(tīng)特定的IP地址和端口,從而等待客戶端的連接。

listen()

listen() 是套接字API中的一個(gè)函數(shù),用于讓一個(gè)套接字進(jìn)入監(jiān)聽(tīng)模式,從而能夠接收來(lái)自客戶端的連接請(qǐng)求。這是創(chuàng)建服務(wù)器應(yīng)用程序的必要步驟之一。

函數(shù)原型:

int listen(int sockfd, int backlog);

參數(shù):

  1. sockfd: 一個(gè)套接字描述符,它應(yīng)該先前已經(jīng)使用 socket() 創(chuàng)建并使用 bind() 綁定到一個(gè)特定的地址和端口。

  2. backlog: 這個(gè)參數(shù)定義了等待隊(duì)列的大小,也就是說(shuō),系統(tǒng)應(yīng)該允許等待處理(未accept()的)的連接數(shù)量。當(dāng)有更多的客戶端嘗試連接,超過(guò)了backlog指定的數(shù)量時(shí),系統(tǒng)會(huì)開(kāi)始拒絕這些新的連接請(qǐng)求。

返回值:

  • 如果函數(shù)調(diào)用成功,則返回0。
  • 如果出現(xiàn)錯(cuò)誤,則返回-1,并設(shè)置errno以指示出現(xiàn)的特定錯(cuò)誤。

使用:

一旦使用bind()函數(shù)將套接字綁定到一個(gè)地址和端口后,我們可以調(diào)用listen()以進(jìn)入監(jiān)聽(tīng)模式。在此模式下,套接字準(zhǔn)備接受來(lái)自客戶端的連接請(qǐng)求。

這是一個(gè)簡(jiǎn)單的示例:

int sockfd = socket(AF_INET, SOCK_STREAM, 0);  // Create a socket// ... (bind the socket to an address using bind() here)if (listen(sockfd, 5) < 0) {  // Allow up to 5 pending connectionsperror("Error while trying to listen");return 1;
}

此示例創(chuàng)建了一個(gè)套接字,并設(shè)置其最大待處理連接數(shù)為5。當(dāng)超過(guò)5個(gè)客戶端連接并等待被accept()時(shí),任何進(jìn)一步的連接請(qǐng)求都將被拒絕,直到有一個(gè)連接被accept()為止。

注意:

  • 在調(diào)用 listen() 之前,必須先調(diào)用 bind()。
  • backlog 參數(shù)的具體含義和行為可能因操作系統(tǒng)而異。在某些系統(tǒng)上,它表示待處理的連接數(shù)量,而在其他系統(tǒng)上,它可能包括已被accept()但尚未由應(yīng)用程序處理的連接。
  • 當(dāng) backlog 隊(duì)列已滿,進(jìn)一步的連接請(qǐng)求可能會(huì)被拒絕。因此,為了避免這種情況,服務(wù)器應(yīng)該盡快處理連接。
  • 通常,在 listen() 之后,會(huì)進(jìn)入一個(gè)循環(huán),不斷地調(diào)用 accept() 來(lái)接受并處理來(lái)自客戶端的連接。

總之,listen() 函數(shù)是服務(wù)器套接字編程中的關(guān)鍵步驟,使得服務(wù)器能夠開(kāi)始接受客戶端的連接請(qǐng)求。

accept()

accept() 是套接字編程中的一個(gè)關(guān)鍵函數(shù),用于從已經(jīng)處于監(jiān)聽(tīng)模式的套接字中提取連接請(qǐng)求,并返回一個(gè)新的套接字描述符,該描述符代表與客戶端之間的新連接。此函數(shù)在服務(wù)器應(yīng)用程序中經(jīng)常使用,以處理來(lái)自客戶端的連接請(qǐng)求。

函數(shù)原型:

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

參數(shù):

  1. sockfd: 這是一個(gè)處于監(jiān)聽(tīng)模式的套接字描述符,通常先前已經(jīng)通過(guò) socket() 創(chuàng)建并通過(guò) bind()listen() 函數(shù)配置。

  2. addr: 這是一個(gè)指向struct sockaddr的指針,當(dāng) accept() 調(diào)用返回時(shí),這個(gè)結(jié)構(gòu)將被填充與已經(jīng)接受的連接的遠(yuǎn)程端(客戶端)的地址信息。

  3. addrlen: 這是一個(gè)值-結(jié)果參數(shù)。在調(diào)用 accept() 之前,它應(yīng)該被設(shè)置為addr指向的地址結(jié)構(gòu)的大小。當(dāng)函數(shù)返回時(shí),addrlen 將被設(shè)置為實(shí)際的地址大小。

返回值:

  • 成功時(shí),accept() 返回一個(gè)新的套接字描述符,代表與客戶端的新連接。此新描述符應(yīng)用于后續(xù)的所有通信(例如 send()recv() 調(diào)用)。

  • 失敗時(shí),返回 -1,并設(shè)置 errno 以指示出現(xiàn)的錯(cuò)誤。

使用和注意事項(xiàng):

  1. 在服務(wù)器應(yīng)用程序中,通常在 listen() 函數(shù)調(diào)用后立即調(diào)用 accept(),等待客戶端的連接。

  2. accept() 函數(shù)是阻塞的,這意味著它將等待,直到一個(gè)連接請(qǐng)求可用,除非套接字已被配置為非阻塞。

  3. 返回的新套接字描述符與原始的監(jiān)聽(tīng)套接字是獨(dú)立的。應(yīng)使用新的套接字描述符進(jìn)行與客戶端的所有通信,并繼續(xù)使用原始的監(jiān)聽(tīng)套接字來(lái)接受其他連接請(qǐng)求。

  4. 通常,服務(wù)器將為每個(gè)接受的連接啟動(dòng)一個(gè)新的線程或進(jìn)程以并行處理多個(gè)連接。

  5. addraddrlen 參數(shù)是可選的;如果我們不關(guān)心客戶端的地址,我們可以設(shè)置這兩個(gè)參數(shù)為 NULL。

示例:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>int main() {int server_sock, client_sock;struct sockaddr_in server_addr, client_addr;socklen_t client_addr_len = sizeof(client_addr);// Assuming server_sock has been created and set up for listening...client_sock = accept(server_sock, (struct sockaddr *) &client_addr, &client_addr_len);if (client_sock < 0) {perror("Error on accept");return 1;}// Use client_sock for communication with the client...close(client_sock);return 0;
}

這個(gè)簡(jiǎn)單的例子展示了如何使用 accept() 函數(shù)從 server_sock 監(jiān)聽(tīng)套接字中接受一個(gè)新的連接,并使用 client_sock 與客戶端進(jìn)行通信。

connect()

connect() 是套接字編程中的一個(gè)函數(shù),主要用于客戶端應(yīng)用程序。該函數(shù)使客戶端嘗試與服務(wù)器端的指定地址建立連接。

函數(shù)原型:

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

參數(shù):

  1. sockfd: 這是我們想要與遠(yuǎn)程主機(jī)連接的套接字的描述符。

  2. addr: 這是一個(gè)指向struct sockaddr的指針,包含我們想要連接的遠(yuǎn)程主機(jī)的地址信息。在實(shí)際應(yīng)用中,通常使用特定于協(xié)議的結(jié)構(gòu)(如struct sockaddr_in對(duì)于IPv4)并將其類型強(qiáng)制轉(zhuǎn)換為struct sockaddr *。

  3. addrlen: 這是地址結(jié)構(gòu)的大小,例如對(duì)于IPv4地址,這通常是sizeof(struct sockaddr_in)。

返回值:

  • 成功時(shí),connect() 返回0。

  • 失敗時(shí),返回-1,并設(shè)置 errno 以指示錯(cuò)誤原因。

使用和注意事項(xiàng):

  1. 在客戶端應(yīng)用程序中,我們通常首先使用 socket() 函數(shù)創(chuàng)建一個(gè)套接字,然后使用 connect() 函數(shù)嘗試與服務(wù)器連接。

  2. 如果 connect() 成功,客戶端可以開(kāi)始使用 send()recv() 或其他相關(guān)函數(shù)與服務(wù)器通信。

  3. 如果連接嘗試失敗,connect() 將返回-1。這可能是由于多種原因,例如服務(wù)器未在指定的地址和端口上運(yùn)行,網(wǎng)絡(luò)故障,或服務(wù)器拒絕連接。

  4. connect() 在默認(rèn)情況下是阻塞的,這意味著它會(huì)等待,直到連接成功或發(fā)生錯(cuò)誤。但是,我們可以將套接字設(shè)置為非阻塞模式,使 connect() 立即返回,并后續(xù)使用 select()poll() 來(lái)等待連接完成。

示例:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>int main() {int client_sock;struct sockaddr_in server_addr;// Assuming client_sock has been created...server_addr.sin_family = AF_INET;server_addr.sin_port = htons(8080); // server portinet_pton(AF_INET, "192.168.1.1", &server_addr.sin_addr); // server IPif (connect(client_sock, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {perror("Error on connect");return 1;}// Now client_sock is connected and can be used to send or receive data...return 0;
}

這個(gè)簡(jiǎn)單的例子展示了如何使用 connect() 函數(shù)嘗試與運(yùn)行在192.168.1.1的服務(wù)器上的服務(wù)連接,該服務(wù)監(jiān)聽(tīng)端口8080。

send()

send() 是套接字編程中的一個(gè)函數(shù),用于向一個(gè)已連接的套接字發(fā)送數(shù)據(jù)。它通常用于TCP套接字,但也可以與其他類型的套接字一起使用。

函數(shù)原型:

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

參數(shù):

  1. sockfd: 這是一個(gè)已連接的套接字的描述符。

  2. buf: 這是一個(gè)指針,指向我們想要發(fā)送的數(shù)據(jù)的緩沖區(qū)。

  3. len: 這是buf中我們想要發(fā)送的數(shù)據(jù)的字節(jié)數(shù)。

  4. flags: 這是一個(gè)修改函數(shù)操作的標(biāo)志集合。常見(jiàn)的標(biāo)志包括 MSG_OOB (用于發(fā)送"out-of-band"數(shù)據(jù)) 和 MSG_NOSIGNAL (阻止在連接斷開(kāi)時(shí)發(fā)送SIGPIPE信號(hào))。大多數(shù)情況下,我們可以簡(jiǎn)單地將此參數(shù)設(shè)置為0。

返回值:

  • 成功時(shí),send() 返回實(shí)際發(fā)送的字節(jié)數(shù)。請(qǐng)注意,這可能少于我們請(qǐng)求發(fā)送的數(shù)量。

  • 失敗時(shí),返回-1,并設(shè)置 errno 以指示錯(cuò)誤原因。

使用和注意事項(xiàng):

  1. 在一個(gè)已連接的TCP套接字上使用send()之前,必須先成功地調(diào)用connect()(對(duì)于客戶端)或accept()(對(duì)于服務(wù)器)。

  2. TCP是一個(gè)流協(xié)議,這意味著沒(méi)有消息邊界。連續(xù)的send()調(diào)用可能會(huì)在接收方看起來(lái)像一個(gè)連續(xù)的數(shù)據(jù)流,而不是單獨(dú)的消息。

  3. 如果套接字是阻塞的(默認(rèn)情況),send()可能會(huì)阻塞,直到有足夠的網(wǎng)絡(luò)緩沖區(qū)可用以發(fā)送數(shù)據(jù)。如果套接字是非阻塞的,而網(wǎng)絡(luò)緩沖區(qū)不可用,則send()將立即返回-1,并將errno設(shè)置為EAGAINEWOULDBLOCK

  4. 在連接斷開(kāi)的套接字上調(diào)用send()將導(dǎo)致發(fā)送一個(gè)SIGPIPE信號(hào),除非設(shè)置了MSG_NOSIGNAL標(biāo)志。此信號(hào)的默認(rèn)行為是終止進(jìn)程,但可以捕獲或忽略它。

示例:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>int main() {int sockfd;  // assuming it's already connectedconst char *message = "Hello, server!";ssize_t bytes_sent;bytes_sent = send(sockfd, message, strlen(message), 0);if (bytes_sent < 0) {perror("Error on send");return 1;}printf("Sent %zd bytes to server.\n", bytes_sent);return 0;
}

這個(gè)簡(jiǎn)單的示例展示了如何使用send()函數(shù)將一條消息發(fā)送到一個(gè)已連接的服務(wù)器。

recv()

recv() 函數(shù)用于從已連接的套接字接收數(shù)據(jù)。它主要用于 TCP 套接字,但也可以與其他類型的套接字一起使用。

函數(shù)原型:

ssize_t recv(int sockfd, void *buf, size_t len, int flags);

參數(shù):

  1. sockfd: 這是一個(gè)已連接的套接字的描述符。

  2. buf: 這是一個(gè)指針,指向一個(gè)緩沖區(qū),用于存儲(chǔ)接收到的數(shù)據(jù)。

  3. len: 這是緩沖區(qū)的大小,即我們期望接收的最大字節(jié)數(shù)。

  4. flags: 這是一個(gè)修改函數(shù)操作的標(biāo)志集合。一些常見(jiàn)的標(biāo)志包括:

    • MSG_PEEK: 查看即將到來(lái)的數(shù)據(jù),但不從隊(duì)列中刪除它。
    • MSG_WAITALL: 嘗試接收指定的len字節(jié)。與默認(rèn)行為不同,該標(biāo)志會(huì)使函數(shù)等待,直到請(qǐng)求的字節(jié)數(shù)量可用或發(fā)生某些錯(cuò)誤。
    • MSG_OOB: 用于接收 “out-of-band” 數(shù)據(jù)。

    在大多數(shù)常規(guī)操作中,我們可以簡(jiǎn)單地將此參數(shù)設(shè)置為0。

返回值:

  • 成功時(shí),recv() 返回實(shí)際接收到的字節(jié)數(shù)。如果連接已關(guān)閉,返回0。

  • 失敗時(shí),返回-1,并設(shè)置 errno 以指示錯(cuò)誤原因。

使用和注意事項(xiàng):

  1. 在一個(gè)已連接的 TCP 套接字上使用 recv() 之前,我們需要先成功調(diào)用 connect()(對(duì)于客戶端)或 accept()(對(duì)于服務(wù)器)。

  2. TCP 是一個(gè)流協(xié)議,這意味著沒(méi)有消息邊界。連續(xù)的 recv() 調(diào)用可能會(huì)接收到之前調(diào)用的數(shù)據(jù)的剩余部分。

  3. 如果套接字是阻塞的(默認(rèn)情況),并且沒(méi)有數(shù)據(jù)可用,recv() 會(huì)阻塞,直到數(shù)據(jù)可用。如果套接字是非阻塞的,并且沒(méi)有數(shù)據(jù)可用,recv() 會(huì)立即返回-1,并將 errno 設(shè)置為 EAGAINEWOULDBLOCK。

  4. 當(dāng)連接斷開(kāi)或關(guān)閉時(shí),recv() 將返回0。因此,接收到0字節(jié)通常意味著對(duì)端關(guān)閉了連接。

示例:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>int main() {int sockfd;  // assuming it's already connectedchar buffer[1024];ssize_t bytes_received;bytes_received = recv(sockfd, buffer, sizeof(buffer) - 1, 0);if (bytes_received < 0) {perror("Error on recv");return 1;} else if (bytes_received == 0) {printf("The peer has closed the connection.\n");return 0;}buffer[bytes_received] = '\0';  // Null-terminate the stringprintf("Received: %s\n", buffer);return 0;
}

這個(gè)簡(jiǎn)單的示例展示了如何使用 recv() 函數(shù)從已連接的服務(wù)器接收消息,并將其打印出來(lái)。

綜合案例

下面是一個(gè)簡(jiǎn)單的TCP套接字編程的例子,其中包括一個(gè)服務(wù)器和一個(gè)客戶端。服務(wù)器接收來(lái)自客戶端的消息,然后返回相同的消息。

服務(wù)器端:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>#define SERVER_PORT 8080
#define BUFFER_SIZE 1024int main() {int server_sock, client_sock;struct sockaddr_in server_addr, client_addr;char buffer[BUFFER_SIZE];int bytes_read;// 創(chuàng)建套接字server_sock = socket(AF_INET, SOCK_STREAM, 0);if (server_sock == -1) {perror("Socket creation failed");exit(1);}// 設(shè)置服務(wù)器地址結(jié)構(gòu)memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(SERVER_PORT);server_addr.sin_addr.s_addr = INADDR_ANY;// 綁定套接字if (bind(server_sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {perror("Bind failed");exit(1);}// 監(jiān)聽(tīng)連接請(qǐng)求listen(server_sock, 5);printf("Server is listening on port %d...\n", SERVER_PORT);socklen_t client_addr_len = sizeof(client_addr);client_sock = accept(server_sock, (struct sockaddr*)&client_addr, &client_addr_len);if (client_sock == -1) {perror("Accept failed");exit(1);}// 讀取和響應(yīng)客戶端的消息bytes_read = recv(client_sock, buffer, BUFFER_SIZE, 0);buffer[bytes_read] = '\0';printf("Received from client: %s\n", buffer);send(client_sock, buffer, bytes_read, 0);close(client_sock);close(server_sock);return 0;
}

客戶端:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>#define SERVER_PORT 8080
#define SERVER_IP "127.0.0.1"
#define BUFFER_SIZE 1024int main() {int client_sock;struct sockaddr_in server_addr;char buffer[BUFFER_SIZE];// 創(chuàng)建套接字client_sock = socket(AF_INET, SOCK_STREAM, 0);if (client_sock == -1) {perror("Socket creation failed");exit(1);}// 設(shè)置服務(wù)器地址結(jié)構(gòu)memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(SERVER_PORT);inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr);// 連接到服務(wù)器if (connect(client_sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {perror("Connect failed");exit(1);}strcpy(buffer, "Hello, Server!");send(client_sock, buffer, strlen(buffer), 0);int bytes_received = recv(client_sock, buffer, BUFFER_SIZE, 0);buffer[bytes_received] = '\0';printf("Received from server: %s\n", buffer);close(client_sock);return 0;
}

運(yùn)行結(jié)果如下:
在這里插入圖片描述
上述示例中,服務(wù)器創(chuàng)建一個(gè)套接字,綁定到本地地址并監(jiān)聽(tīng)連接。當(dāng)客戶端連接時(shí),服務(wù)器接收來(lái)自客戶端的消息,并將相同的消息發(fā)送回客戶端??蛻舳藙t發(fā)送一個(gè)簡(jiǎn)單的消息,并從服務(wù)器接收響應(yīng)。

http://www.risenshineclean.com/news/48980.html

相關(guān)文章:

  • 肇慶企業(yè)做網(wǎng)站搜索引擎優(yōu)化案例分析
  • 手機(jī)ui設(shè)計(jì)網(wǎng)站免費(fèi)創(chuàng)建個(gè)人博客網(wǎng)站
  • 哪個(gè)網(wǎng)站專門(mén)做代購(gòu)寧波seo外包哪個(gè)品牌好
  • 支付網(wǎng)站招聘費(fèi)分錄怎么做長(zhǎng)尾關(guān)鍵詞愛(ài)站網(wǎng)
  • 網(wǎng)站建設(shè)和注冊(cè)北京seo包年
  • 一站式網(wǎng)站建設(shè)服務(wù)今日熱搜第一名
  • 開(kāi)封做網(wǎng)站公司漢獅外貿(mào)網(wǎng)站seo優(yōu)化
  • 建設(shè)網(wǎng)站證書(shū)西安百度seo
  • 濟(jì)源網(wǎng)站建設(shè)濟(jì)源百度地圖在線查詢
  • 國(guó)外商業(yè)網(wǎng)站設(shè)計(jì)廣東深圳疫情最新消息今天
  • 互聯(lián)網(wǎng)行業(yè)最有前景的十大職業(yè)手機(jī)網(wǎng)站排名優(yōu)化
  • wordpress自動(dòng)廣告位二級(jí)域名和一級(jí)域名優(yōu)化難度
  • 撰寫(xiě)網(wǎng)站的建設(shè)方案北京seo服務(wù)商
  • 賢邦網(wǎng)站建設(shè)app開(kāi)發(fā)公司網(wǎng)絡(luò)營(yíng)銷(xiāo)推廣
  • 做網(wǎng)站創(chuàng)業(yè)app排名優(yōu)化
  • 做網(wǎng)站建設(shè)的公司有哪些內(nèi)容房地產(chǎn)估價(jià)師考試
  • 電商網(wǎng)站功能介紹百度seo排名優(yōu)化公司推薦
  • 網(wǎng)站建設(shè)沒(méi)業(yè)務(wù)互聯(lián)網(wǎng)產(chǎn)品推廣
  • 購(gòu)物網(wǎng)站建設(shè)網(wǎng)站seo實(shí)戰(zhàn)密碼第三版pdf下載
  • 四川網(wǎng)站建設(shè)培訓(xùn)班百度助手下載安裝
  • 制作網(wǎng)站模板的發(fā)展空間網(wǎng)站搜索引擎優(yōu)化工具
  • 動(dòng)態(tài)網(wǎng)站開(kāi)發(fā)采用的關(guān)鍵技術(shù)百度入口網(wǎng)頁(yè)版
  • 西安做百度網(wǎng)站的上海職業(yè)技能培訓(xùn)機(jī)構(gòu)一覽表
  • 南昌網(wǎng)站建設(shè)優(yōu)化推廣費(fèi)用百度指數(shù)分析報(bào)告案例
  • 寧波做網(wǎng)站哪家公司好網(wǎng)站設(shè)計(jì)公司蘇州
  • 武漢市二手房交易合同備案在那個(gè)網(wǎng)站上做呀如何讓網(wǎng)站快速收錄
  • 網(wǎng)站制作 牛商網(wǎng)外鏈查詢工具
  • 手把手教做網(wǎng)站網(wǎng)站優(yōu)化策略
  • 做京東網(wǎng)站需要哪些手續(xù)費(fèi)企業(yè)推廣app
  • l網(wǎng)站建設(shè)線上營(yíng)銷(xiāo)手段