wxpython select 聊天室server+client

一天看完python,一天wxpython,马上实践一下。


# -*- coding: utf-8 -*-
#Just for fuck jack!!!
#-----------------------------------
#author philsong    [email protected]
#V0.0.1 2012-8-14   initial version
#V0.0.2 2012-8-15   use mulplex select, wait for notification that an input or output channel is ready
#-----------------------------------

import wx
import socket
import thread
import sys
import select
import Queue

class chatdlg(wx.Dialog):
    def __init__(self):
        wx.Dialog.__init__(self, None, -1, 'chat window', 
                size=(600, 500))

        self.DisplayText = wx.TextCtrl(self, -1, '', 
                size=(600, 350), style=wx.TE_MULTILINE)

        self.InputText = wx.TextCtrl(self, -1, "Hi, jack! What the fuck are u doing now?", 
                pos=(5, 370), size=(500, -1))

        self.sendButton = wx.Button(self, -1, "Send", pos=(510, 370))
        self.Bind(wx.EVT_BUTTON, self.OnSendClick, self.sendButton)
        self.sendButton.SetDefault()

        wx.StaticText(self, -1, "IP", (5, 415))
        self.IPText = wx.TextCtrl(self, -1, "219.147.23.114", 
                pos=(30, 415), size=(150, -1))
        wx.StaticText(self, -1, "Port", (200, 415))
        self.PortText = wx.TextCtrl(self, -1, "8001", 
                pos=(230, 415), size=(50, -1))

        self.cButton = wx.Button(self, -1, "Connect as a client", pos=(280, 415))
        self.Bind(wx.EVT_BUTTON, self.OnClientClick, self.cButton)
        self.sButton = wx.Button(self, -1, "Connect as a Server", pos=(390, 415))
        self.Bind(wx.EVT_BUTTON, self.OnSeverClick, self.sButton)

    def OnSendClick(self, event):
       #self.sendButton.SetLabel("Clicked")
        self.send_data = self.InputText.GetValue()
        try:
            self.client.send(self.send_data)
            self.DisplayText.AppendText('\nYour said:  [')
            self.DisplayText.AppendText(self.send_data)
            self.DisplayText.AppendText(']\n')
        except  socket.error, e:
            self.DisplayText.AppendText('Pls connect to chat server @%d firstly\n' % self.port)

    def SocketProc_server(self):
        self.sButton.SetLabel(self.PortText.GetValue())
        
        # Sockets to which we expect to write
        outputs = [ ]

        # Outgoing message queues (socket:Queue)
        message_queues = {}

        #创建socket并绑定
        self.server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        self.port = int(self.PortText.GetValue())
        self.host = ''

        print 'Waiting for connection @%s:%d\n' % (self.host, self.port)

        self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.server.bind((self.host, self.port))
        self.server.listen(5)        

        self.DisplayText.AppendText('Waiting for connection @%s:%d\n' % (self.host, self.port))

        # Sockets from which we expect to read
        inputs = [ self.server ]

        while inputs:
            # Wait for at least one of the sockets to be ready for processing
            print >>sys.stderr, '\nwaiting for the next event'
            readable, writable, exceptional = select.select(inputs, outputs, inputs)
            
            # Handle inputs
            for s in readable:
                if s is self.server:
                    # A "readable" server socket is ready to accept a connection
                    connection, client_address = s.accept()
                    print >>sys.stderr, 'new connection from', client_address
                    self.DisplayText.AppendText('new connection from %s %s\n' % client_address)
                    connection.setblocking(False)
                    inputs.append(connection)

                    # Give the connection a queue for data we want to send
                    message_queues[connection] = Queue.Queue()
                else:
                    data = s.recv(1024)
                    if data:
                        # A readable client socket has data
                        print >>sys.stderr, 'received [%s] from %s' % (data, s.getpeername())

                        self.DisplayText.AppendText('received [%s] from %s\n' % (data, s.getpeername()))

                        for c in inputs:
                            if c is self.server:
                                print >>sys.stderr, 'from server'
                            elif c is not s:
                                print >>sys.stderr, 'send_data [%s] to %s' % (data, s.getpeername())
                                message_queues[c].put('[' + data + '] from'+str(s.getpeername()))
                                if c not in outputs:
                                    outputs.append(c)
                    else:
                        # Interpret empty result as closed connection
                        print >>sys.stderr, 'closing', client_address, 'after reading no data'

                        self.DisplayText.AppendText('closing %s %s after reading no data\n\n' % client_address)
                        # Stop listening for input on the connection
                        if s in outputs:
                            outputs.remove(s)
                        inputs.remove(s)
                        s.close()
                        
                        # Remove message queue
                        del message_queues[s]

            # Handle outputs
            for s in writable:
                try:
                    next_msg = message_queues[s].get_nowait()
                except Queue.Empty:
                    # No messages waiting so stop checking for writability.
                    print >>sys.stderr, 'output queue for', s.getpeername(), 'is empty'
                    outputs.remove(s)
                else:
                    print >>sys.stderr, 'sending "%s" to %s' % (next_msg, s.getpeername())
                    s.send(next_msg)
            # Handle "exceptional conditions"
            for s in exceptional:
                print >>sys.stderr, 'handling exceptional condition for', s.getpeername()
                self.DisplayText.AppendText('handling exceptional condition for', s.getpeername())
                # Stop listening for input on the connection
                inputs.remove(s)
                if s in outputs:
                    outputs.remove(s)
                s.close()

                # Remove message queue
                del message_queues[s]   

    def SocketProc_client(self):
        self.cButton.SetLabel(self.PortText.GetValue())
        
        # Sockets to which we expect to write
        outputs = [ ]

        # Outgoing message queues (socket:Queue)
        message_queues = {}

        self.client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        self.host = str(self.IPText.GetValue())
        self.port = int(self.PortText.GetValue())
        print 'Connecting to chat server@%s:%d\n' % (self.host, self.port)
        try:
            self.client.connect((self.host, self.port))
            print 'connected to chat server @%s:%d\n' % (self.host, self.port)
            self.DisplayText.AppendText('Connected to chat server@%s:%d\n' % (self.host, self.port))
        except socket.error, e:
            print 'Could not connect to chat server @%s:%d\n' % (self.host, self.port)
            self.DisplayText.AppendText('Could not connect to chat server @%s:%d\n' % (self.host, self.port))
            return

        inputs = [ self.client ]
        message_queues[self.client] = Queue.Queue()


        while inputs:
            # Wait for at least one of the sockets to be ready for processing
            print >>sys.stderr, '\nwaiting for the next event'
            readable, writable, exceptional = select.select(inputs, outputs, inputs)
            
            # Handle inputs
            for s in readable:
                data = s.recv(1024)
                if data:
                    # A readable client socket has data
                    print >>sys.stderr, 'received "%s" from %s' % (data, s.getpeername())

                    self.DisplayText.AppendText('received "%s"\n' % data)
                else:
                    # Interpret empty result as closed connection
                    print >>sys.stderr, 'closing', client_address, 'after reading no data'

                    self.DisplayText.AppendText('closing %s %s after reading no data\n\n' % client_address)
                    # Stop listening for input on the connection
                    if s in outputs:
                        outputs.remove(s)
                    inputs.remove(s)
                    s.close()
                    
                    # Remove message queue
                    del message_queues[s]

            # Handle outputs
            for s in writable:
                try:
                    next_msg = message_queues[s].get_nowait()
                except Queue.Empty:
                    # No messages waiting so stop checking for writability.
                    print >>sys.stderr, 'output queue for', s.getpeername(), 'is empty'
                    outputs.remove(s)
                else:
                    print >>sys.stderr, 'sending "%s" to %s' % (next_msg, s.getpeername())
                    s.send(next_msg)
            # Handle "exceptional conditions"
            for s in exceptional:
                print >>sys.stderr, 'handling exceptional condition for', s.getpeername()
                self.DisplayText.AppendText('handling exceptional condition for', s.getpeername())
                # Stop listening for input on the connection
                inputs.remove(s)
                if s in outputs:
                    outputs.remove(s)
                s.close()

                # Remove message queue
                del message_queues[s]    
    def SocketProc_process(self):
        pass
        #recv all recv_data
        #broadcast msg

    def OnSeverClick(self, event):
        self.socketmode=1
        thread.start_new_thread(self.SocketProc_server,())

    def OnClientClick(self, event):
        self.socketmode=0
        #self.cButton.SetLabel("connected")
        thread.start_new_thread(self.SocketProc_client,())

if __name__ == '__main__':
    app = wx.PySimpleApp()
    app.MainLoop() 
    dialog = chatdlg()
    result = dialog.ShowModal()
    if result == wx.ID_OK:
        print "OK"
    else:
        print "Cancel"
    dialog.Destroy()


你可能感兴趣的:(wxpython select 聊天室server+client)