17講中接觸了一些情況,比如通過read等呼叫,通過對eof的判斷,防範對方程式崩潰。
int nbytes =
recv
(connfd, buffer,
sizeof
(buffer),0
);if(nbytes ==-1
)else
if(nbytes ==0)
但是如果服務端完全崩潰或者網路中斷,如果是阻塞套接字,會一直阻塞在read等呼叫上,沒有辦法感知套接字的異常。可以用以下方法來解決。
方法1:給read設定超時
struct timeval tv;
tv.tv_sec =5;
tv.tv_usec =0;
//設定套接字的讀操作超時
setsockopt
(connfd, sol_socket, so_rcvtimeo,
(const
char*)
&tv,
sizeof tv)
;while(1
)else
}else
if(nbytes ==0)
...}
方法2:利用12講中的心跳包判斷連線是否正常
方法3:利用多路復用技術自帶的超時能力
select函式自帶超時的引數
struct timeval tv;
tv.tv_sec =5;
tv.tv_usec =0;
fd_zero
(&allreads)
;fd_set
(socket_fd,
&allreads)
;for(;
;)if(rc ==0)
...}
第乙個例子
char response=
"command ok"
;char buffer[
128]
;while(1
)else
if(nbytes ==0)
buffer[nbytes]
='\0';if
(strcmp
(buffer,
"quit")==
0)printf
("received %d bytes: %s\n"
, nbytes, buffer)
;}
問題:通過recv讀取的字元數為128時,就會buffer[128] = '\0'
造成緩衝區溢位
改正:留下buffer裡的乙個位元組,容納後面的『\0』
int nbytes =
recv
(connfd, buffer,
sizeof
(buffer)-1
,0);
send函式:傳送的字串呼叫的是sizeof,意味著』\0』是被傳送出去的,接收時假設沒有』\0』的存在,所以使用strlen,傳送中忽略』\0』
send
(socket, response,
strlen
(response),0
);
第二個例子
size_t read_message
(int fd,
char
*buffer, size_t length)
/* retrieve the record itself */
rc =
readn
(fd, buffer, msg_length);if
(rc != msg_length)
return rc <0?
-1:0
;return rc;
}
如果沒有if (msg_length > length)
這個判斷,對方發來的訊息體可以構建出乙個非常大的msg_length,而實際傳送的報文主體長度卻沒有這麼大,這樣後面的讀取操作就不會成功。
第三個例子
需要開發乙個函式,假設報文分界符是換行符\n,乙個做法是每次讀取乙個字元,判斷這個字元是不是換行符
版本一:
size_t readline
(int fd,
char
*buffer, size_t length)
}return-1
;}
問題:工作效率太低,每次recv都是一次系統呼叫,需要從使用者空間切換到核心空間,開銷較大。用版本二來解決。
版本二:一次性最多讀取512位元組到臨時緩衝區,之後將臨時緩衝區的字元乙個個拷貝到應用程式緩衝區,這樣做效率很高
size_t readline
(int fd,
char
*buffer, size_t length)
return-1
;}if(nread ==0)
return0;
//讀取成功
buffer_pointer = read_buffer;
nleft = nread;
}//乙個個讀到應用程式緩衝區
c =*buffer_pointer++
;*buffer++
= c;
//處理乙個就減乙個
nleft--;if
(c ==
'\n')}
return-1
;}
問題:如果輸入字元為012345678\n
//輸入字元為: 012345678\n
char buf[10]
readline
(fd, buf,
10)
讀到最後乙個\n字元時,length為1,讀到換行符會增加乙個字串截止符\0,越過了應用程式緩衝區的大小。所以要將length--
改為--length
。
●最終緩衝區的大小應該比預計接收的資料大小大一些,預防緩衝區溢位。
●可以動態分配緩衝區,但是要記得在return前釋放緩衝區
第二章 構造高效且健壯的網路程式 一
第二章 構造高效且健壯的網路程式 一 技巧15 理解tcp的寫操作 1 從應用題程式的角度看寫操作 首先會將資料從使用者緩衝區複製到核心中去,tcp可能傳送全部 部分或者不傳送資料,應用程式無法判定傳送了多少資料,也無法判斷對等實體是否判定 除非tcp傳送緩衝區滿了,否則寫操作是不會被阻塞的 寫操作...
網路程式設計實戰 檢查資料的有效
對端的異常狀況 可以通過read呼叫,對eof的判斷,隨時防範對方程式崩潰 但是 不是每種情況都可以通過讀操作來感知異常 比如伺服器完全崩潰,或者網路中斷的情況下,此時如果阻塞套接字,那麼會一直阻塞在read等呼叫上,沒有辦法感知套接字異常 其實有幾種辦法來解決這個問題 第乙個辦法是給套接字的rea...
網路爬蟲 spider 程式的程式設計實現
搜尋引擎中網路爬蟲的設計分析 1 網路爬蟲高度可配置性。可以配置網路引數,例如頻寬等等 2 網路爬蟲可以解析抓到的網頁裡的鏈結 這是必須的,要不你爬什麼呢?3 網路爬蟲有簡單的儲存配置 爬下來的東西要怎麼存 4 網路爬蟲擁有智慧型的根據網頁更新分析功能 最傻的做法是沒有時間更新權重,一通的爬,回頭再...