1. 程式人生 > >linux伺服器程式設計 ---資料收集:

linux伺服器程式設計 ---資料收集:

linux高效能伺服器程式設計+原始碼(帶書籤) 31.8M
https://download.csdn.net/download/qq_20772811/10683128

問題

socket伺服器開發中的SO_REUSEADDR選項與讓人心煩的TIME_WAIT

https://www.cnblogs.com/qiaoconglovelife/p/5416715.html
回想一下,Linux下的TIME_WAIT大概是2分鐘,這樣也合情合理。那麼沒有釋放掉的資源是什麼呢,是埠嗎?機智的我立刻決定做實驗找出答案。啟動伺服器程式,在與客戶建立連線之後,kill掉伺服器。飛快地在terminal裡輸入命令:netstat -an|grep 9877。這裡9877是我伺服器打算繫結的埠。果然:
  結果顯示9877埠正在被使用,並處於TCP中的TIME_WAIT狀態。再過兩分鐘,我再執行命令netstat -an|grep 9877,世界清靜了,什麼都沒有。

終於找到了答案:果然是TIME_WAIT在搗鬼。

我遇到的情況正好符合情況1,並且書上說了:“所有TCP伺服器都應該指定本套接字選項,以允許伺服器在這種情形下被重新啟動。”那麼試試看嘍。

UNIX Network Programming

一個很特別的TCP選項TCP_DEFER_ACCEPT

經過測試發現,設定TCP_DEFER_ACCEPT選項後,伺服器受到一個CONNECT請求後,作業系統不會Accept,也不會建立IO控制代碼。作業系統應該在若干秒,(但肯定遠遠大於上面設定的1s) 後,會釋放相關的連結。但沒有同時關閉相應的埠,所以客戶端會一直以為處於連結狀態。如果Connect後面馬上有後續的傳送資料,那麼伺服器會呼叫Accept接收這個連結埠。

感覺了一下,這個埠設定對於CONNECT連結上來而又什麼都不幹的攻擊方式處理很有效。我們原來的程式碼都是先允許連結,然後再進行超時處理,比他這個有點Out了。不過這個選項可能會導致定位某些問題麻煩。

裡面 val 的單位是秒,注意如果開啟這個功能,kernel 在 val 秒之內還沒有收到資料,不會繼續喚醒程序,而是直接丟棄連線。

將sin_addr設定為INADDR_ANY"的含義是什麼?

INADDR_ANY
轉換過來就是0.0.0.0,泛指本機的意思,也就是表示本機的所有IP,因為有些機子不止一塊網絡卡,多網絡卡的情況下,這個就表示所有網絡卡ip地址的意思。
比如一臺電腦有3塊網絡卡,分別連線三個網路,那麼這臺電腦就有3個ip地址了,如果某個應用程式需要監聽某個埠,那他要監聽哪個網絡卡地址的埠呢?

如果繫結某個具體的ip地址,你只能監聽你所設定的ip地址所在的網絡卡的埠,其它兩塊網絡卡無法監聽埠,如果我需要三個網絡卡都監聽,那就需要繫結3個ip,也就等於需要管理3個套接字進行資料交換,這樣豈不是很繁瑣?

所以出現INADDR_ANY,你只需繫結INADDR_ANY,管理一個套接字就行,不管資料是從哪個網絡卡過來的,只要是繫結的埠號過來的資料,都可以接收到。

epoll:EPOLLLT和EPOLLET的區別

概念:

Level-triggered :水平觸發,預設模式

edge-triggered :邊緣觸發

比如redis用LT模式,nginx用ET模式

通知模式:

LT模式時,事件就緒時,假設對事件沒做處理,核心會反覆通知事件就緒

ET模式時,事件就緒時,假設對事件沒做處理,核心不會反覆通知事件就緒

事件通知的細節:

1.呼叫epoll_ctl,ADD或者MOD事件EPOLLIN

LT:如果此時快取區沒有可讀資料,則epoll_wait不會返回EPOLLIN,如果此時緩衝區有可讀資料,則epoll_wait會持續返回EPOLLIN

