不對(duì),除非你接收前把緩沖區(qū)置0 用RtlZeroMemory函數(shù)。
黃岡網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián)建站,黃岡網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為黃岡上千多家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站建設(shè)要多少錢,請(qǐng)找那個(gè)售后服務(wù)好的黃岡做網(wǎng)站的公司定做!
你可以在接收那里加判斷啊,滿足你的條件時(shí)繼續(xù)執(zhí)行,執(zhí)行完成再重置緩沖區(qū)
1、如果對(duì)方斷開連接的話,那么readNum = recv ( socketId, rcvBuf, rcvBufSize, 0 );
readNum返回值應(yīng)該是0,可以根據(jù)返回值判斷。
2、recv函數(shù)返回值說明
recv函數(shù)
int recv( SOCKET s, char FAR *buf, int len, int flags);
不論是客戶還是服務(wù)器應(yīng)用程序都用recv函數(shù)從TCP連接的另一端接收數(shù)據(jù)。該函數(shù)的第一個(gè)參數(shù)指定接收端套接字描述符; 第二個(gè)參數(shù)指明一個(gè)緩沖區(qū),該緩沖區(qū)用來存放recv函數(shù)接收到的數(shù)據(jù); 第三個(gè)參數(shù)指明buf的長(zhǎng)度; 第四個(gè)參數(shù)一般置0。
這里只描述同步Socket的recv函數(shù)的執(zhí)行流程。當(dāng)應(yīng)用程序調(diào)用recv函數(shù)時(shí),
(1)recv先等待s的發(fā)送緩沖中的數(shù)據(jù)被協(xié)議傳送完畢,如果協(xié)議在傳送s的發(fā)送緩沖中的數(shù)據(jù)時(shí)出現(xiàn)網(wǎng)絡(luò)錯(cuò)誤,那么recv函數(shù)返回SOCKET_ERROR,
(2)如果s的發(fā)送緩沖中沒有數(shù)據(jù)或者數(shù)據(jù)被協(xié)議成功發(fā)送完畢后,recv先檢查套接字s的接收緩沖區(qū),如果s接收緩沖區(qū)中沒有數(shù)據(jù)或者協(xié)議正在接收數(shù) 據(jù),那么recv就一直等待,直到協(xié)議把數(shù)據(jù)接收完畢。當(dāng)協(xié)議把數(shù)據(jù)接收完畢,recv函數(shù)就把s的接收緩沖中的數(shù)據(jù)copy到buf中(注意協(xié)議接收到的數(shù)據(jù)可能大于buf的長(zhǎng)度,所以 在這種情況下要調(diào)用幾次recv函數(shù)才能把s的接收緩沖中的數(shù)據(jù)copy完。recv函數(shù)僅僅是copy數(shù)據(jù),真正的接收數(shù)據(jù)是協(xié)議來完成的), recv函數(shù)返回其實(shí)際copy的字節(jié)數(shù)。如果recv在copy時(shí)出錯(cuò),那么它返回SOCKET_ERROR;如果recv函數(shù)在等待協(xié)議接收數(shù)據(jù)時(shí)網(wǎng)絡(luò)中斷了,那么它返回0。 默認(rèn) socket 是阻塞的 解阻塞與非阻塞recv返回值沒有區(qū)分,都是 0 出錯(cuò) =0 連接關(guān)閉 0 接收到數(shù)據(jù)大小,
特別:返回值0時(shí)并且(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)的情況下認(rèn)為連接是正常的,繼續(xù)接收。只是阻塞模式下recv會(huì)阻塞著接收數(shù)據(jù),非阻塞模式下如果沒有數(shù)據(jù)會(huì)返回,不會(huì)阻塞著讀,因此需要循環(huán)讀?。?。
返回說明: 成功執(zhí)行時(shí),返回接收到的字節(jié)數(shù)。另一端已關(guān)閉則返回0。失敗返回-1,errno被設(shè)為以下的某個(gè)值 EAGAIN:套接字已標(biāo)記為非阻塞,而接收操作被阻塞或者接收超時(shí) EBADF:sock不是有效的描述詞 ECONNREFUSE:遠(yuǎn)程主機(jī)阻絕網(wǎng)絡(luò)連接 EFAULT:內(nèi)存空間訪問出錯(cuò) EINTR:操作被信號(hào)中斷 EINVAL:參數(shù)無效 ENOMEM:內(nèi)存不足 ENOTCONN:與面向連接關(guān)聯(lián)的套接字尚未被連接上 ENOTSOCK:sock索引的不是套接字 當(dāng)返回值是0時(shí),為正常關(guān)閉連接;
思考:當(dāng)對(duì)側(cè)沒有send,即本側(cè)的套接字s的接收緩沖區(qū)無數(shù)據(jù),返回值是什么(EAGAIN,原因?yàn)槌瑫r(shí),待測(cè))
你的代碼其實(shí)沒有任何問題,之所以 server 沒有打印,是由于server最后打印時(shí)的代碼是
printf("%s",buff);
把它改成
printf("%s\n",buff);
即可。 標(biāo)準(zhǔn)輸出是行緩沖的,所以如果打印的內(nèi)容沒有 \n 了話,內(nèi)容不會(huì)真正打印出來,而是留在緩沖中。
至于你client打印時(shí)
printf("recv from server :%s", buff);
雖然沒有在后面加 \n, 但是你從server發(fā)到client的消息里已經(jīng)帶有 \n 了,所以這里沒出問題。
關(guān)于標(biāo)準(zhǔn)輸入輸出緩沖相關(guān)的更多細(xì)節(jié),自己搜一下吧。
htons和inet_aton有什么區(qū)別?
htons 是把 主機(jī)使用的字節(jié)序轉(zhuǎn)成網(wǎng)絡(luò)字節(jié)序 (即入?yún)⑹钦麛?shù),返回值也是整數(shù))
而 inet_aton 是吧 ascii 字符串形式的IP地址 轉(zhuǎn)換成 網(wǎng)絡(luò)字節(jié)序的整數(shù)。
自己去搜一下網(wǎng)絡(luò)字節(jié)序相關(guān)信息。
需要將recv設(shè)置超時(shí),Linux下設(shè)置超時(shí)如下:
//設(shè)置發(fā)送超時(shí)
struct timeval timeout={3,0};//3s
setsockopt(socket,SOL_SOCKET,SO_SNDTIMEO,(char *)timeout,sizeof(struct timeval));
//設(shè)置接收超時(shí)
setsockopt(socket,SOL_SOCKET,SO_RCVTIMEO,(char *)timeout,sizeof(struct timeval));
windows下設(shè)置超時(shí)如下:
int timeout = 3000; //3s
int ret=setsockopt(sock_fd,SOL_SOCKET,SO_SNDTIMEO,timeout,sizeof(timeout));
int ret=setsockopt(sock_fd,SOL_SOCKET,SO_RCVTIMEO,timeout,sizeof(timeout));
你好
recv函數(shù)只是在用戶空間定義的。內(nèi)核空間有與之對(duì)應(yīng)的函數(shù),也就是說,執(zhí)行recv函數(shù)就會(huì)調(diào)用到內(nèi)核中與它對(duì)應(yīng)的函數(shù),實(shí)際起作用的就是內(nèi)核里的這個(gè)函數(shù)。
至于內(nèi)核里調(diào)用的是那個(gè)函數(shù),你不需要是找,那樣會(huì)把你看暈的,內(nèi)核里的調(diào)用關(guān)系復(fù)雜的很,除非對(duì)內(nèi)核非常了解的,才會(huì)找到到底是怎么調(diào)用的,他也是只是找到怎么調(diào)用的,至于為什么這樣調(diào)用是極少人知道的。得問linux的開發(fā)者。因?yàn)閮?nèi)核的代碼量是太多了。有人花了三年時(shí)間才看完內(nèi)核代碼。
souce insight只能查找內(nèi)核里有的東西,屬于內(nèi)核的。recv()函數(shù)是不屬于內(nèi)核的,所以用這個(gè)是查找不到的
希望可以幫到你,望選為滿意答案
不可能知道服務(wù)器是否已經(jīng)發(fā)送完畢,因?yàn)槟惆l(fā)送的沒有數(shù)據(jù)協(xié)議的格式,你可以讓發(fā)送方與接收方定個(gè)協(xié)議。其實(shí)你可以在recv時(shí)加個(gè)參數(shù),讓它只是看看有沒有數(shù)據(jù)到達(dá),recv最后那個(gè)參數(shù)設(shè)為MSG_OOB就可以,當(dāng)發(fā)現(xiàn)有數(shù)據(jù)到時(shí),你先Sleep一下,至于多長(zhǎng)時(shí)間就要看實(shí)際情況,一般幾十個(gè)毫秒就絕對(duì)夠了,然后,你再recv一下,這次最后那個(gè)參數(shù)為MSG_WAITALL就可以,這樣就一次性接收完畢