How to make a simple command-line chat in Python?
我学习网络编程,想在Python中编写一个简单的命令行聊天。
我想知道如何随时随地输入可用于发送的接收。
如您所见,此客户端一次只能执行一项任务:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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() |
因此,如果另一个客户端发送消息,该客户端也将仅在发送消息后接收它。 我打赌你了解我。 我搜索了这个问题,发现了很多有趣的东西,比如异步I / O,线程,非阻塞同步,并发编程等等。 我也安装了扭曲的包装。 简而言之,我一直在学习所有这些东西但却找不到我想要的东西。 (当然,我会一直努力尝试,直到我说到这一点。)
所以,我的问题是如何制作的?=)
你的问题不是很一致。但是,您的程序根本不需要异步即可实现您的要求。
这是一个您最初想要的工作聊天脚本,只需要很少的更改。它使用1个线程进行接收,1个用于发送,两者都使用阻塞套接字。它比使用异步方法简单得多。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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() |
如果你想从头开始编码
嗯,好吧,这就是我现在所拥有的。
服务器是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | import asyncore import socket clients = {} class MainServerSocket(asyncore.dispatcher): def __init__(self, port): asyncore.dispatcher.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.bind(('',port)) self.listen(5) def handle_accept(self): newSocket, address = self.accept( ) clients[address] = newSocket print"Connected from", address SecondaryServerSocket(newSocket) class SecondaryServerSocket(asyncore.dispatcher_with_send): def handle_read(self): receivedData = self.recv(8192) if receivedData: every = clients.values() for one in every: one.send(receivedData+' ') else: self.close( ) def handle_close(self): print"Disconnected from", self.getpeername( ) one = self.getpeername( ) del clients[one] MainServerSocket(21567) asyncore.loop( ) |
客户端就像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | from Tkinter import * from socket import * import thread HOST = 'localhost' PORT = 21567 BUFSIZE = 1024 ADDR = (HOST, PORT) tcpCliSock = socket(AF_INET, SOCK_STREAM) tcpCliSock.connect(ADDR) class Application(Frame): def __init__(self, master): Frame.__init__(self, master) self.grid() self.create_widgets() self.socket() def callback(self, event): message = self.entry_field.get() tcpCliSock.send(message) def create_widgets(self): self.messaging_field = Text(self, width = 110, height = 20, wrap = WORD) self.messaging_field.grid(row = 0, column = 0, columnspan = 2, sticky = W) self.entry_field = Entry(self, width = 92) self.entry_field.grid(row = 1, column = 0, sticky = W) self.entry_field.bind('<Return>', self.callback) def add(self, data): self.messaging_field.insert(END, data) def socket(self): def loop0(): while 1: data = tcpCliSock.recv(BUFSIZE) if data: self.add(data) thread.start_new_thread(loop0, ()) root = Tk() root.title("Chat client") root.geometry("550x260") app = Application(root) root.mainloop() |
现在是时候让代码看起来更好并添加一些功能。
伙计们,感谢您的帮助!
聊天程序同时做两件事。
观看本地用户的键盘并发送给远程用户(通过某种插座)
观察远程套接字并在本地控制台上显示它们键入的内容。
你有几种方法可以做到这一点。
一个程序,用于打开套接字和键盘,并使用选择模块查看哪个输入就绪。
一个创建两个线程的程序。一个线程读取远程套接字并打印。另一个线程读取键盘并发送到远程套接字。
一个分叉两个子进程的程序。一个子进程读取远程套接字并打印。另一个子进程读取键盘并发送到远程套接字。
我在异步I / O中编写了一个...它比完整的线程模型更容易包围你。
如果你能掌握"谈话"的源代码,你可以学到很多东西。看一个演示http://dsl.org/cookbook/cookbook_40.html#SEC559,或者如果你在Linux机器上试试吧...
它实时发送字符。
此外,ytalk是互动和多个用户....有点像hudddlechat或篝火。
你应该使用select。
校验:
- 另一个选择链接
- 如何