1 回答

TA貢獻(xiàn)2036條經(jīng)驗(yàn) 獲得超8個(gè)贊
我認(rèn)為你的問(wèn)題非常標(biāo)準(zhǔn):不注意TCP不實(shí)現(xiàn)消息邊界的事實(shí),只是通過(guò)連接傳輸兩個(gè)不透明的字節(jié)流。
這意味著,當(dāng)您將一串字節(jié)“Hello world從客戶端”發(fā)送到連接的套接字(已建立的TCP連接)時(shí),連接的另一端不知道客戶端的消息在哪里結(jié)束,除非客戶端以某種方式傳達(dá)它本身;根本沒(méi)有辦法使用TCP本身來(lái)劃分單個(gè)消息。
輸入“應(yīng)用程序級(jí)協(xié)議”:除非您打算使用TCP的數(shù)據(jù)交換任務(wù)自然地傳輸單個(gè)“消息” - 想象一下服務(wù)器將單個(gè)文件的內(nèi)容轉(zhuǎn)儲(chǔ)到每個(gè)連接的客戶端并關(guān)閉連接 - 您必須發(fā)明一些方法讓客戶端告訴服務(wù)器它發(fā)送的每條消息實(shí)際上在哪里結(jié)束。
考慮一下您的示例:在讀取過(guò)程中,您基本上有一個(gè)循環(huán),該循環(huán)從套接字重復(fù)讀取數(shù)據(jù)塊,具有單個(gè)退出條件:到達(dá)該套接字上的文件末尾。只有當(dāng)遠(yuǎn)程端(在本例中為客戶端)關(guān)閉其連接端時(shí),才會(huì)報(bào)告 EOF,而客戶端從不這樣做:它發(fā)送一個(gè)字符串,然后等待服務(wù)器發(fā)回一些東西,但服務(wù)器從不回復(fù),因?yàn)樗肋h(yuǎn)不會(huì)完成讀取。
有多種方法可以解決問(wèn)題。
發(fā)明一個(gè)自定義協(xié)議(例如,在TLV系列中),它將實(shí)現(xiàn)消息成幀。
例如,在最簡(jiǎn)單的形式中,該協(xié)議可以定義為單個(gè)無(wú)符號(hào)字節(jié),其中包含以下消息的長(zhǎng)度(以字節(jié)為單位)。
然后,服務(wù)器將有一個(gè)兩步過(guò)程來(lái)讀取客戶端的每條消息:讀取單個(gè)字節(jié);
如果成功,請(qǐng)讀取由前導(dǎo)字節(jié)值定義的任意數(shù)量的后續(xù)字節(jié);
成功后,請(qǐng)返回步驟 1 以閱讀以下消息。
想出一個(gè)消息分隔符,如ASCII LF字符 - 可以編碼為Go的字符串文本,并使服務(wù)器繼續(xù)讀取,直到遇到LF;一旦它發(fā)現(xiàn)了一個(gè)LF,它就知道它應(yīng)該處理消息,然后開(kāi)始讀取另一個(gè)消息。
\n
圍棋有方便的類(lèi)型
布菲奧。讀取器
在其標(biāo)準(zhǔn)包中,可以從由LF分隔的任何單個(gè)行中讀取。io.Reader
具有更復(fù)雜的消息框架,例如使用 JSON 流發(fā)送 JSON 文檔。
由庫(kù)存包實(shí)現(xiàn)的解碼器的一個(gè)經(jīng)常監(jiān)督的功能是,它可以解碼JSON對(duì)象的流,以此為例。
encoding/json
可能性實(shí)際上很多,所以我只是觸及了表面,我認(rèn)為你應(yīng)該明白這個(gè)想法。
- 1 回答
- 0 關(guān)注
- 112 瀏覽
添加回答
舉報(bào)