網路程式設計實戰18 增強程式的健壯性

2021-10-09 03:07:39 字數 3247 閱讀 2493

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 網路爬蟲擁有智慧型的根據網頁更新分析功能 最傻的做法是沒有時間更新權重,一通的爬,回頭再...