2012-07-30 79 views
1

這是一個相當複雜的問題,爲此我表示歉意。我編寫了Linux C套接字應用程序,這是一個簡單聊天服務器的基本框架。服務器正在我的筆記本上運行。客戶端是Telnet,直到我寫一個指定的客戶端應用程序(希望這會更安全)。我知道有更好的應用程序可以從客戶端發送通用網絡數據,但我對感興趣,爲什麼某個事情發生在一個Telnet客戶端上,而不是另一個。Telnet客戶端及其處理EOL

第一次Telnet客戶端測試是在另一臺Linux筆記本電腦上。它按預期工作。然而,接下來是一款名爲BBSSH的黑莓應用程序,它允許Telnet和SSH連接。我通過Telnet選項,它也可以。除了它不完全。

服務器代碼執行通常的read調用來檢索數據塊,該數據塊被視爲字符串,即消息。前一個客戶讀取,直到我輸入,然後它發送一串字符。然而,BB應用程序發送每個單獨的字符,就好像我在每個字符後按下Enter鍵一樣,而我沒有。很明顯,這與緩衝有關,某些客戶端從用戶輸入中分類爲EOL等,我只是無法精確定位它。

爲了說明,這裏是服務器輸出從客戶端收到的消息。

首先,從Linux客戶端的消息:

client name: this is a test 

現在,BBSSH:

client name: t 
client name: h 
client name: i 
client name: s 
client name: 
client name: i 
client name: s 
client name: 
client name: a 
client name: 
client name: t 
client name: e 
client name: s 
client name: t 

任何幫助嗎?

回答

3

Telnet客戶端可以在線路模式或字符模式下運行。由於某種原因,BBSSH客戶端似乎在字符模式下運行。

您的服務器可能會強制客戶端進入線路模式,通過在telnet連接開始時進行的協商過程中向客戶端發送指令以實現此效果。

您的服務器需要發送到客戶端的字節序列是0x255 0x253 0x34,它翻譯爲「解釋爲命令,做,線性模式」。如果客戶端願意/能夠在線路模式下工作,則應回覆0x255 0x251 0x34(「解釋命令,請問,線路模式」)。

如果這對你來說是全新的(即你的telnet服務器目前根本不做任何談判),谷歌可以使用「telnet negotiation」或者查看一些相關的RFCS(RFC 854是Telnet本身,RFC 1184涵蓋了Linemode選項)。

+0

啊......我懷疑這是和兩個客戶端運行不同的配置或模式有關。這種行爲似乎過於一致,不足以成爲服務器端讀取量的僥倖。鑑於Telnet客戶端僅僅是一個測試平臺,並且客戶端最終將直接使用TCP,所以我只會暫時嵌入該模式字節序列。感謝RFC編號,我會查找它們:) – Louis 2012-07-30 15:00:56

+0

即使客戶端以完整的行發送數據,它是否仍然易受TCP碎片影響? – 2012-07-30 15:20:26

+0

@JamesMcLaughlin是的,你仍然可以得到TCP級別的碎片,但是這不是導致問題中描述的問題的原因。另外,這種碎片需要在TCP或Telnet之上的協議級別解決 - 在這個問題上,這真是'聊天協議'的工作。 – Chris 2012-07-30 15:53:11

2

TCP是面向流的,所以不存在「消息」之類的東西。您可能一次收到所有數據,或者只是一次收集所有數據。

就你而言,你可能想要緩衝接收到的任何東西,直到你點擊一個EOL標記。

+0

我的意思是'消息'作爲我的應用程序的抽象概念,我知道它是基於流和緩衝區的。我認爲讀取會阻塞,直到它收到EOF,填滿緩衝區,直到滿足該點爲止? – Louis 2012-07-30 14:44:57

+2

默認情況下使用TCP套接字,'read'只是阻塞,直到有一些數據(任何數據)可用。這可能是一個字節,也可能是一整行。 – 2012-07-30 14:45:26

+0

啊,我明白了。這讓我感到困惑。那麼在數據變得可用之前,如何在停止之前知道要讀取多少字節? – Louis 2012-07-30 14:46:47