python 实现一个私人定制聊天室 贼溜

效果:

客户端打开后,自动发现服务器,服务器将多个客户端建立到一起成为一个聊天室,每个客户端都可以发言,每个人的发言都由服务器公告到聊天室中。

python 实现一个私人定制聊天室 贼溜_第1张图片

客户端代码:

main.py

# coding=utf-8
import socket
import subprocess
import threading
import time
import lib
import json
from base.config import config
import sys
from urllib.parse import unquote

client=None
message_pos=0
def display_message(message):
    for msg in message:
        print("%s, %s_%s_%s say: %s" % (msg["cdate"],str(msg["hostname"]).upper(),str(msg["username"]).upper(),msg["ip"],msg["msg"]))
def init_conn(host,port):
    global message_pos
    print("connect to %s:%s" % (host,port))
    client = socket.socket()
    client.settimeout(200)
    try:
        client.connect((host,port))
        hostname,username=lib.env()
        body={"hostname":hostname,"username":username}
        body=json.dumps(body)
        body="register_client_info:::" + body
        client.send(body.encode("utf8"))
        print("connected")
        ack = client.recv(50000)
        ack = ack.decode("utf8")
        message=json.loads(ack)
        display_message(message)
        if message:
            message_pos=message[-1]["pos"]
        return client
    except Exception as e:
        print("connect with error - %s" % e)
        client.close()
        return False

def heart_beat():
    global client,message_pos
    while 1:
        try:
            body="message_position:::%d" % message_pos
            client.send(body.encode())
            ack = client.recv(50000)
            ack = ack.decode("utf8")
            if ack == "bye":
                client.close()
                break
            message = json.loads(ack)
            display_message(message)
            if message:
                message_pos = message[-1]["pos"]
        except:
            # client.close()
            client=init_conn(config["host"], config["port"])
        time.sleep(2)
if __name__=="__main__":
    if len(sys.argv)==3:
        config["host"] = sys.argv[1]
        config["port"] = int(sys.argv[2])
    else:
        print("请提供合法的参数  ")
        sys.exit(0)
    client = init_conn(config["host"], config["port"])
    thread_hb = threading.Thread(target=heart_beat)
    thread_hb.start()
    while 1:
        line=input()
        line="client_say:::"+line
        client.send(line.encode("utf8"))


lib.py

# coding=utf-8
import time
import urllib.request
import socket
import string
from urllib.parse import unquote,quote
from base.config import config
import platform
import os

def env():
    hostname = socket.gethostname()
    username = os.getenv("USERNAME")
    return hostname,username

服务器:

import socket
import subprocess
import sys
import threading
import time
import json
import log.log as log
import lib

def handle_message(client,msg):
    client.send(msg.encode("utf8"))
def heart_beat(client,addr):
    hostname=ip=username=""
    log.info("connected from : %s" % ':'.join('%s' % s for s in addr))
    while 1:
        data = client.recv(50000)
        msg = data.decode("utf8")
        if msg:
            if ":::" in msg:
                msgs=str(msg).split(":::")
                cmd=msgs[0]
                arg=msgs[1]
                if cmd=="register_client_info":
                    hostname,ip,username=lib.register_client(addr[0],msgs[1])
                    if not hostname:
                        client.close()
                        break
                    message = lib.msgs()
                    client.send(json.dumps(message).encode('utf8'))
                if cmd=="message_position":
                    message=lib.msgs(int(arg))
                    client.send(json.dumps(message).encode('utf8'))
                if cmd=="client_say":
                    lib.say(hostname,ip,username,arg)
                    # client.send(json.dumps({"code":1,"message":"success"}).encode('utf8'))
            elif msg=="bye":
                log.info('client say bye')
                client.close()
            else:
                log.info("client: %s" % msg)

server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# server.settimeout(10)
host="0.0.0.0"
port=8888
server.bind((host,port))
server.listen(1)
log.info("server lisen on "+str(port))

while True:
    try:
        client, addr = server.accept()
        thread=threading.Thread(target=heart_beat,args=(client,addr))
        thread.start()
    except:
        continue

lib.py

import json
import time
import os
import log.log as log
from base.config import config

agents=[]
message=[]

def register_client(ra,body):
    global agents
    try:
        body = json.loads(body)
        if "hostname" in body.keys() and "username" in body.keys():
            log.info("client register info : %s - %s - %s" % (body["hostname"], ra, body["username"]))
            agent=get_agent(body["hostname"], ra, body["username"])
            if agent:
                return agent["hostname"],agent["ip"],agent["username"]
            else:
                agents.append({"hostname":body["hostname"],"ip":ra,"username":body["username"]})
                return body["hostname"], ra, body["username"]
        else:
            return False,False,False
    except:
        return False, False,False
def say(hostname,ip,username,msg):
    global message
    message.append({"hostname":hostname,"ip":ip,"username":username,"msg":msg,"cdate":time.strftime("%Y-%m-%dT%H:%M:%S",time.localtime()),"pos":len(message)+1})
def msgs(position=None):
    global message
    if position:
        return message[position:]
    else:
        return message[-5:]
def get_agent(hostname,ip,username):
    global agents
    for agent in agents:
        if agent["hostname"]==hostname and agent["ip"]==ip and agent["username"]==username:
            return agent
    return False

你可能感兴趣的:(python,Linux,网络,服务器,python,tcp/ip,网络)