Python聊天室

Python聊天室

一、套接字

    套接字是为特定网络协议(例如TCP/IP,ICMP/IP,UDP/IP等)套件对上的网络应用程序提供者提供当前可移植标准的对象。它们允许程序接受并进行连接,如发送和接受数据。为了建立通信通道,网络通信的每个端点拥有一个套接字对象极为重要。
    套接字为BSD UNIX系统核心的一部分,而且他们也被许多其他类似UNIX的操作系统包括Linux所采纳。许多非BSD UNIX系统(如ms-dos,windows,os/2,mac os及大部分主机环境)都以库形式提供对套接字的支持。
    三种最流行的套接字类型是:stream,datagram和raw。stream和datagram套接字可以直接与TCP协议进行接口,而raw套接字则接口到IP协议。但套接字并不限于TCP/IP。

二、套接字模块

    套接字模块是一个非常简单的基于对象的接口,它提供对低层BSD套接字样式网络的访问。使用该模块可以实现客户机和服务器套接字。要在python 中建立具有TCP和流套接字的简单服务器,需要使用socket模块。利用该模块包含的函数和类定义,可生成通过网络通信的程序。

服务器端:

step-1:

        创建socket对象。调用socket构造函数。

        socket=socket.socket(familly,type)

        family的值可以是AF_UNIX(Unix域,用于同一台机器上的进程间通讯),也可以是AF_INET(对于IPV4协议的TCP和 UDP),至于type参数,SOCK_STREAM(流套接字)或者 SOCK_DGRAM(数据报文套接字),SOCK_RAW(raw套接字)。

step-2:

        将socket绑定(指派)到指定地址上。

        socket.bind(address)

        address必须是一个双元素元组,((host,port)),主机名或者ip地址+端口号。如果端口号正在被使用或者保留,或者主机名或ip地址错误,则引发socke.error异常。

step-3:

        绑定后,必须准备好套接字,以便接受连接请求。

        socket.listen(backlog)

        backlog指定了最多连接数,至少为1,接到连接请求后,这些请求必须排队,如果队列已满,则拒绝请求。

step-4:

        服务器套接字通过socket的accept方法等待客户请求一个连接。

        connection,address=socket.accept()

        调用accept方法时,socket会进入'waiting'(或阻塞)状态。客户请求连接时,方法建立连接并返回服务器。accept方法返回一个含有俩个元素的元组,形如(connection,address)。第一个元素(connection)是新的socket对象,服务器通过它与客户通信;第二个元素(address)是客户的internet地址。

step-5:

        处理阶段,服务器和客户通过send和recv方法通信(传输数据)。服务器调用send,并采用字符串形式向客户发送信息。send方法返回已发送的字符个数。服务器使用recv方法从客户接受信息。调用recv时,必须指定一个整数来控制本次调用所接受的最大数据量。recv方法在接受数据时会进入'blocket'状态,最后返回一个字符串,用它来表示收到的数据。如果发送的量超过recv所允许,数据会被截断。多余的数据将缓冲于接受端。以后调用recv时,多余的数据会从缓冲区删除。

step-6:

        传输结束,服务器调用socket的close方法以关闭连接。

客户端:

step-1:

        创建一个socket以连接服务器。

        socket=socket.socket(family,type)

step-2:

        使用socket的connect方法连接服务。

        socket.connect((host,port))

step-3:

        客户和服务器通过send和recv方法通信。
step-4:

        结束后,客户通过调用socket的close方法来关闭连接。

server.py

    if __name__ == '__main__':
        import socket
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.bind(("XXX.XXX.XXX.X", XXXX))
        sock.listen(5)
        connection,address = sock.accept()
        data = connection.recv(1024)
        print data
        if data == '1\'m on your own side.':
            connection.send('welcome!')
        else:
            connection.send('gun!')
        connection.close()

client.py

    if __name__ == '__main__':
        import socket
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect(("XXX.XXX.XXX.X", XXXX))
        key=raw_input("join us or not? y/n. ")
        if key is "y":
            sock.send('1\'m on your own side.')
        if key is "n":
            sock.send('fuck you all!')
            print sock.recv(1024)
        sock.close()
    这是一个简单网络编程。
    在终端运行server.py,然后运行clien.py,会在终端打印“join us or not? y/n."。如果客户端输入"y",则服务器端会收到"1'm on your own side."。如果客户端输入"n",则服务器端会收到"fuck you all!",然后服务器端会回敬一句"gun!"。

