чат Python с использованием опроса - PullRequest
2 голосов
/ 21 января 2012

Мне нужно построить чат на python, и я застрял на самом последнем этапе. Я собрал сервер и клиент, и у меня возникла следующая проблема при запуске кода:

  • server.py 127.0.0.1 -в отдельном окне client.py 127.0.0.1 другой клиент - введите псевдонимы для чата для обоих клиентов и получите правильный ответ «яппи», что означает, что вы подключены
  • клиент пытается говорить
  • сообщение не будет прочитано другим клиентом, пока оно не напечатает что-либо, после печати оно получит сообщение, правильно напечатанное на его экране.

Я бы хотел получить сообщение без необходимости что-либо печатать, это довольно нереально !!! Код клиента и сервера ниже в 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()

1 Ответ

0 голосов
/ 15 марта 2012

В следующий раз взгляните на http://www.zeromq.org/, у него хорошая привязка к питону http://zeromq.github.com/pyzmq/. Он идеально подходит для такого рода вещей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...