如何在Python中进行简单的命令行聊天?

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()


如果你想从头开始编码select是要走的路(你可以在谷歌图书搜索中阅读包含这些问题的果壳中的大部分Python章节);如果你想利用更多的抽象,asyncore是可用的,但Twisted更丰富,更强大。


嗯,好吧,这就是我现在所拥有的。

服务器是这样的:

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。

    校验:

    • 另一个选择链接
    • 如何