一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

C++ Socket send recv 循環(huán)發(fā)送和接收 阻塞與緩沖區(qū)

 沁水映月 2022-10-20 發(fā)布于江蘇

重點(diǎn):socket數(shù)據(jù)發(fā)送與接收問(wèn)題

數(shù)據(jù)的發(fā)送和接收是獨(dú)立的,并不是發(fā)送方執(zhí)行一次send,接收方就執(zhí)行以此recv。recv函數(shù)不分Send幾次,都會(huì)從輸入緩沖區(qū)盡可能多的Receive數(shù)據(jù)。如果發(fā)送方發(fā)送了多次信息,接收方?jīng)]來(lái)得及進(jìn)行recv,則數(shù)據(jù)堆積在輸入緩沖區(qū)中,取數(shù)據(jù)的時(shí)候會(huì)都取出來(lái)。換句話說(shuō),recv并不能判斷數(shù)據(jù)包的結(jié)束位置。

send函數(shù): 
在數(shù)據(jù)進(jìn)行發(fā)送的時(shí)候,需要先檢查輸出緩沖區(qū)的可用空間大小,如果可用空間大小小于要發(fā)送的數(shù)據(jù)長(zhǎng)度,則send會(huì)被阻塞,直到緩沖區(qū)中的數(shù)據(jù)被發(fā)送到目標(biāo)主機(jī),有了足夠的空間之后,send函數(shù)才會(huì)將數(shù)據(jù)寫入輸出緩沖區(qū)。

TCP協(xié)議正在將數(shù)據(jù)發(fā)送到網(wǎng)絡(luò)上的時(shí)候,輸出緩沖區(qū)會(huì)被鎖定(生產(chǎn)者消費(fèi)者問(wèn)題),不允許寫入,send函數(shù)會(huì)被阻塞,直到數(shù)據(jù)發(fā)送完,輸出緩沖區(qū)解鎖,此時(shí)send才能將數(shù)據(jù)寫入到輸出緩沖區(qū)。

要寫入的數(shù)據(jù)大于輸出緩沖區(qū)的最大長(zhǎng)度的時(shí)候,要分多次寫入,直到所有數(shù)據(jù)都被寫到緩沖區(qū)之后,send函數(shù)才會(huì)返回。

recv函數(shù): 
函數(shù)先檢查輸入緩沖區(qū),如果輸入緩沖區(qū)中有數(shù)據(jù),讀取出緩沖區(qū)中的數(shù)據(jù),否則的話,recv函數(shù)會(huì)被阻塞,等待網(wǎng)絡(luò)上傳來(lái)數(shù)據(jù)。如果讀取的數(shù)據(jù)長(zhǎng)度小于輸出緩沖區(qū)中的數(shù)據(jù)長(zhǎng)度,沒(méi)法一次性將所有數(shù)據(jù)讀出來(lái),需要多次執(zhí)行recv函數(shù),才能將數(shù)據(jù)讀取完畢。

--------------------------------------------------------------------------------------------------------------------

套接字的概念及分類

在網(wǎng)絡(luò)中,要全局的標(biāo)識(shí)一個(gè)參與通信的進(jìn)程,需要三元組:協(xié)議,IP地址以及端口號(hào)。要描述兩個(gè)應(yīng)用進(jìn)程之間的端到端的通信關(guān)聯(lián)需要五元組:協(xié)議,信源主機(jī)IP,信源應(yīng)用進(jìn)程端口,信宿主機(jī)IP,信宿應(yīng)用進(jìn)程端口。為了實(shí)現(xiàn)兩個(gè)應(yīng)用進(jìn)程的通信連接,提出了套接字的概念。套接字可以理解為通信連接的一端,將兩個(gè)套接字連接在一起,可以實(shí)現(xiàn)不同進(jìn)程之間的通信。 
針對(duì)不同的通信需求,TCP/IP中提供了三種不同的套接字: 
(1)流套接字(SOCK_STREAM) 
流套接字用于面向連接,可靠的數(shù)據(jù)傳輸服務(wù)。它之所以能實(shí)現(xiàn)可靠的數(shù)據(jù)服務(wù),是因?yàn)樗褂昧藗鬏斂刂茀f(xié)議–TCP。適合傳輸大量的數(shù)據(jù),但是不支持廣播和組播。 
(2)數(shù)據(jù)報(bào)套接字(SOCK_DGRAM) 
數(shù)據(jù)報(bào)套接字提供了一種無(wú)連接的服務(wù),通信雙方不需要建立任何顯示連接,數(shù)據(jù)可以發(fā)送到指定的套接字。數(shù)據(jù)報(bào)套接字使用UDP進(jìn)行數(shù)據(jù)傳輸,支持廣播和組播方式。 
(3)原始套接字(SOCK_RAW) 
原始套接字與標(biāo)準(zhǔn)套接字(上面兩個(gè))區(qū)別在于:原始套接字可以讀寫內(nèi)核沒(méi)有處理的IP數(shù)據(jù)報(bào),流套接字只能讀寫TCP數(shù)據(jù)報(bào),數(shù)據(jù)報(bào)套接字只能讀寫UDP數(shù)據(jù)報(bào)。原始套接字的主要目的是避開(kāi)TCP/IP的處理機(jī)制,被傳送的數(shù)據(jù)報(bào)可以直接傳送給需要他的程序。主要用于編寫自定義地層協(xié)議的應(yīng)用程序。

