2016-08-03 53 views
1

我有一个标准的服务器 - 客户端TCP设置。基本的想法是一个聊天系统。使用下面的逻辑使用sys.stdin之前的输入提示

sys.stdout.write('<%s> ' % username) 
sys.stdout.flush() 

while True: 
    socket_list = [sys.stdin, s] 
    read_sockets, write_sockets, error_sockets = select.select(socket_list, [], []) 
    for sock in read_sockets: 
     if sock == s: 
      data = sock.recv(4096) 
      if data: 
       output('\a\r%s' % data) #output incoming message 
       sys.stdout.write('<%s> ' % username) #prompt for input 
       sys.stdout.flush() 
      else: 
       raise SystemExit 
     else: 
      msg = getASCII(sys.stdin.readline()) # returns only the ascii 
      if msg: 
       s.send(msg) 
      sys.stdout.write('<%s> ' % username) 
      sys.stdout.flush()) 

(注:截断片断的完整代码,可以发现望着只有客户端的会话的端,客户端会提示用户输入与here链接的代码已更新,因此不再相关)

问题是,当用户正在键入并从服务器获取传入消息时,客户端会输出消息并再次提示输入。正在键入的消息仍然在stdin缓冲区中,但已从屏幕消失。如果用户按下Enter键发送消息,则将发送包括缓冲区中的内容的整个消息,但在用户的屏幕上,仅显示消息的第二部分,即中断后的部分。

我有一个可能的解决方案,那就是当我提示输入时,我检查缓冲区中是否有任何内容以及与提示一起输出,但我不知道如何实现它。任何帮助表示赞赏。

+0

您使用的是什么版本的Python? –

+0

Python 2.支持3应该不难。 – Awn

+0

要实施您的解决方案,您必须以非缓冲方式从标准输入读取数据。 'readline()'和'read()'阻塞直到EOL或EOF。您需要输入标准偏差前的数据,然后按下回车键。为了达到这个目的,这可能会有所帮助:http://code.activestate.com/recipes/134892-getch-like-unbuffered-character-reading-from-stdin/ 当您即将写入数据时,您可以阅读从stdin开始,将它存储在某个地方并在输出消息后再次输出它。由于select不会被stdin调用,所以创建一个读取stdin的单独读取线程。到目前为止,使用锁来访问stdin的数据。 – Munchhausen

回答

1

要实施您的解决方案,您必须以非缓冲方式从标准输入读取数据。 readline()和read()阻塞,直到EOL或EOF。您需要输入标准偏差前的数据,然后按下回车键。为了达到这个目的,这可能是有帮助的:http://code.activestate.com/recipes/134892-getch-like-unbuffered-character-reading-from-stdin/当你要写数据时,你可以从stdin中读取数据,将它存储在某个地方并在输出消息后再次输出。由于select不会被stdin调用,所以创建一个读取stdin的单独读取线程。到目前为止,使用锁来访问stdin的数据。

0

作为实现问题评论中讨论的自己的编辑行输入函数的替代方法,请考虑以下方法:更改滚动区域以省略屏幕的底线(用户输入行)并仅临时输入滚动区域输出传入的服务器消息。 That answer包含一个例子。

0

问题似乎是,您让来自其他用户的邮件中断打字。我建议你一次只听一件东西(当用户打字时让他完成并在听取远程消息之前按下输入键)您一次收听用户输入的一个键并建立自己的键缓冲区(见Polling the keyboard (detect a keypress) in python)。后面的方法的缺点是你需要实现键编辑等等。可能有一个库为你完成这个工作。

请注意,在大多数聊天程序中,您键入的区域位于与您看到消息的位置不同的窗口/屏幕区域。所有消息(您的以及其他消息)在此消息区域中完成时显示。也许你可以在屏幕上的其他地方使用显示消息(独立于输入)。