`
hnylj
  • 浏览: 209776 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Python在线聊天

阅读更多

 

发布一个用Python实现的一个在线聊天,主要功能是实现客户端与服务器端的双向通信,这个小东西用到的主要知识点:

1.Python Socket;
2.Python Tkinter库。

 

当然也应该了解如下的基础知识:
1.Python基本语法;
2.Python基本语句;
3.Python函数;
4.Python模块;
5.Python异常处理;
6.Python面向对象;

7.Python线程等相关知识。

 

另外:我使用的是Python2.5这个版本,如果你使用的Python3.0,可能不兼容。 推荐使用稳定的2.5版,linux系统默认安装的也是2.5这个版本,许多第三方库也是使用2.5这个版本。

 

下面是这个小东西的一个截图:

 

 

下面是服务器端代码:

# _*_ coding:utf-8 _*_
# Filename:ServerUI.py
# Python在线聊天服务器端

import Tkinter
import tkFont
import socket
import thread
import time
import sys

class ServerUI():
    
    title = 'Python在线聊天-服务器端V1.0'
    local = '127.0.0.1'
    port = 8808
    global serverSock;
    flag = False
    
    #初始化类的相关属性,类似于Java的构造方法
    def __init__(self):
        self.root = Tkinter.Tk()
        self.root.title(self.title)
        
        #窗口面板,用4个frame面板布局
        self.frame = [Tkinter.Frame(),Tkinter.Frame(),Tkinter.Frame(),Tkinter.Frame()]

        #显示消息Text右边的滚动条
        self.chatTextScrollBar = Tkinter.Scrollbar(self.frame[0])
        self.chatTextScrollBar.pack(side=Tkinter.RIGHT,fill=Tkinter.Y)
        
        #显示消息Text,并绑定上面的滚动条
        ft = tkFont.Font(family='Fixdsys',size=11)
        self.chatText = Tkinter.Listbox(self.frame[0],width=70,height=18,font=ft)
        self.chatText['yscrollcommand'] = self.chatTextScrollBar.set
        self.chatText.pack(expand=1,fill=Tkinter.BOTH)
        self.chatTextScrollBar['command'] = self.chatText.yview()
        self.frame[0].pack(expand=1,fill=Tkinter.BOTH)
        
        #标签,分开消息显示Text和消息输入Text
        label = Tkinter.Label(self.frame[1],height=2)
        label.pack(fill=Tkinter.BOTH)
        self.frame[1].pack(expand=1,fill=Tkinter.BOTH)
        
        #输入消息Text的滚动条
        self.inputTextScrollBar = Tkinter.Scrollbar(self.frame[2])
        self.inputTextScrollBar.pack(side=Tkinter.RIGHT,fill=Tkinter.Y)
        
        #输入消息Text,并与滚动条绑定
        ft = tkFont.Font(family='Fixdsys',size=11)
        self.inputText = Tkinter.Text(self.frame[2],width=70,height=8,font=ft)
        self.inputText['yscrollcommand'] = self.inputTextScrollBar.set
        self.inputText.pack(expand=1,fill=Tkinter.BOTH)
        self.inputTextScrollBar['command'] = self.chatText.yview()
        self.frame[2].pack(expand=1,fill=Tkinter.BOTH)
        
        #发送消息按钮
        self.sendButton=Tkinter.Button(self.frame[3],text=' 发 送 ',width=10,command=self.sendMessage)
        self.sendButton.pack(expand=1,side=Tkinter.BOTTOM and Tkinter.RIGHT,padx=25,pady=5)

        #关闭按钮
        self.closeButton=Tkinter.Button(self.frame[3],text=' 关 闭 ',width=10,command=self.close)
        self.closeButton.pack(expand=1,side=Tkinter.RIGHT,padx=25,pady=5)
        self.frame[3].pack(expand=1,fill=Tkinter.BOTH)
        
    #接收消息
    def receiveMessage(self):
        #建立Socket连接
        self.serverSock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        self.serverSock.bind((self.local,self.port))
        self.serverSock.listen(15)
        self.buffer = 1024
        self.chatText.insert(Tkinter.END,'服务器已经就绪......')
        #循环接受客户端的连接请求
        while True:
            self.connection,self.address = self.serverSock.accept()
            self.flag = True
            while True:
                #接收客户端发送的消息
                self.cientMsg = self.connection.recv(self.buffer)
                if not self.cientMsg:
                    continue
                elif self.cientMsg == 'Y':
                    self.chatText.insert(Tkinter.END,'服务器端已经与客户端建立连接......')
                    self.connection.send('Y')
                elif self.cientMsg == 'N':
                    self.chatText.insert(Tkinter.END,'服务器端与客户端建立连接失败......')
                    self.connection.send('N')
                else:
                    theTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
                    self.chatText.insert(Tkinter.END, '客户端 ' + theTime +' 说:\n')
                    self.chatText.insert(Tkinter.END, '  ' + self.cientMsg)
    
    #发送消息
    def sendMessage(self):
        #得到用户在Text中输入的消息
        message = self.inputText.get('1.0',Tkinter.END)
        #格式化当前的时间
        theTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        self.chatText.insert(Tkinter.END, '服务器 ' + theTime +' 说:\n')
        self.chatText.insert(Tkinter.END,'  ' + message + '\n')
        if self.flag == True:
            #将消息发送到客户端
            self.connection.send(message)
        else:
            #Socket连接没有建立,提示用户
            self.chatText.insert(Tkinter.END,'您还未与客户端建立连接,客户端无法收到您的消息\n')
        #清空用户在Text中输入的消息
        self.inputText.delete(0.0,message.__len__()-1.0)
    
    #关闭消息窗口并退出
    def close(self):
        sys.exit()
    
    #启动线程接收客户端的消息
    def startNewThread(self):
        #启动一个新线程来接收客户端的消息
        #thread.start_new_thread(function,args[,kwargs])函数原型,
        #其中function参数是将要调用的线程函数,args是传递给线程函数的参数,它必须是个元组类型,而kwargs是可选的参数
        #receiveMessage函数不需要参数,就传一个空元组
        thread.start_new_thread(self.receiveMessage,())
    
def main():
    server = ServerUI()
    server.startNewThread()
    server.root.mainloop()
    
if __name__=='__main__':
    main()

 

 

下面是客户端代码:

# _*_ coding:utf-8 _*_
# Filename:ClientUI.py
# Python在线聊天客户端

import Tkinter
import tkFont
import socket
import thread
import time
import sys

class ClientUI():
    
    title = 'Python在线聊天-客户端V1.0'
    local = '127.0.0.1'
    port = 8808
    global clientSock;
    flag = False
    
    #初始化类的相关属性,类似于Java的构造方法
    def __init__(self):
        self.root = Tkinter.Tk()
        self.root.title(self.title)
        
        #窗口面板,用4个面板布局
        self.frame = [Tkinter.Frame(),Tkinter.Frame(),Tkinter.Frame(),Tkinter.Frame()]

        #显示消息Text右边的滚动条
        self.chatTextScrollBar = Tkinter.Scrollbar(self.frame[0])
        self.chatTextScrollBar.pack(side=Tkinter.RIGHT,fill=Tkinter.Y)
        
        #显示消息Text,并绑定上面的滚动条
        ft = tkFont.Font(family='Fixdsys',size=11)
        self.chatText = Tkinter.Listbox(self.frame[0],width=70,height=18,font=ft)
        self.chatText['yscrollcommand'] = self.chatTextScrollBar.set
        self.chatText.pack(expand=1,fill=Tkinter.BOTH)
        self.chatTextScrollBar['command'] = self.chatText.yview()
        self.frame[0].pack(expand=1,fill=Tkinter.BOTH)
        
        #标签,分开消息显示Text和消息输入Text
        label = Tkinter.Label(self.frame[1],height=2)
        label.pack(fill=Tkinter.BOTH)
        self.frame[1].pack(expand=1,fill=Tkinter.BOTH)
        
        #输入消息Text的滚动条
        self.inputTextScrollBar = Tkinter.Scrollbar(self.frame[2])
        self.inputTextScrollBar.pack(side=Tkinter.RIGHT,fill=Tkinter.Y)
        
        #输入消息Text,并与滚动条绑定
        ft = tkFont.Font(family='Fixdsys',size=11)
        self.inputText = Tkinter.Text(self.frame[2],width=70,height=8,font=ft)
        self.inputText['yscrollcommand'] = self.inputTextScrollBar.set
        self.inputText.pack(expand=1,fill=Tkinter.BOTH)
        self.inputTextScrollBar['command'] = self.chatText.yview()
        self.frame[2].pack(expand=1,fill=Tkinter.BOTH)
        
        #发送消息按钮
        self.sendButton=Tkinter.Button(self.frame[3],text=' 发 送 ',width=10,command=self.sendMessage)
        self.sendButton.pack(expand=1,side=Tkinter.BOTTOM and Tkinter.RIGHT,padx=15,pady=8)

        #关闭按钮
        self.closeButton=Tkinter.Button(self.frame[3],text=' 关 闭 ',width=10,command=self.close)
        self.closeButton.pack(expand=1,side=Tkinter.RIGHT,padx=15,pady=8)
        self.frame[3].pack(expand=1,fill=Tkinter.BOTH)
        
    #接收消息
    def receiveMessage(self):
        try:
            #建立Socket连接
            self.clientSock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
            self.clientSock.connect((self.local, self.port))
            self.flag = True
        except:
            self.flag = False
            self.chatText.insert(Tkinter.END,'您还未与服务器端建立连接,请检查服务器端是否已经启动')
            return
            
        self.buffer = 1024
        self.clientSock.send('Y')
        while True:
            try:
                if self.flag == True:
                    #连接建立,接收服务器端消息
                    self.serverMsg = self.clientSock.recv(self.buffer)
                    if self.serverMsg == 'Y':
                        self.chatText.insert(Tkinter.END,'客户端已经与服务器端建立连接......')
                    elif self.serverMsg == 'N':
                        self.chatText.insert(Tkinter.END,'客户端与服务器端建立连接失败......')
                    elif not self.serverMsg:
                        continue
                    else:
                        theTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
                        self.chatText.insert(Tkinter.END, '服务器端 ' + theTime +' 说:\n')
                        self.chatText.insert(Tkinter.END, '  ' + self.serverMsg)
                else:
                    break
            except EOFError, msg:
                raise msg
                self.clientSock.close()
                break
                  
    #发送消息
    def sendMessage(self):
        #得到用户在Text中输入的消息
        message = self.inputText.get('1.0',Tkinter.END)
        #格式化当前的时间
        theTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        self.chatText.insert(Tkinter.END, '客户端器 ' + theTime +' 说:\n')
        self.chatText.insert(Tkinter.END,'  ' + message + '\n')
        if self.flag == True:
            #将消息发送到服务器端
            self.clientSock.send(message);
        else:
            #Socket连接没有建立,提示用户
            self.chatText.insert(Tkinter.END,'您还未与服务器端建立连接,服务器端无法收到您的消息\n')
        #清空用户在Text中输入的消息
        self.inputText.delete(0.0,message.__len__()-1.0)
    
    #关闭消息窗口并退出
    def close(self):
        sys.exit()
    
    #启动线程接收服务器端的消息
    def startNewThread(self):
        #启动一个新线程来接收服务器端的消息
        #thread.start_new_thread(function,args[,kwargs])函数原型,
        #其中function参数是将要调用的线程函数,args是传递给线程函数的参数,它必须是个元组类型,而kwargs是可选的参数
        #receiveMessage函数不需要参数,就传一个空元组
        thread.start_new_thread(self.receiveMessage,())

def main():
    client = ClientUI()
    client.startNewThread()
    client.root.mainloop()
    
if __name__=='__main__':
    main()

 

上面的代码基本上都是有注释的,是容易阅读的,这个程序比较简陋,但记住动手写才是非常重要的。 

另外直接拷贝上面的代码,有可能需要你排版一下格式,因为Python语言都是用缩进来区分语句块的。

 

Python这种语言简单并且功能强大,第三方支持的类库也很丰富,开发起来效率确实很高,据说使用Python web框架Django能用一星期开发出一个网站,感觉真是比较神奇呀。

 

一个Java技术交流群,一起交流,共同进步,扣扣群号:513086638

 

 

 

 

  • 大小: 141.3 KB
20
0
分享到:
评论
10 楼 hnylj 2010-09-01  
MR牛奶快跑 写道
不好意思,我在运行楼主的代码的时候出现问题:显示的登陆消息,发送,关闭等都是乱码哦。请问是在什么地方指定编码(UTF-8)呢?发送也不能发送中文。
我的系统环境是:
os:windows 2003
python2.5.2
没有特定IDE

因为源文件声明为了utf-8,并且也是用utf-8的编码保存的源文件,而windows的本地默认编码是cp936,也就是gbk编码,所以可能出现乱码,你可以试一试
str.decode('UTF-8').encode('GBK'),手动地转一下码试一试
9 楼 MR牛奶快跑 2010-09-01  
不好意思,我在运行楼主的代码的时候出现问题:显示的登陆消息,发送,关闭等都是乱码哦。请问是在什么地方指定编码(UTF-8)呢?发送也不能发送中文。
我的系统环境是:
os:windows 2003
python2.5.2
没有特定IDE
8 楼 MR牛奶快跑 2010-09-01  
感谢楼主的分享,想用Python 实现web service,可是几个月前学了些Python基本的东东,现在还得复习语法~~ 看到楼主的例子很是有憧憬呢。谢谢分享。
7 楼 zxyzxy12321 2010-08-17  
我初学python,不过以上代码基本上都看得懂
6 楼 kdale 2010-08-14  
很喜欢Python的代码风格!
5 楼 hnylj 2010-08-12  
matyhtf 写道
客户端无法发送汉字

我在调试这个程序的时候,未曾出现这个问题,我使用的是Python2.5这个版本,是否与你的环境有关。
4 楼 matyhtf 2010-08-12  
客户端无法发送汉字
3 楼 skyfen 2010-08-11  
楼主,做的不错啊。佩服啊。偶用python两年多啦,主要是用django开发的。
2 楼 TTNecro 2010-08-10  
很不错,我刚开始学Python,还要多多向你学习!!
1 楼 meiykyong 2010-08-09  
好东西,谢谢分享

相关推荐

Global site tag (gtag.js) - Google Analytics