如何用Python制作简单的命令行聊天?

12 投票
6 回答
26409 浏览
提问于 2025-04-15 12:23

我在学习网络编程,想用Python写一个简单的命令行聊天程序。

我想知道怎么才能在接收消息的同时,也能随时输入消息发送出去。

如你所见,这个客户端一次只能做一件事:

from socket import *

HOST = 'localhost'
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST, PORT)

tcpCliSock = socket(AF_INET, SOCK_STREAM)
tcpCliSock.connect(ADDR)

while 1:
    data = raw_input('> ')
    if not data: break
    tcpCliSock.send(data)
    data = tcpCliSock.recv(BUFSIZE)
    if not data: break
    print data

tcpCliSock.close()

所以如果其他客户端发来消息,这个客户端只能在发送完自己的消息后才能接收到。你应该能理解我的意思。我在网上查了很多资料,发现了很多有趣的东西,比如异步输入输出、线程、非阻塞同步、并发编程等等。我还安装了twisted这个包。总之,我在学习这些东西,但还没找到我想要的解决方案。(当然,我会继续努力,直到找到答案。)

所以,我的问题是怎么做到这一点呢?=)

6 个回答

2

聊天程序同时在做两件事情。

  1. 监听本地用户的键盘输入,并通过某种方式把这些信息发送给远程用户(比如通过一个网络连接)。

  2. 监听远程连接,显示他们在本地控制台上输入的内容。

你可以用几种方法来实现这个功能。

  1. 一个程序打开网络连接和键盘,然后使用select模块来检查哪个输入准备好了。

  2. 一个程序创建两个线程。一个线程读取远程连接的数据并打印出来,另一个线程读取键盘输入并发送到远程连接。

  3. 一个程序创建两个子进程。一个子进程读取远程连接的数据并打印,另一个子进程读取键盘输入并发送到远程连接。

5

如果你想从头开始编写代码,使用 select 是个不错的选择(你可以在谷歌图书搜索中找到《Python in a Nutshell》这本书的大部分章节,里面有讲到这些内容);如果你想用更高级的方式来处理,asyncore 也可以用,但 Twisted 更加丰富和强大。

8

你的问题表达得不是很清楚。不过,其实你的程序并不需要使用异步方式就能实现你想要的功能。

这是一个可以正常工作的聊天脚本,跟你最初想要的差不多,只做了很少的修改。它使用了1个线程来接收消息,1个线程来发送消息,两个线程都使用了阻塞式的套接字。这种方式比使用异步方法简单得多。

from socket import *
from threading import Thread
import sys

HOST = 'localhost'
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST, PORT)

tcpCliSock = socket(AF_INET, SOCK_STREAM)
tcpCliSock.connect(ADDR)

def recv():
    while True:
        data = tcpCliSock.recv(BUFSIZE)
        if not data: sys.exit(0)
        print data

Thread(target=recv).start()
while True:
    data = raw_input('> ')
    if not data: break
    tcpCliSock.send(data)

tcpCliSock.close()

撰写回答