WinSock函數(shù)

1.WSAStartup函數(shù): 
功能:用于初始化WinSock,即檢查系統(tǒng)中是否有Windows Sockets的實(shí)現(xiàn)庫(kù)。 
格式:int WSAStartup(WORD wVersionRequest, LPWSADATA lpWSAData)。 
參數(shù):wVersionRequest使用WinSock的最低版本號(hào),lpWSAData是WSADATA指針。 
返回值:函數(shù)成功調(diào)用返回0,失敗時(shí)返回非0。 
說(shuō)明:此函數(shù)是應(yīng)用程序調(diào)用的第一個(gè)WinSock函數(shù),只有在該函數(shù)調(diào)用成功后才能調(diào)用其他WinSock函數(shù)。

2.socket函數(shù): 
功能:為應(yīng)用程序創(chuàng)建套接字。 
格式:SOCKET socket(int af, int type, int protocol)。 
參數(shù):af-套接字使用的協(xié)議地址族,如果使用TCP或者UDP,只能使用AF_INET;type-套接字協(xié)議類型,如SOCK_STREAM、SOCK_DGRAM;protocol-套接字使用的特定協(xié)議,如果不希望特別指定協(xié)議類型,則設(shè)置為0。 
返回值:函數(shù)成功調(diào)用后返回一個(gè)新的套接字,是一個(gè)無(wú)符號(hào)的整型數(shù)據(jù);失敗時(shí)返回INVALID_SOCKET。 
說(shuō)明:應(yīng)用程序在使用套接字通信之前,必須擁有一個(gè)套接字。

3.bind函數(shù): 
功能:實(shí)現(xiàn)套接字與主機(jī)本地IP地址和端口號(hào)的綁定。 
格式:int bind(SOCKET s, const struct sockaddr *name, int namelen)。 
參數(shù):s-將要綁定的套接字;name-與指定協(xié)議有關(guān)的地址結(jié)構(gòu)指針;namelen-name參數(shù)的長(zhǎng)度。 
返回值:函數(shù)成功時(shí)返回0;失敗時(shí)返回SOCKET_ERROR。

4.listen函數(shù): 
功能:設(shè)定套接字為監(jiān)聽(tīng)狀態(tài),準(zhǔn)備接收由客戶機(jī)進(jìn)程發(fā)出的連接請(qǐng)求。 
格式:int listen(SOCKET s, int backlog)。 
參數(shù):s-已綁定地址,但還未建立連接的套接字標(biāo)識(shí)符;backlog-指定正在等待連接的最大隊(duì)列長(zhǎng)度。 
返回值:函數(shù)成功時(shí)返回0;失敗時(shí)返回SOCKET_ERROR。 
說(shuō)明:僅適用于面向連接的套接字,且用于服務(wù)器進(jìn)程。

5.connect函數(shù): 
功能:提出與服務(wù)器建立連接的請(qǐng)求,如果服務(wù)器進(jìn)程接受請(qǐng)求,則服務(wù)器進(jìn)程與客戶機(jī)進(jìn)城之間便建立了一條通信連接。 
格式:int connect(SOCKET s, const struct sockaddr FAR *name, int namelen )。 
參數(shù):s-欲要建立連接的套接字;name-指向通信對(duì)方的套接字地址結(jié)構(gòu)指針,表示s欲與其建立連接;namelen-name參數(shù)的長(zhǎng)度。 
返回值:函數(shù)成功時(shí)返回0;失敗時(shí)返回SOCKET_ERROR。 
說(shuō)明:在客戶機(jī)進(jìn)程調(diào)用該方法請(qǐng)求建立連接時(shí),將激活建立連接的3次握手,以此來(lái)建立一條與服務(wù)器進(jìn)程的TCP連接。如果該函數(shù)調(diào)用之前沒(méi)有綁定地址,系統(tǒng)自動(dòng)綁定本地地址到此套接字。

