一起来做一个基于python的tcp聊天室吧

基于python的tcp聊天室的实现

1.目标和思路

2.客户端代码

3.服务器代码

4.运行结果

1.目标和思路

1.功能和目标: 类似群聊天

    [1]有人进入聊天室需要输入姓名,姓名不能重复

    [2] 有人进入聊天室时,其他人会收到通知:

        *** 进入聊天室

    [3] 一个人发消息,其他人会收到:

        ××× :××××××××

    [4] 有人退出聊天室,则其他人会收到通知:

        ××× 退出聊天室

2.确定技术模型

    [1] 使用字典保存用户信息 {姓名:客户端套接字}

    [2] 套接字选择: tcp套接字

    [3] 转换模型 : 客户端-->>服务端-->>所有客户端

    [4] 收发关系处理: 一个客户端发送消息给服务端,服务端再转发给其他客户端

                    客户端使用多进程来分别处理收发消息

                    服务端使用多线程来管理客户端

3.具体实现流程

    [1] 搭建网络连接

    [2] 实现登录

            客户端: × 输入姓名

                    × 将姓名发送给服务端

                    × 接收服务端反馈

                    × 如果不允许进入则重新输入,允许则进入聊天室

                    × 创建新的进程用于收发消息

            服务端:  * 创建新的线程用于管理客户端的连接

                    × 接收姓名

                    ×  判断姓名是否存在

                    ×  将结果反馈给客户端

                    × 不允许 登录结束,允许登录则将用户信息插入数据机构保存

                    × 将登录信息通知其他人

    [3] 聊天

            客户端: × 循环发送消息

                                × 循环接收消息

            服务器: × 接收消息,判断请求类型

                    × 将消息转发给其他用户

    [4] 退出

            客户端: ×输入quit进行退出

                    × 发送进程关闭,接收进程关闭

            服务器: × 退出信息发送给其他人

                    × 将其信息从服务器清除

2.客户端代码

import os,sys,signal

from socket import *

server_addr = (('127.0.0.1',9696))

def msg_recv(sockfd):      ##接收消息

    while True:

        data = sockfd.recv(1024)

        if data.decode() == 'q':

            break

        print(data.decode())

def msg_send(sockfd,name):      ##发送消息

    while True:

        try:

            data = input("发言>>")

        except KeyboardInterrupt:

            data = 'quit'

        if data == 'quit':  ##退出

            msg = 'Q %s'%name

            sockfd.send(msg.encode())

            break

        else:

            msg = 'C %s %s'%(data,name)

            sockfd.send(msg.encode())

def main():

    sockfd = socket()##创建套接字

    try:

        sockfd.connect(server_addr)

    except Exception:

        print("连接失败")

        sockfd.close()

        return

    while True:            ####输入姓名登录

        name = input("请输入昵称:")

        sockfd.send(('L '+name).encode())  ## L 区分消息类型

        data = sockfd.recv(128)

        if data.decode() == 'OK':

            print("你已经进入9696聊天室")

            break

        else:

            print(data.decode())

    signal.signal(signal.SIGCHLD,signal.SIG_IGN)

    pid = os.fork()

    if pid < 0:

        sys.exit("err") 

    elif pid == 0:        ##子进程

        msg_recv(sockfd)

    else:

        msg_send(sockfd,name)

    sys.exit("退出")

if __name__ == "__main__":

    main()

3.服务器代码

from threading import Thread

from socket import *

import os,sys

Host = '0.0.0.0'

Post = 9696

address = (Host,Post)

chat_name = {}  ## name:conn

jobs = {}  ###conn:t  存储线程对象t   

#conn_stat = {}  ###  conn:'true'  存储套接字的状态 true为运行  false 为结束线程

def do_login(conn,name):        ##登录

    if name not in chat_name:

        conn.send(b'OK')

    else:

        conn.send("昵称已经存在".encode())

        return

    msg = "%s 进入9696聊天室" %name

    for c in chat_name:

        chat_name[c].send(msg.encode())

    chat_name[name] = conn

def do_chat(conn,msg,name):

    text = "%s :%s"%(name,msg)

    for n in chat_name:

        if n != name:

            chat_name[n].send(text.encode())

def do_quit(conn,name):

    msg = "%s 退出9696聊天室了"%name

    for c in chat_name:

        if c == name:

            conn.send(b'q')

        else:

            chat_name[c].send(msg.encode())

    del chat_name[name]

    #conn_stat[conn] = 'false'

    conn.close()

def do_request(conn):  ##用来处理客户端的请求

    while True:

        data = conn.recv(1024).decode().strip().split(' ')

        if data[0] == 'L':  ##登录

            name = data[-1]

            do_login(conn,name)

        elif data[0] == 'C':    ##聊天

            name = data[-1]

            msg = ''.join(data[1:-1])

            do_chat(conn,msg,name)

        elif data[0] == 'Q':  ##退出

            name = data[-1]

            do_quit(conn,name)

            break


def main():

    sockfd = socket()  ##tcp套接字

    sockfd.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)    ##端口重用

    sockfd.bind(address)

    sockfd.listen(5)

    while True:

        try:

            conn,addr = sockfd.accept()

        except KeyboardInterrupt:

            sockfd.close()

            sys.exit("退出")

        except Exception as e:

            print(e)

            continue

        print("Connect from:",addr)

        t = Thread(target=do_request,args=(conn,))

        t.start()

        jobs[conn] = t

        #conn_stat[conn] = 'true'

        ###回收线程  当有线程结束,只有当新的客户端连接进来才会回收结束的线程

        for c in jobs:

            if c._closed is True:

                jobs[c].join()

if __name__ == '__main__':

    main()

4.运行结果

1.运行客户端和服务器

2.输入姓名

3.发送消息

4.退出客户端

运行中收到的消息会显示在“发言>>”之后,可以在其后加上“\r”让光标回到行首,效果会好一点。。。。。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容