后续代码更新和功能添加会提交到个人github主页,有兴趣可以一起来完善!

如果只是拿过去运行看结果,请注意平台相关性以及python版本号,本示例开发运行平台为win7x86_64 pycharm community,python版本号为3.5!!!

TALK IS CHEAP, SHOW YOU MY CODE:

客户端

#coding:utf-8'''file:client.py.pydate:2017/9/11 11:01author:lockeyemail:lockey@123.complatform:win7.x86_64 pycharm python3desc:p2p communication clientside'''from socket import *import threading,sys,json,re#引入json模块主要是为了数据的封装传输,re的话是做一些合法性的验证HOST = '192.168.1.7'PORT=8022BUFSIZE = 1024  ##缓冲区大小  1KADDR = (HOST,PORT)myre = r"^[_a-zA-Z]\w{0,}"tcpCliSock = socket(AF_INET,SOCK_STREAM)#创建一个socket连接userAccount = None#用户登录标志,也用来记录登录的用户名称def register():#用户注册函数    print("""    Glad to have you a member of us!    """)    accout = input('Please input your account: ')    if not re.findall(myre, accout):        print('Account illegal!')        return None    password1  = input('Please input your password: ')    password2 = input('Please confirm your password: ')    if not (password1 and password1 == password2):        print('Password not illegal!')        return None    global userAccount    userAccount = accout    regInfo = [accout,password1,'register']    datastr = json.dumps(regInfo)    tcpCliSock.send(datastr.encode('utf-8'))    data = tcpCliSock.recv(BUFSIZE)    data = data.decode('utf-8')    if data == '0':        print('Success to register!')        return True    elif data == '1':        print('Failed to register, account existed!')        return False    else:        print('Failed for exceptions!')        return Falsedef login():#用户登录函数    print("""    Welcome to login in!    """)    accout = input('Account: ')    if not re.findall(myre, accout):        print('Account illegal!')        return None    password = input('Password: ')    if not password:        print('Password illegal!')        return None    global userAccount    userAccount = accout    loginInfo = [accout, password,'login']    datastr = json.dumps(loginInfo)    tcpCliSock.send(datastr.encode('utf-8'))    data = tcpCliSock.recv(BUFSIZE)    if data == '0':        print('Success to login!')        return True    else:        print('Failed to login in(user not exist or username not match the password)!')        return Falsedef addGroup():#群组添加    groupname = input('Please input group name: ')    if not re.findall(myre, groupname):        print('group name illegal!')        return None    return groupnamedef chat(target):#进入聊天(群聊和点对点聊天可以选择)    while True:        print('{} -> {}: '.format(userAccount,target))        msg = input()        if len(msg) > 0 and not msg in 'qQ':            if 'group' in target:                optype = 'cg'            else:                optype = 'cp'            dataObj = {'type': optype, 'to': target, 'msg': msg, 'froms': userAccount}            datastr = json.dumps(dataObj)            tcpCliSock.send(datastr.encode('utf-8'))            continue        elif msg in 'qQ':            break        else:            print('Send data illegal!')class inputdata(threading.Thread):#用户输入选择然后执行不同的功能程序    def run(self):        menu = """                        (CP): Chat with individual                        (CG): Chat with group member                        (AG): Add a group                        (EG): Enter a group                        (H):  For help menu                        (Q):  Quit the system                        """        print(menu)        while True:            operation = input('Please input your operation("h" for help): ')            if operation in 'cPCPCpcp':            #进入个人聊天                target = input('Who would you like to chat with: ')                chat(target)                continue            if  operation in 'cgCGCgcG':            #进入群聊                target = input('Which group would you like to chat with: ')                chat('group'+target)                continue            if operation in 'agAGAgaG':            #添加群组                groupName = addGroup()                if groupName:                    dataObj = {'type': 'ag', 'groupName': groupName}                    dataObj = json.dumps(dataObj)                    tcpCliSock.send(dataObj.encode('utf-8'))                continue            if operation in 'egEGEgeG':            #入群                groupname = input('Please input group name fro entering: ')                if not re.findall(myre, groupname):                    print('group name illegal!')                    return None                dataObj = {'type': 'eg', 'groupName': 'group'+groupname}                dataObj = json.dumps(dataObj)                tcpCliSock.send(dataObj.encode('utf-8'))                continue            if operation in 'hH':                print(menu)                continue            if operation in 'qQ':                sys.exit(1)            else:                print('No such operation!')class getdata(threading.Thread):#接收数据线程    def run(self):        while True:            data = tcpCliSock.recv(BUFSIZE).decode('utf-8')            if data == '-1':                print('can not connect to target!')                continue            if data == 'ag0':                print('Group added!')                continue            if data == 'eg0':                print('Entered group!')                continue            if data == 'eg1':                print('Failed to enter group!')                continue            dataObj = json.loads(data)            if dataObj['type'] == 'cg':            #群组消息的格式定义                print('{}(from {})-> : {}'.format(dataObj['froms'], dataObj['to'], dataObj['msg']))            else:            #个人消息的格式定义                print('{} ->{} : {}'.format(dataObj['froms'], userAccount, dataObj['msg']))def main():        try:            tcpCliSock.connect(ADDR)            print('Connected with server')            while True:                loginorReg = input('(l)ogin or (r)egister a new account: ')                if loginorReg in 'lL':                    log = login()                    if log:                        break                if loginorReg in 'rR':                    reg = register()                    if reg:                        break            myinputd = inputdata()            mygetdata = getdata()            myinputd.start()            mygetdata.start()            myinputd.join()            mygetdata.join()        except Exception:            print('error')            tcpCliSock.close()            sys.exit()if __name__ == '__main__':    main()