6.accept函數(shù): 
功能:接受客戶機(jī)進(jìn)程調(diào)用connect函數(shù)發(fā)出的連接請(qǐng)求。 
格式:SOCKET accept(SOCKET s, struct sockaddr FAR *addr, int FAR *addrlen)。 
參數(shù):s-處于偵聽(tīng)狀態(tài)的套接字;addr-指向一個(gè)用來(lái)存放發(fā)出連接請(qǐng)求的客戶機(jī)進(jìn)程IP地址信息的地址結(jié)構(gòu)指針;addrlen-addr的長(zhǎng)度。 
返回值:調(diào)用成功返回一個(gè)新的套接字,這個(gè)套接字對(duì)應(yīng)于已接受的那個(gè)客戶機(jī)進(jìn)程的連接,失敗時(shí)返回INVALID_SOCKET。 
說(shuō)明:用于面向連接的服務(wù)器進(jìn)程,在IP協(xié)議族中只適用于TCP服務(wù)器端。

7.shutdown函數(shù): 
功能:關(guān)閉套接字讀寫通道,即停止套接字接受傳遞的功能。 
格式:int shutdown(SOCKET s, int how)。 
參數(shù):s-套接字;how-描述停止哪些操作。 
how-0:不再接收消息; 
how-1:不再允許發(fā)送消息; 
how-2:既不接收消息,也不再發(fā)送消息。 
返回值:函數(shù)成功時(shí)返回0;失敗時(shí)返回SOCKET_ERROR。 
說(shuō)明:只是停止套接字的功能,并沒(méi)有關(guān)閉套接字,套接字的資源還沒(méi)釋放。

8.closesocket函數(shù): 
功能:關(guān)閉套接字,釋放與套接字關(guān)聯(lián)的所有資源。 
格式:int closesocket(SOCKET s)。 
參數(shù):s-將要關(guān)閉的套接字。 
返回值:函數(shù)成功時(shí)返回0;失敗時(shí)返回SOCKET_ERROR。 
說(shuō)明:當(dāng)套接字s的數(shù)據(jù)緩沖隊(duì)列中還有未發(fā)出的數(shù)據(jù)時(shí),如果套接字設(shè)定為SO_DONTLINGER,則等待數(shù)據(jù)緩沖隊(duì)列中的數(shù)據(jù)繼續(xù)傳輸完畢關(guān)閉該套接字;如果套接字設(shè)定為SO_LINGER,則分以下兩種情況: 
(1)Timeout設(shè)為0,套接字馬上關(guān)閉,數(shù)據(jù)緩沖隊(duì)列中數(shù)據(jù)丟失。 
(2)Timeout不為0,等待數(shù)據(jù)傳輸完畢或者Timeout為0時(shí)關(guān)閉套接字。

9.WSACleanup函數(shù): 
功能:終止使用WinSock,釋放為應(yīng)用程序分配的相關(guān)資源。 
格式:int WSACleanup()。 
參數(shù):無(wú)。 
返回值:調(diào)用成功時(shí)返回0,失敗時(shí)返回非0。 
說(shuō)明:該函數(shù)是任何一個(gè)基于WinSock應(yīng)用程序在最后必須調(diào)用的函數(shù),終止了所有Windows Sockets在所有線程上的操作。

10.recv函數(shù): 
功能:在已建立連接的套接字上接收數(shù)據(jù)。 
格式:int recv(SOCKET s, char *buf, int len, int flags)。 
參數(shù):s-已建立連接的套接字;buf-存放接收到的數(shù)據(jù)的緩沖區(qū)指針;len-buf的長(zhǎng)度;flags-調(diào)用方式: 
(1)0:接收的是正常數(shù)據(jù),無(wú)特殊行為。 
(2)MSG_PEEK:系統(tǒng)緩沖區(qū)數(shù)據(jù)復(fù)制到提供的接收緩沖區(qū),但是系統(tǒng)緩沖區(qū)內(nèi)容并沒(méi)有刪除。 
(3)MSG_OOB:表示處理帶外數(shù)據(jù)。 
返回值:接收成功時(shí)返回接收到的數(shù)據(jù)長(zhǎng)度,連接結(jié)束時(shí)返回0,連接失敗時(shí)返回SOCKET_ERROR。

