python实现聊天室功能

快过年了,我这颗躁动的心啊,根本集中不了精神来详细整理博客了,所以干脆直接贴上代码来,等年后我会详细介绍每一步实现方法。给代码加上详细注释的,大家见谅啊~~~

聊天室程序需求:

我们要实现的是简单的聊天室的例子,就是允许多个人同时一起聊天,每个人发送的消息所有人都能接收到,类似于 QQ 群的功能,而不是点对点的 QQ 好友之间的聊天。如下图:

python实现聊天室功能_第1张图片

这里我们首先要知道《python网络编程》知识,其中要明白什么是Socket以及如何使用Socket 实现不同主机间的通信。具体内容大家可以参考Python Socket网络编程

OK,我这里直接上TCP版本的server.py和client.py文件
运行时分别运行server.py和client.py文件即可,或者在编译器上直接运行,效果图在文章末尾。

server.py

# -*- encoding:utf-8 -*-
# socket.getaddrinfo(host,  port, family=0, socktype=0, proto=0, flags=0)
# 根据给定的参数host/port,相应的转换成一个包含用于创建socket对象的五元组,
# 参数host为域名,以字符串形式给出代表一个IPV4/IPV6地址或者None.
# 参数port如果字符串形式就代表一个服务名,比如“http”"ftp""email"等,或者为数字,或者为None
# 参数family为地主族,可以为AF_INET  ,AF_INET6 ,AF_UNIX.
# 参数socktype可以为SOCK_STREAM(TCP)或者SOCK_DGRAM(UDP)
# 参数proto通常为0可以直接忽略
# 参数flags为AI_*的组合,比如AI_NUMERICHOST,它会影响函数的返回值
# 附注:给参数host,port传递None时建立在C基础,通过传递NULL。
# 该函数返回一个五元组(family, socktype, proto, canonname, sockaddr),同时第五个参数sockaddr也是一个二元组(address, port)
# 更多的方法及链接请访问
# Echo server program

#socket - tcp - server.py(服务端):
from socket import *
import sys
import threading
from time import ctime
from time import localtime
import traceback
import time
import subprocess

reload(sys)
sys.setdefaultencoding("utf8")

HOST = '127.0.0.1'
PORT = 8555  # 设置侦听端口
BUFSIZ = 1024


class TcpServer():
    def __init__(self):
        self.ADDR = (HOST, PORT)
        try:
            self.sock = socket(AF_INET, SOCK_STREAM)
            print '%d is open' % PORT

            self.sock.bind(self.ADDR)
            self.sock.listen(5)
            # 设置退出条件
            self.STOP_CHAT = False

            # 所有监听的客户端
            self.clients = {}
            self.thrs = {}
            self.stops = []

        except Exception, e:
            print "%d is down" % PORT
            return False

    def IsOpen(ip, port):

        s = socket(AF_INET, SOCK_STREAM)
        try:
            s.connect((ip, int(port)))
            # s.shutdown(2)
            # 利用shutdown()函数使socket双向数据传输变为单向数据传输。shutdown()需要一个单独的参数,
            # 该参数表示s了如何关闭socket。具体为:0表示禁止将来读;1表示禁止将来写;2表示禁止将来读和写。
            print '%d is open' % port
            return True
        except:
            print '%d is down' % port
            return False

    def listen_client(self):
        while not self.STOP_CHAT:
            print(u'等待接入,侦听端口:%d' % (PORT))
            self.tcpClientSock, self.addr = self.sock.accept()
            print(u'接受连接,客户端地址:', self.addr)
            address = self.addr
            # 将建立的client socket链接放到列表self.clients中
            self.clients[address] = self.tcpClientSock
            # 分别将每个建立的链接放入进程中,接收且分发消息
            self.thrs[address] = threading.Thread(target=self.readmsg, args=[address])
            self.thrs[address].start()
            time.sleep(0.5)

    def readmsg(self, address):
        # 如果地址不存在,则返回False
        if address not in self.clients:
            return False
        # 得到发送消息的client socket
        client = self.clients[address]
        while True:
            try:
                # 获取到消息内容data
                data = client.recv(BUFSIZ)
            except:
                print error
                self.close_client(address)
                break
            if not data:
                break
            # python3使用bytes,所以要进行编码
            # s='%s发送给我的信息是:[%s] %s' %(addr[0],ctime(), data.decode('utf8'))
            # 对日期进行一下格式化
            ISOTIMEFORMAT = '%Y-%m-%d %X'
            stime = time.strftime(ISOTIMEFORMAT, localtime())
            s = u'%s发送给我的信息是:%s' % (str(address), data.decode('utf8'))
            # 将获得的消息分发给链接中的client socket
            for k in self.clients:
                self.clients[k].send(s.encode('utf8'))
                self.clients[k].sendall('sendall:' + s.encode('utf8'))
                print str(k)
            print [stime], ':', data.decode('utf8')
            # 如果输入quit(忽略大小写),则程序退出
            STOP_CHAT = (data.decode('utf8').upper() == "QUIT")
            if STOP_CHAT:
                print "quit"
                self.close_client(address)
                print "already quit"
                break

    def close_client(self, address):
        try:
            client = self.clients.pop(address)
            self.stops.append(address)
            client.close()
            for k in self.clients:
                self.clients[k].send(str(address) + u"已经离开了")
        except:
            pass
        print str(address) + u'已经退出'


if __name__ == '__main__':
    tserver = TcpServer()
    tserver.listen_client()

client.py

# -*- encoding:utf-8 -*-
from socket import *
import sys
import threading
import time
#socket - tcp - client.py (客户端):
reload(sys)
sys.setdefaultencoding("utf8")

# 测试,连接本机
HOST = '127.0.0.1'
# 设置侦听端口
PORT = 8555
BUFSIZ = 1024


class TcpClient:
    ADDR = (HOST, PORT)

    def __init__(self):
        self.HOST = HOST
        self.PORT = PORT
        self.BUFSIZ = BUFSIZ
        # 创建socket连接
        self.client = socket(AF_INET, SOCK_STREAM)
        self.client.connect(self.ADDR)
        # 起一个线程,监听接收的信息
        self.trecv = threading.Thread(target=self.recvmsg)
        self.trecv.start()

    def sendmsg(self):
        # 循环发送聊天消息,如果socket连接存在则一直循环,发送quit时关闭链接
        while self.client.connect_ex(self.ADDR):
            data = raw_input('>:')
            if not data:
                break
            self.client.send(data.encode('utf8'))
            print(u'发送信息到%s:%s' % (self.HOST, data))
            if data.upper() == "QUIT":
                self.client.close()
                print u"已关闭"
                break

    def recvmsg(self):
        # 接收消息,如果链接一直存在,则持续监听接收消息
        try:
            while self.client.connect_ex(self.ADDR):
                data = self.client.recv(self.BUFSIZ)
                print(u'从%s收到信息:%s' % (self.HOST, data.decode('utf8')))
        except Exception, e:
            print str(e)


if __name__ == '__main__':
    client = TcpClient()
    client.sendmsg()

结果展示:
我运行了两次client.py文件,表示我有两个用户进行通信,服务器会接收到两个用户发送的消息。

server.py

python实现聊天室功能_第2张图片

client.py

第一个用户首先与服务器连接

python实现聊天室功能_第3张图片

第二个用户也进来了,现在两个用户之间可以相互发送消息了

python实现聊天室功能_第4张图片

你可能感兴趣的:(爬虫实战,Python,python,网络编程,python实现qq,python实现聊天室,python-socket)