效果:
客户端打开后,自动发现服务器,服务器将多个客户端建立到一起成为一个聊天室,每个客户端都可以发言,每个人的发言都由服务器公告到聊天室中。
客户端代码:
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("请提供合法的参数 <server> <port>")
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