11.send函數(shù): 
功能:在已建立連接的套接字上發(fā)送數(shù)據(jù). 
格式:int send(SOCKET s, const char *buf, int len, int flags)。 
參數(shù):參數(shù):s-已建立連接的套接字;buf-存放將要發(fā)送的數(shù)據(jù)的緩沖區(qū)指針;len-發(fā)送緩沖區(qū)中的字符數(shù);flags-控制數(shù)據(jù)傳輸方式: 
(1)0:接收的是正常數(shù)據(jù),無(wú)特殊行為。 
(2)MSG_DONTROUTE:表示目標(biāo)主機(jī)就在本地網(wǎng)絡(luò)中,無(wú)需路由選擇。 
(3)MSG_OOB:表示處理帶外數(shù)據(jù)。 
返回值:發(fā)送成功時(shí)返回發(fā)送的數(shù)據(jù)長(zhǎng)度,連接結(jié)束時(shí)返回0,連接失敗時(shí)返回SOCKET_ERROR。

--------------------------------------------------------------------------------------------------------------------

socket緩沖區(qū)

每一個(gè)socket在被創(chuàng)建之后,系統(tǒng)都會(huì)給它分配兩個(gè)緩沖區(qū),即輸入緩沖區(qū)和輸出緩沖區(qū)。 
這里寫圖片描述

send函數(shù)并不是直接將數(shù)據(jù)傳輸?shù)骄W(wǎng)絡(luò)中,而是負(fù)責(zé)將數(shù)據(jù)寫入輸出緩沖區(qū),數(shù)據(jù)從輸出緩沖區(qū)發(fā)送到目標(biāo)主機(jī)是由TCP協(xié)議完成的。數(shù)據(jù)寫入到輸出緩沖區(qū)之后,send函數(shù)就可以返回了,數(shù)據(jù)是否發(fā)送出去,是否發(fā)送成功,何時(shí)到達(dá)目標(biāo)主機(jī),都不由它負(fù)責(zé)了,而是由協(xié)議負(fù)責(zé)。

recv函數(shù)也是一樣的,它并不是直接從網(wǎng)絡(luò)中獲取數(shù)據(jù),而是從輸入緩沖區(qū)中讀取數(shù)據(jù)。

輸入輸出緩沖區(qū),系統(tǒng)會(huì)為每個(gè)socket都單獨(dú)分配,并且是在socket創(chuàng)建的時(shí)候自動(dòng)生成的。一般來(lái)說(shuō),默認(rèn)的輸入輸出緩沖區(qū)大小為8K。套接字關(guān)閉的時(shí)候,輸出緩沖區(qū)的數(shù)據(jù)不會(huì)丟失,會(huì)由協(xié)議發(fā)送到另一方;而輸入緩沖區(qū)的數(shù)據(jù)則會(huì)丟失。

socket數(shù)據(jù)發(fā)送與接收問(wèn)題

數(shù)據(jù)的發(fā)送和接收是獨(dú)立的,并不是發(fā)送方執(zhí)行一次send,接收方就執(zhí)行以此recv。recv函數(shù)不管發(fā)送幾次,都會(huì)從輸入緩沖區(qū)盡可能多的獲取數(shù)據(jù)。如果發(fā)送方發(fā)送了多次信息,接收方?jīng)]來(lái)得及進(jìn)行recv,則數(shù)據(jù)堆積在輸入緩沖區(qū)中,取數(shù)據(jù)的時(shí)候會(huì)都取出來(lái)。換句話說(shuō),recv并不能判斷數(shù)據(jù)包的結(jié)束位置。

send函數(shù): 
在數(shù)據(jù)進(jìn)行發(fā)送的時(shí)候,需要先檢查輸出緩沖區(qū)的可用空間大小,如果可用空間大小小于要發(fā)送的數(shù)據(jù)長(zhǎng)度,則send會(huì)被阻塞,直到緩沖區(qū)中的數(shù)據(jù)被發(fā)送到目標(biāo)主機(jī),有了足夠的空間之后,send函數(shù)才會(huì)將數(shù)據(jù)寫入輸出緩沖區(qū)。

