Re: [問題] socket在第一次recv後 會自動斷線

看板C_and_CPP作者 (藍影)時間14年前 (2011/06/29 11:46), 編輯推噓2(205)
留言7則, 3人參與, 最新討論串3/5 (看更多)
※ 引述《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,
當你while去跟buffer拿資料拿不到就會斷了啊
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
聽說要來推一下 :P
06/29 20:46, 1F

06/29 21:05, , 2F
先謝謝你的答覆 我有個想法其實在程式碼中 在recv我有註解
06/29 21:05, 2F

06/29 21:06, , 3F
就是如果 我在recv部份加一個do-while 那我只有在recv的
06/29 21:06, 3F

06/29 21:07, , 4F
byte數 = 0 或 -1(SOCKET_ERROR)才break 那這樣是不是保證
06/29 21:07, 4F

06/29 21:08, , 5F
收乾淨 才會跳出 作send的動作呢?
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 22:01, , 7F
程式把MAXLINE的資料丟到底層buffer =>底層bufferqueue爆炸
06/29 22:01, 7F
再看一次您原本引出來的地方,發現那段確實有點問題 send(s, send_buf, strlen(send_buf), 0) == SOCKET_ERROR 應是這樣吧.. 謝謝您提供的網頁 ※ 編輯: tropical72 來自: 180.177.73.222 (06/29 22:24)
文章代碼(AID): #1E2n2cjC (C_and_CPP)
討論串 (同標題文章)
文章代碼(AID): #1E2n2cjC (C_and_CPP)