ET:如果此時快取區沒有可讀資料,則epoll_wait不會返回EPOLLIN,如果此時緩衝區有可讀資料,則epoll_wait會返回一次EPOLLIN

2.呼叫epoll_ctl,ADD或者MOD事件EPOLLOUT

LT:如果不呼叫epoll_ctl將EPOLLOUT修改為EPOLLIN,則epoll_wait會持續返回EPOLLOUT(前提條件是寫緩衝區未滿)

ET:epoll_wait只會返回一次EPOLLOUT

針對TCP的測試詳請,都是non-blocking:

1.listenfd設定為LT

表現:當3次握手完成,如果不進行accept操作,那麼核心會反覆通知

2.listenfd設定為ET

https://blog.csdn.net/daiyudong2020/article/details/50439029

epoll

https://blog.csdn.net/ljx0305/article/details/4065058

linux 下epoll與執行緒池結合使用的簡單例項
https://blog.csdn.net/xilango/article/details/52824486

linux中send函式MSG_NOSIGNAL異常訊息

最近2周在做 ineedle 的國舜專案擴充套件,需要使用 socket 的 tcp 連線向對方傳送訊息,當然需求很簡單,只是按照對方要求傳送指定格式的訊息,程式結構也非常的簡單,一對多的 client/server 模型,ineedle 傳送給多個伺服器訊息。我們這邊在分析出結果,封裝為相應格式訊息後傳送給對方,只需要線上程迴圈傳送訊息即可,便在測試環境中編寫簡單的socket進行模擬訊息傳送,一對一發送,能夠正常傳送訊息。可以遇到了一個棘手的問題:在伺服器端用ctrl+c 來結束伺服器接收程序來模擬伺服器宕機的情況,結束服務 socket 程序之後,服務端自然關閉程序,可是 client 端也竟然出乎意料的關閉掉。

這就奇怪了,我在服務端關閉程序,伺服器會關閉 tcp 連線,向 client 傳送FIN包,client 響應 ack 後,等雙向 tcp 連線關閉後,tcp 連線徹底關閉,在 client 端傳送訊息會失敗,返回錯誤資訊,錯誤訊息會被正常的打印出來,可是很多時候錯誤資訊都沒有列印( write 函式沒有返回),有時候返回了錯誤資訊,但是 client 端程序仍然無辜死掉,我的 client 端可是用的 while(1) 死迴圈啊,怎麼可能。於是乎百度了一番,說法千奇百怪,有說防火牆的問題,關閉防火牆仍然如此。鬱悶 ing,測試了其它方法都不行,打印出錯誤錯誤碼,也沒有查詢到結果。

最後問了下我們的張總,問題剛給他說完,他便說他以前也遇到這個問題,給我找到了他以前的解決方案。解決方法是使用 send 函式時候在最後一個引數上加 MSG_NOSIGNAL 標記即可。於是自己更改傳送函式 write 為 send 並新增 MSG_NOSIGNAL 標誌,重新編譯,執行,中斷 server,果然這個問題被很瀟灑的解決了,感謝張總的英明神武。

參考一個博文的介紹

Linux 下當連線斷開,還發送資料的時候,不僅 send() 的返回值會有反映,而且還會向系統傳送一個異常訊息,如果不作處理,系統會出 BrokePipe,程式會退出,這對於伺服器提供穩定的服務將造成巨大的災難。為此,send() 函式的最後一個引數可以設定為 MSG_NOSIGNAL,禁止 send() 函式向系統傳送常訊息。

《windows網路程式設計》
<<windows網路程式設計>>和<windows 網路程式設計技術> 是同一本書嗎

題名/著者: Windows 網路程式設計/ (美)Athony Jones,(美)Jim Ohlund著
叢編題名: 微軟 .NET 程式設計師系列
ISBN號: 7-302-05947-0
出版項: 北京 清華大學出版社 2002.10
載體資訊: 23cm ⅩⅢ,458頁 CNY78.00
附註項: 本書著重於Windows XP中革新的聯網特性,同時包含了對C#程式語言的支援。本書還介紹了最新的網際協議:IPv4和IPv6,以及可靠IP多播協議。 讀者物件:VB或C++ 的程式開發人員。