TCP協(xié)議正在將數(shù)據(jù)發(fā)送到網(wǎng)絡(luò)上的時(shí)候,輸出緩沖區(qū)會(huì)被鎖定(生產(chǎn)者消費(fèi)者問(wèn)題),不允許寫入,send函數(shù)會(huì)被阻塞,直到數(shù)據(jù)發(fā)送完,輸出緩沖區(qū)解鎖,此時(shí)send才能將數(shù)據(jù)寫入到輸出緩沖區(qū)。

要寫入的數(shù)據(jù)大于輸出緩沖區(qū)的最大長(zhǎng)度的時(shí)候,要分多次寫入,直到所有數(shù)據(jù)都被寫到緩沖區(qū)之后,send函數(shù)才會(huì)返回。

recv函數(shù): 
函數(shù)先檢查輸入緩沖區(qū),如果輸入緩沖區(qū)中有數(shù)據(jù),讀取出緩沖區(qū)中的數(shù)據(jù),否則的話,recv函數(shù)會(huì)被阻塞,等待網(wǎng)絡(luò)上傳來(lái)數(shù)據(jù)。如果讀取的數(shù)據(jù)長(zhǎng)度小于輸出緩沖區(qū)中的數(shù)據(jù)長(zhǎng)度,沒(méi)法一次性將所有數(shù)據(jù)讀出來(lái),需要多次執(zhí)行recv函數(shù),才能將數(shù)據(jù)讀取完畢。---轉(zhuǎn)發(fā)于網(wǎng)絡(luò)。

循環(huán)發(fā)送和接收

防止send或者 recv不完整,這樣你想發(fā)一個(gè)預(yù)定義函數(shù)<<

幾MB直接調(diào)用下面方法就okay,不會(huì)少發(fā)~

// 循環(huán)發(fā)送和接收
//防止send或者 recv不完整,這樣你想發(fā)一個(gè) 
//幾MB直接調(diào)用下面方法就okay,不會(huì)少發(fā)~
bool SendAll(SOCKET &sock,char*buffer,int size)
{
	while(size>0)
	{
		int SendSize=send(sock,buffer,size,0);
		if(SOCKET_ERROR==SendSize)
		return false;
		size=size-SendSize;//用于循環(huán)發(fā)送且忒出功能
		buffer+=SendSize;//用于計(jì)算已發(fā)buffer的偏移量 
	}
	return true; 
}

bool RecvAll(SOCKET &sock,char*buffer,int size)
{
	while(size>0)//剩余部分大于0 
	int RecvSize=recv(sock,buffer,size,0);
		if(SOCKET_ERROR==SendSize)
		return false;
		size=size-SendSize;//用于循環(huán)發(fā)送且忒出功能
		buffer+=SendSize;//用于計(jì)算已發(fā)buffer的偏移量 
	}
	return true; 
}

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

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    自拍偷拍一区二区三区| 日本久久精品在线观看| 欧美三级不卡在线观线看| 国产成人精品视频一二区| 久热香蕉精品视频在线播放| 欧美做爰猛烈叫床大尺度| 人妻乱近亲奸中文字幕| 亚洲二区欧美一区二区| 国产精品激情在线观看| 黄色污污在线免费观看| 欧美日韩亚洲国产综合网 | 精品亚洲香蕉久久综合网| 日韩欧美精品一区二区三区| 青青久久亚洲婷婷中文网| 五月情婷婷综合激情综合狠狠| 国产一级性生活录像片| 成人午夜激情免费在线| 亚洲中文字幕三区四区| 日韩国产精品激情一区| 丝袜人妻夜夜爽一区二区三区| 国产精品一区二区三区欧美| 欧美黑人暴力猛交精品| 女厕偷窥一区二区三区在线| 精品视频一区二区三区不卡| 日韩一级欧美一级久久| 91欧美激情在线视频| 国产又粗又硬又大又爽的视频| 精品推荐久久久国产av| 欧美不卡午夜中文字幕| 久久精品国产第一区二区三区| 99热九九在线中文字幕| 人妻人妻人人妻人人澡| 日韩和欧美的一区二区三区| 午夜成年人黄片免费观看| 手机在线不卡国产视频| 精品女同一区二区三区| 黄片免费观看一区二区| 日韩在线免费看中文字幕| 日本不卡在线一区二区三区| 久久精品a毛片看国产成人| 欧美不雅视频午夜福利|