2015-11-30 100 views
0

我正在寫C語言的簡單客戶端 - 服務器程序來練習網絡編程。服務器可以使用多線程處理多個客戶端。每個客戶端都在一個單獨的線程中進行服務。客戶端使用兩個線程:一個從標準輸入接收用戶輸入,另一個輸出到標準輸出。爲什麼箭頭鍵搞砸了stdout?

我用普通的文本測試了程序,它完美地工作。但是,當我輸入箭頭鍵時(左鍵=^[[D,右鍵=^[[C,上鍵=^[[A,下鍵=^[[B]),其行爲非常奇怪。

例如看到以下輸出: 這是我在順序發送的輸入(在客戶端):

>> test 
I got your message 
>> test1 
I got your message 
>> test2 
I got your message 
>> test3 
I got your message 

這是在服務器中的(正確的)輸出:

Here is the message: test 
Here is the message: test1 
Here is the message: test2 
Here is the message: test3 

現在我輸入隨機方向鍵(輸入test3後):

>>^[[D^[[A^[[C^[[A^[[D^[[C^[[A^[[D^[[B^[[C^[[D^[[B^[[D^[[C^[[A^[[D^[[C^[[A^[[D^[[A^[[D^[[C^[[A 
I got your message 

但是,服務器打印什麼(我假設的人物進行轉義):

Here is the message: test 
Here is the message: test1 
Here is the message: test2 
Here is the message: test3 
Here is the message: 

Now, I start inputting normal text: 

>> test4 
I got your message 
>> test5 
I got your message 
>> test6 
I got your message 
>> test7 
I got your message 
>> test8 
I got your message 
>> test9 
I got your message 
>> test10 
I got your message 

當我檢查服務器的stdout,所有以前的打印輸出將被覆蓋:

Here is the message: test4 
Here is the message: test5 
Here is the message: test6 
Here is the message: test7 
Here is the message: test8 
Here is the message: test9 
Here is the message: test10 

最重要的是,該行爲有箭頭的隨機按鍵改變我進入。有時,輸入不會覆蓋服務器的stdout,但會在stdout中插入輸入。

我不確定爲什麼會發生這種情況,但如果有人想看我的消息來源,我可以發佈它。來源不長 - 客戶端和服務器長度大約爲100行。


好的我測試了每個鍵的分開。

向下鍵和向上鍵似乎將stdout中的文件指針按行移動。左右鍵看起來什麼都不做。

+0

你期望箭頭鍵做什麼? –

+0

嘗試使用調試器並逐行讀取光標鍵輸入時,逐行瀏覽代碼,並查看將它發送到服務器時的操作。然後在服務器中執行相同的操作,以查看它是否接收到任何內容,並逐步處理代碼處理數據的方式。 –

+0

我以爲它只會打印這些字符。 – 1729

回答

0

你很困惑stdout(這是一個字節流),結果將這些字節送入終端仿真器。如果您捕捉你的服務器的 stdout到一個文件,你就可以使用十六進制編輯器(或hd命令看它,你就會看到實際發送的字節數。

終端仿真需要這些字節並將它們轉換成動作,這些動作會導致顯示器顯示某些東西。字節或字節序列可能顯示爲單個字素(可見符號)或解釋爲控制代碼(移動光標,更改輸出或背景顏色等),或者即使只是被忽略

要理解這些字節是如何解釋的,你可以參考你的終端仿真器的文檔(如果你能找到它)或者嘗試XTerm documentation(wh ich特定於xterm,但大多數現代終端仿真器都是相似的)或man 4 console_codes(它專用於Linux控制檯,但又與大多數終端仿真器類似)。

+0

有沒有什麼方法可以指導Bash(我正在使用)把所有東西當作一個角色來對待。基本上,我將我從客戶端讀取的內容存儲在char數組緩衝區中。有沒有一個功能,打印完整的字符(我目前使用printf)? – 1729

+0

@ 1729。 Bash只是另一個程序。它不是*終端模擬器。 (我不知道你使用的是什麼終端模擬器:它是你用來創建運行bash的窗口的程序,如果你沒有終端模擬器,你不會有窗口:-) )所以bash確實把所有的東西看作是一個角色,但是終端模擬器會根據它認爲合適的角色來解釋角色。如果你想看到實際的字節,可以使用'hd'(將程序傳入'hd'或將輸出保存到文件中,然後在文件中使用'hd')。 – rici

+0

Bash說沒有命令'hd' – 1729

0

箭頭鍵正在發送多字符ANSI轉義序列。BASH(和其他程序)使用類似readline(或者curses)的庫來將轉義序列轉換爲光標移動/編輯。如果你不想使用這樣的庫,你可以將終端置於原始模式,讀取和處理每個轉義序列,並通過發送光標移動序列來移動光標,這是一個困難的過程。

+0

我可以使用一些精確打印字節的C函數,而不是使用終端仿真器嗎? – 1729

+0

也許** printf **。 – RTLinuxSW