[爆卦]recv意思是什麼?優點缺點精華區懶人包

為什麼這篇recv意思鄉民發文收入到精華區:因為在recv意思這個討論話題中,有許多相關的文章在討論,這篇最有參考價值!作者cole945 (躂躂..)看板C_and_CPP標題Re: [問題] socket在第一次re...



我補一些東西 @@

※ 引述《tropical72 (藍影)》之銘言:
: http://pastie.org/2139024
: 恕刪. 小弟 winsock 不強, 只做拋磚引玉之效。
: 首先,之前我查到的 10054 代表的是:server 強制把連線斷掉。
10054 是 reset by peer 或是 reset connection 的意思,
就是 TCP flags 的 RST 被 set..
跟 server 做 close(s) 不一樣, 是比較 low-level 問題
如果是 server close(s), 那 recv() 最終會先得到 0 才對

常見的reset可能有幾種情形
a. connect 時, server 在網路上, 但該 port 沒有開,
會由os直接回 rest 讓client斷線,
省得client要等到timeout浪費時間..
(有時因為安全的考慮, server也有可能故意不回, 避免被掃port)
b. tcp SN或之類的東西不sync了, 像是socket被重開了等等

建議原po可以拿像telnet類的工具連連看, 如果也是reset可能是server端的問題
或是有什麼防火牆做怪

: recv(s, recv_buf, MAXLINE, 0)) == 0
: 我無法確定 server 要丟過來的訊息有多大,剛試 ptt.cc (140.112.172.11)
: 在進入 do-while 前必須收二次才能把所有歡迎畫面 收完 (設定 MAXLINE 為 20000),

寫TCP程式, 要有幾點要注意, 不然很容易出問題
1. send是send, recv是recv, 兩個獨立的stream
send彼此之間, 或recv後此之間有序,
但send/recv之間沒有
2. 一次 send 可能被多次 recv,
多次 send 可能被一次 recv
所以buffer開多大能不能一次收完, 反而不是重點

像 telnet 這種, 就是有資料就收, 沒資料就卡..
有些protocol是會有 header 的,
所以可以用 header裡的length去決定還要收多少
才會是一個完整的boundary
多收到的就留著, 要跟下次合並,
少數就要繼承收完

3. 若是 blocking model (default)
ret = send或recv(s, buf, N, 0));
當 return 時, 有三種可能
i. <0 error
ii. =0 close
iii. ret>0 && ret <=n <-- 要注意這點,
不保證全部送/收, 所以基本上要用一個 loop 包住
while (len>0) {
r = send (s, buf, len, 0);
if (r > 0) {
buf += r;
len -= r;
}
/* ... 其他略 ... */
}
4. send return, 不表示對方收到, 也不表示資料已經送出
只是已經放進 os的transmission queue,
所以你可以拿buffer去做別的事

如果程式是單純的一來一回
(client request(send), 等server response(recv))
其實就沒什麼差別了..


: 架構絕對不只一種,但一些連線軟體似乎會用這種概念下去做。
: 比如說
: 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;
: }

1. 基本上, poll flag 蠻容易出問題的,
因為 varible 可能被 cache 在 register 裡,
像 while (!done); 這種code會變成inifite loop
2. 每次 creat thread, overhead 很大..

以上兩點合起來, 其實是程式 IO Model 的問題,
常用的大略有下面幾種

1. 若是簡單的console程式,
在 send或recv 完成前, 其實也不能做別的事
用原本的 block-io 就以了
2. 如果有 GUI 的話, 若是在 event handler 內 send/recv
會block住UI thread, user會感覺到UI hang住
所以會用
i. 自已開獨立的 worker thread 做
ii. 用 library/framework提供的 asyn-io api
3. non-block 變成在poll, 不建議

thread怎麼開? 如果是client,
對一個server就開一個 thread 一個是最簡單的方式
因為連線通常不多, 而且一個connection一個thread,
context處理比較直觀

但 thread overhead 不小,
大概可以想一想, win32一個thread 1MB stack,
2000個thread就 2GB, 一個process在user-space可以存取的就2G
2000個thread就滿了, 這還不考慮 scheduling的問題
所以就large scale的server(或connection較多的client),
就會用asyn-io + thread poll 搭下面提的 state machine 架構,
但連線的context變成是比較獨立的state, context 維護比較麻煩

: 架構可議性甚大!但重點、該防範的是:
: 怎樣不讓 recv / send 被卡死? send 被卡死可能是 server 那裡出包;
: 但 recv 被卡死, client 出包機率就更大!
總合以上..
我是覺得..會卡是正常的 orz 不要卡到UI就是了 ||||
: thread 不在此篇討論範圍內,提出之範例使用之 thread 亦不佳。
: 重點在於:防呆、防卡死。
: -------
: 若要自己寫 winsock, 其實還蠻建議自己先寫一份 ser 出來,
: 去簡單模擬你的 serv,再寫 client,同時不少人建議下面的東西也要學
: 1. thread
: 2. FSM ---> 這個技巧寫 winsock 據說非常好用,日後容易維護。
如果是搭 GUI 的話, 基本上都是用 state machine 會比較好用,
因為 GUI 會有一個 message queue/loop.
是一個很方便同步的機制
: 此篇僅為拋磚引玉,一點意見,參考一下。


--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 1.169.173.71
cole945:補兩本書,寫winsock的話,建議看MS Press 的 Network 06/29 22:21
cole945:Programming for Microsft Windows, 2nd. Edition 06/29 22:21
cole945:UNIX Network Programming, Vol1的話,蠻值得一讀.. 06/29 22:22
cole945:對socket的觀念很完整 06/29 22:22
tropical72: 神之手出現了, 快拜 !! 06/29 22:24
cole945:別鬧了..我是剛剛被拋出去的磚 orz 06/29 22:51
VictorTom:結果掉下來發現裡面其實是塊玉....XD 06/30 09:25
asoedarren:請問UDP是否也需要檢查接收長度 還是他自己有邊界? 07/02 09:56

你可能也想看看

搜尋相關網站