服务端

#coding:utf-8'''file:server.pydate:2017/9/11 14:43author:lockeyemail:lockey@123.complatform:win7.x86_64 pycharm python3desc:p2p communication serverside'''import socketserver,json,timeimport subprocessconnLst = []groupLst = []##  代号 地址和端口 连接对象#optype = {'ag':'group adding','cp':'chat with individual','cg':'chat with group'}class Connector(object):   ##连接对象类    def __init__(self,account,password,addrPort,conObj):        self.account = account        self.password = password        self.addrPort = addrPort        self.conObj = conObjclass Group(object):#群组类    def __init__(self,groupname,groupOwner):        self.groupId = 'group'+str(len(groupLst)+1)        self.groupName = 'group'+groupname        self.groupOwner = groupOwner        self.createTime = time.time()        self.members=[groupOwner]class MyServer(socketserver.BaseRequestHandler):    def handle(self):        print("got connection from",self.client_address)        userIn = False        global connLst        global groupLst        while not userIn:            conn = self.request            data = conn.recv(1024)            if not data:                continue            dataobj = json.loads(data.decode('utf-8'))            #如果连接客户端发送过来的信息格式是一个列表且注册标识为False时进行用户注册或者登陆            ret = '0'            if type(dataobj) == list and not userIn:                account = dataobj[0]                password = dataobj[1]                optype = dataobj[2]                existuser = False                if len(connLst) > 0:                    for obj in connLst:                        if obj.account == account:                            existuser = True                            if obj.password == password:                                userIn = True                                print('{} has logged in system({})'.format(account,self.client_address))                                break                if optype == 'login' and (not userIn or not existuser):                    ret = '1'                    print('{} failed to logged in system({})'.format(account, self.client_address))                else:                    if existuser:                        ret = '1'                        print('{} failed to register({}),account existed!'.format(account, self.client_address))                    else:                        try:                            conObj = Connector(account,password,self.client_address,self.request)                            connLst.append(conObj)                            print('{} has registered to system({})'.format(account,self.client_address))                            userIn = True                        except:                            print('%s failed to register for exception!'%account)                            ret = '99'            conn.sendall(ret.encode('utf-8'))            if ret == '0':                break        while True:        #除登陆注册之外的请求的监听            conn = self.request            data = conn.recv(1024)            if not data:                continue            print(data)            dataobj = data.decode('utf-8')            dataobj = json.loads(dataobj)            if dataobj['type'] == 'ag' and userIn:            #如果判断用户操作请求类型为添加群组则进行以下操作                groupName = dataobj['groupName']                groupObj = Group(groupName,self.request)                groupLst.append(groupObj)                conn.sendall('ag0'.encode('utf-8'))                print('%s added'%groupName)                continue            if dataobj['type'] == 'eg' and userIn:            #入群操作                groupName = dataobj['groupName']                ret = 'eg1'                for group in groupLst:                    if groupName == group.groupName:                        group.members.append(self.request)                        print('{} added into {}'.format(self.client_address,groupName))                        ret = 'eg0'                        break                conn.sendall(ret.encode('utf-8'))                continue            #客户端将数据发给服务器端然后由服务器转发给目标客户端            print('connLst',connLst)            print('grouplst',groupLst)            if len(connLst) > 1:                sendok = False                if dataobj['type'] == 'cg':                #群内广播(除发消息的人)                    print('group',data)                    for obj in groupLst:                        if obj.groupName == dataobj['to']:                            for user in obj.members:                                if user != self.request:                                    user.sendall(data)                else:                #个人信息发送                    for obj in connLst:                        if dataobj['to'] == obj.account:                            obj.conObj.sendall(data)                            sendok = True                    if sendok == False:                        print('no target valid!')            else:                conn.sendall('-1'.encode('utf-8'))                continueif __name__ == '__main__':    server = socketserver.ThreadingTCPServer(('192.168.1.7',8022),MyServer)    print('waiting for connection...')    server.serve_forever()

运行结果示例

服务端(记录着各客户端的操作):

python聊天软件开发 基于python的聊天软件_python聊天软件开发

客户端1:

有注册、建群、群聊、点对点聊天

python聊天软件开发 基于python的聊天软件_群组_02

客户端2:

python聊天软件开发 基于python的聊天软件_python_03

客户端3:

python聊天软件开发 基于python的聊天软件_json_04

要拷贝代码运行的话请注意平台(win7.x86_64)和python版本号(python3.5)!!!