Re: [問題] socket在第一次recv後 會自動斷線
※ 引述《werbnm (懶懶懶)》之銘言:
: 開發平台(Platform): (Ex: VC++, GCC, Linux, ...)
: VC++ 2010
: 額外使用到的函數庫(Library Used): (Ex: OpenGL, ...)
: WinSock.h
http://pastie.org/2139024
恕刪. 小弟 winsock 不強, 只做拋磚引玉之效。
首先,之前我查到的 10054 代表的是:server 強制把連線斷掉。
---
整體流程我不確定你 server 是怎樣長,
但如果你的 server 是 bbs 的話,正常應是要先 recv 歡迎畫面,
所以在進入 loop 前應先做 recv, 這時應會有個問題出現
#define MAXLINE 1024
...
recv(s, recv_buf, MAXLINE, 0)) == 0
我無法確定 server 要丟過來的訊息有多大,剛試 ptt.cc (140.112.172.11)
在進入 do-while 前必須收二次才能把所有歡迎畫面 收完 (設定 MAXLINE 為 20000),
太少次的話,前幾次 send 都是無效;
太多次的話,程式會卡在那裡,因 server 已沒東西丟過來,但還在等待要丟過來,
這應也是推文中所指之意。
推
06/29 16:07,
06/29 16:07
---
一般而言,確實是用 while(1) / while(true) 方式去做,
但吾人較為常見之方式是開 thread 去做,之後再計時或計次數,
架構絕對不只一種,但一些連線軟體似乎會用這種概念下去做。
比如說
#define TRY_TIMES 3 /* 只收 3 次 */
#define SLEEP_TIMES 1000 /* 每秒 polling 一次是否收成功 */
bool recv_flag;
void my_recv(void *)
{
recv(...);
_endthread();
recv_flag=true; // 已收到
}
int try_times=0;
while(1){
memset(recv_buf, 0, LEN);
recv_flag = false; // 未收到
_beginthread(my_recv, 0, NULL);
while(!recv_flag && try_times!=TRY_TIMES){
Sleep(SLEEP_TIMES);
++try_times;
}
if(!recv_flag) cerr << "recv fail.\n", _endthread(); // 收失敗
}
-----
架構可議性甚大!但重點、該防範的是:
怎樣不讓 recv / send 被卡死? send 被卡死可能是 server 那裡出包;
但 recv 被卡死, client 出包機率就更大!
thread 不在此篇討論範圍內,提出之範例使用之 thread 亦不佳。
重點在於:防呆、防卡死。
-------
若要自己寫 winsock, 其實還蠻建議自己先寫一份 ser 出來,
去簡單模擬你的 serv,再寫 client,同時不少人建議下面的東西也要學
1. thread
2. FSM ---> 這個技巧寫 winsock 據說非常好用,日後容易維護。
此篇僅為拋磚引玉,一點意見,參考一下。
--
YouLoveMe() ? LetItBe() : LetMeFree();
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 180.177.73.222
→
06/29 20:46, , 1F
06/29 20:46, 1F
推
06/29 21:05, , 2F
06/29 21:05, 2F
→
06/29 21:06, , 3F
06/29 21:06, 3F
→
06/29 21:07, , 4F
06/29 21:07, 4F
→
06/29 21:08, , 5F
06/29 21:08, 5F
推斷不是那麼簡單的判斷,
http://msdn.microsoft.com/en-us/library/ms740121%28v=VS.85%29.aspx
網頁上已敘述(簡略翻譯),
「若正常執行無任何錯誤,傳回 bytes 數;若 serv 關閉其連線,傳回 0;
失敗時傳回 SOCKET_ERROR」
故收到 bytes = 0 ,不代表已收完。
----
題外話,Dforce 發文指出 MAXLINE = 65535 於底層會爆,
但我於原 po 程式碼看不出有何問題,不知這方面是否有高人能指點一二?
※ 編輯: tropical72 來自: 180.177.73.222 (06/29 21:54)
推
06/29 21:59, , 6F
06/29 21:59, 6F
→
06/29 22:01, , 7F
06/29 22:01, 7F
再看一次您原本引出來的地方,發現那段確實有點問題
send(s, send_buf, strlen(send_buf), 0) == SOCKET_ERROR
應是這樣吧.. 謝謝您提供的網頁
※ 編輯: tropical72 來自: 180.177.73.222 (06/29 22:24)
討論串 (同標題文章)