2015-11-30 68 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