Skip to main content
 首页 » 编程设计

使用轮询的python聊天

2025年05月04日12shihaiming

我需要构建一个 Python 聊天,我正处于最后一步。我已经构建了服务器和客户端,但在运行代码时遇到以下问题:

  • server.py 127.0.0.1 - 在单独的窗口中 client.py 127.0.0.1 -另一个客户 - 输入昵称来为两个客户聊天并获得正确答案“yuppie”意味着您已连接
  • 客户尝试说话
  • 消息在其他客户端不打印之前不会被其他客户端读取,打印后它会在其屏幕上正确打印消息。

我想在不打印某些东西的情况下收到消息,这很不现实!!!客户端和服务器的代码在下面的 2 个不同的类中。谢谢!

#! /usr/bin/env python 
 
import socket,sys,select,re 
 
PORT=1060   
 
class Server(): 
 
 
    def __init__(self,host): 
        #building listen_sock   
        self.listen_sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 
        self.listen_sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) 
        self.listen_sock.bind((host,PORT)) 
        self.listen_sock.listen(20) 
        #building dict for socket and socket state 
        self.sockets={self.listen_sock.fileno(): self.listen_sock} 
        self.socket_state={self.listen_sock.fileno():''} 
        #building poll object 
        self.poll=select.poll() 
        self.poll.register(self.listen_sock,select.POLLIN) 
        #users' list 
        self.users_list={} 
 
 
 
        #DON'T LOOK HERE 
        #initialize the sender 
        #self.sender=0 
 
     #   self.users=re.compile("\s*\$(get users connected)$\s*",re.IGNORECASE) 
      #  self.nick=re.compile("\s*\$\$(\w*\d*)\$\$\s*",re.IGNORECASE) 
       # self.quit=re.compile("\s*\$(quit)\$\s*",re.IGNORECASE) 
        #self.commands=[self.users,self.nick,self.quit] 
 
 
 
 
    #funcion to receive message from client (work well) 
    def recv_until(self,fd,suffix): 
        self.message='' 
        #checking the end of the message 
        while not self.message.endswith(suffix): 
            data=self.sockets[fd].recv(16) 
            if not data: 
                raise EOFError('socket closed before we saw %r' % suffix) 
            self.message+=data     
        self.message=self.message[:-1] 
 
 
   #delete client (work well) 
    def del_client(self,fd): 
        del self.users_list[fd] 
        del self.socket_state[fd] 
        self.poll.unregister(fd) 
 
       #print the remaining active connections 
        if not len(self.users_list): 
            print 'Anyone is connected, waiting for new connection' 
        else: 
            print self.users_list 
 
 
 
    #add new client and change the of the file descriptor for that client (work well) 
    def new_client(self,fd): 
        newsock, sockname = self.listen_sock.accept() 
        print 'new connection from ', newsock.getpeername() 
        newsock.setblocking(False) 
        #recording the new connection 
        fd=newsock.fileno() 
        self.sockets[fd]=newsock 
        self.poll.register(fd,select.POLLOUT) 
        self.socket_state[fd]='ask nick' 
 
 
 
 
 #DON'T LOOK HERE  
 #   def handle_query(self,fd): 
 
 
  #      for n,command in enumerate(self.commands): 
 
   #         match=command.search(self.message) 
 
 
    #        if n==1 and match: 
 
     #           self.users_list[self.sockets[fd].getpeername()]=match.group(1) 
      #          print self.users_list 
 
       #         for value in self.users_list.values(): 
        #            self.sockets[fd].sendall(value+'\n') 
 
 
 
 
    #starting the main function of the class 
    def chat(self): 
 
        while True:  
            #here il where the code hangs up waitng and waiting (WORKS BAD) 
            #return a tuple, identify where (fd) the event (event) is happening 
            for fd,event in self.poll.poll(): 
                #print the state of each socket and the poll object 
                print self.socket_state 
                print self.poll.poll() 
 
 
                #starting the state machine 
 
                #remove closed sockets 
                if event & (select.POLLHUP | select.POLLERR |  
                select.POLLNVAL):  
                    #deleting the socket closed at fd 
                    self.del_client(fd) 
 
 
                #if the socket referred to is our listen_sock and we have a new connection request    
                elif self.sockets[fd] is self.listen_sock: 
                    #recording the new entry! 
                    self.new_client(fd) 
 
 
 
 
                #managing all the situation where it is necessary to answer to a client 
                #and changing the state of the socket and that of the sockets[fd] 
                elif event & select.POLLOUT: 
 
                    if self.socket_state[fd]=='ask nick': 
                        self.sockets[fd].sendall('identify\n') 
                        self.poll.modify(self.sockets[fd],select.POLLIN) 
                        self.socket_state[fd]='get user' 
 
                    if self.socket_state[fd]=='invalid nick': 
                        self.sockets[fd].sendall('invalid nick\n') 
                        for value in self.users_list.values(): 
                            self.sockets[fd].sendall('\n'+value+'\n') 
                        self.socket_state[fd]='ask nick' 
 
                    if self.socket_state[fd]=='connected': 
                        print '3' 
                        self.sockets[fd].sendall('yuppie\n') 
                        self.poll.modify(self.sockets[fd],select.POLLIN) 
                        self.socket_state[fd]='ready to communicate' 
 
                    if self.socket_state[fd]=='ready to receive': 
                        self.sockets[fd].sendall(self.message) 
                        print '4' 
                        self.poll.modify(self.sockets[fd],select.POLLIN) 
                        self.socket_state[fd]='ready to communicate' 
 
 
 
 
                #managing all the situation where it is necessary to get values from clients 
                elif event & select.POLLIN: 
 
                    if self.socket_state[fd]=='get user': 
 
                        self.recv_until(fd,'\n') 
 
                        if self.message not in self.users_list.values(): 
                            self.users_list[fd]=self.message 
                            self.poll.modify(self.sockets[fd],select.POLLOUT) 
                            self.socket_state[fd]='connected' 
                        else: 
                            self.poll.modify(self.sockets[fd],select.POLLOUT) 
                            self.socket_state[fd]='invalid nick' 
 
                    if self.socket_state[fd]=='ready to communicate': 
                        self.recv_until(fd,'\n') 
                        print '5' 
                        for i in self.users_list.keys(): 
                            if i!=fd: 
                                self.poll.modify(self.sockets[i],select.POLLOUT) 
                                self.socket_state[i]='ready to receive' 
 
 
 
 
if __name__ == '__main__': 
    se=Server(sys.argv[1]) 
    se.chat() 
 
 
 
 
 
 
#! /usr/bin/env python 
 
import sys,socket,select,threading,time 
 
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 
 
HOST=sys.argv.pop() 
PORT=1060 
 
 
class Client(): 
 
 
    def setup(self): 
 
        server_address=(HOST,PORT) 
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
        self.sock.connect(server_address) 
 
 
 
    def chat(self): 
        while True: 
            time.sleep(1) 
            text=raw_input('>>> ') 
            self.sock.sendall(text+'\n') 
 
 
 
 
    def rec(self): 
        while True: 
            mess=self.sock.recv(16) 
            if mess: 
                print '$$$ ', mess, 
 
 
    def start(self): 
        l=threading.Thread(target=self.rec) 
        t=threading.Thread(target=self.chat) 
 
 
        t.start() 
        l.start() 
 
 
if __name__=='__main__': 
    cl=Client() 
    cl.setup() 
    cl.start() 

请您参考如下方法:

下次看看http://www.zeromq.org/ , 它有一个很好的 python 绑定(bind) http://zeromq.github.com/pyzmq/ .它非常适合这类东西。