【解決方案】
1. 發送重試,由業務完成。
因為club_l5的send接口不會保留用戶發送的內容,在recv失敗的情況下,用戶發送的數據已經丟失,所以只能由業務進行重試。
結論:否定。由於后端服務器有多台,每次發送的時候並不能不能保證連接的機器還是上次發送的那一台服務器,有可能后端所有的連接都被斷開,雖然失敗比例有所降低,還是不能解決問題。
2. 修改服務器端關閉連接的等待時間。
治標不治本,可以在緊急情況下使用。
經過和still、allan、robby、steven一起討論,最佳的方案就是在發送的時候,就能感知到服務器端已經關閉連接,經過討論,給出以下解決方案:
3. 在send之前對先對read進行selcect,並使用read檢驗連接的狀態。
在send之前先對select函數read進行select,並設置時間參數設為0,select會立即返回,如果有FIN包可立刻知道,再進行read,如果read的返回值 <= 0,則說明連接有問題,或接收到了fin包,此時需關閉連接進行重連。
4. 使用poll()函數是否處於POLLRDHUP(套接字半關閉)狀態。
如果是,則關閉連接進行重連,目前還不完全成熟,且不適用於內核版本較低的系統。
5. 使用系統調用getpeername函數加系統錯誤碼的方式檢查對端是否關閉連接。
用法如下:if(getpeername (sock, &addr, &len) < 0 && errno == ENOTCONN) 當此條件成立的時候,說明對端已經關閉連接。
6. 發送之前用MSG_PEEK的方式recv。
看recv的返回值是否0字節,如果是0字節,說明對方發送了fin包,已關閉了連接。allan給出TTC中驗證連接是否有效的函數:
- int CPollerObject::CheckLinkStatus(void)
- {
- char msg[1] = {0};
- int err = 0;
- err = recv(netfd, msg, sizeof(msg), MSG_DONTWAIT|MSG_PEEK);
- /* client already close connection. */
- if(err == 0 || (err < 0 && errno != EAGAIN))
- return -1;
- return 0;
- }
綜合集中方案,最好采用6方案。