serverplus.py

    import socket,select,thread;

    host=socket.gethostname()
    port=5963
    addr=(host,port)

    inputs=[]
    fd_name={}

    def main():
        print 'runing'
        ss=socket.socket()
        ss.bind(addr)
        ss.listen(5)
        inputs.append(ss)
        while True:
            r,w,e=select.select(inputs,[],[])
            for temp in r:
                if temp is ss:  
                    client,add=ss.accept()
                    print 'welcome %s %s' % (client,add)
                    wel='''welcome into the talking room . please decide your name.....'''
                    try:
                        client.send(wel)
                        name=client.recv(1024)
                        inputs.append(client)
                        fd_name[client]=name
                        for client in fd_name:
                            fd_name.append(fd_name[client])
                        nameList="Some people in talking room, these are %s" % (fd_name)
                        client.send(nameList)    
                    except Exception,e:
                        print e            
                else:
                    disconnect=False
                    try:
                        data= temp.recv(1024)
                        data=fd_name[temp]+' say : '+data
                    except socket.error:
                        data=fd_name[temp]+' leave the room'
                        disconnect=True                    
                    if disconnect:
                        inputs.remove(temp)
                        print data
                        for other in inputs:
                            if other!=ss and other!=temp:
                                try:
                                    other.send(data)
                                except Exception,e:
                                    print e                    
                        del fd_name[temp]                   
                    else:
                        print data                  
                        for other in inputs:
                            if other!=ss and other!=temp:
                                try:
                                    other.send(data)
                                except Exception,e:
                                    print e

    if __name__=='__main__':
        main()            

clientplus.py

    import socket,select,threading,sys;

    host=socket.gethostname()
    addr=(host,5963)

    def lis(s):
        my=[s]
        while True:
            r,w,e=select.select(my,[],[])
            if s in r:
                try:
                    print s.recv(1024)
                except socket.error:
                    print 'socket is error'
                    exit()

    def talk(s):
        while True:
            try:
                info=raw_input()
            except Exception,e:
                print 'can\'t input'
                exit()
            try:
                s.send(info)
            except Exception,e:
                print e
                exit()

    def main():
        ss=socket.socket()
        ss.connect(addr)
        t=threading.Thread(target=lis,args=(ss,))
        t.start()
        t1=threading.Thread(target=talk,args=(ss,))
        t1.start()

    if __name__=='__main__':
        main()
    这是一个终端聊天室,加入了多线程运行和异常处理。

chatroom.py

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

    class chatdlg(wx.Dialog):
        #initUI
        def __init__(self):  
            wx.Dialog.__init__(self,None,-1,"chat room",size=(400,400))  
            wx.StaticText(self,-1,"IP",pos=(10,14))  
            self.IPText = wx.TextCtrl(self,-1,"",pos=(30,10),size=(104,25))  
            wx.StaticText(self,-1,"Port",pos=(144,14))  ;
            self.PortText = wx.TextCtrl(self,-1,"",pos=(180,10),size=(46,25))
            wx.StaticText(self,-1,"Nickname",pos=(236,14))  
            self.NicknameText = wx.TextCtrl(self,-1,"*Anonym",pos=(304,10),size=(80,25))  
            self.cButton = wx.Button(self,-1,"Client",pos=(10,45),size=(185,50))  
            self.Bind(wx.EVT_BUTTON,self.OnClientClick,self.cButton)  
            self.sButton = wx.Button(self,-1,"Server",pos=(200,45),size=(185,50))  
            self.Bind(wx.EVT_BUTTON,self.OnSeverClick,self.sButton)  
            self.DisplayText = wx.TextCtrl(self,-1,"",pos=(10,104),size=(373,198),style=wx.TE_MULTILINE)  
            self.InputText = wx.TextCtrl(self,-1,"",pos=(10,312),size=(263,50),style=wx.TE_MULTILINE)  
            self.sendButton = wx.Button(self,-1,"Send",pos=(283,312),size=(100,50))  
            self.Bind(wx.EVT_BUTTON,self.OnSendClick,self.sendButton)  
            self.sendButton.SetDefault()  

        #SendButoon
        def OnSendClick(self,event):  
           #self.sendButton.SetLabel("Clicked")  
            self.send_data = self.InputText.GetValue()  
            self.nick_name = self.NicknameText.GetValue()
            try:  
                self.client.send(self.nick_name+" said: "+self.send_data+"\n")  
                self.DisplayText.AppendText(self.nick_name+" said: "+self.send_data+"\n")
                self.InputText.SetValue("")
            except  socket.error,e:  
                print "could not connect to chat server @%s:%d\n" % (self.host,self.port)  
                return  
        #ServerButoon
        def OnSeverClick(self,event):  
            self.socketmode=1  
            thread.start_new_thread(self.SocketProc_server,())  

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

        #Server
        def SocketProc_server(self):    
            # Sockets to which we expect to write  
            outputs = [ ]  

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

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

            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,"waiting for the next event\n"  
                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,"@%s:%s" % (s.getpeername(),data)  

                            self.DisplayText.AppendText("@%s:%s" % (s.getpeername(),data))  

                            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)  
                                    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]     
        #Client
        def SocketProc_client(self):  
            # 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)  
            except socket.error,e:  
                print "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(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  

    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() 
    这是一个图形聊天室,加入了图形界面。
    //如果有用,那么本文是lancer写的
    //如果没用,那么我也不知道是谁写的
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值