本文基于Python socket完成聊天室的开发。聊天室具有注册、登录、获取好友列表、选择具体的好友私聊等功能。
服务器端和客户端使用json格式的报文进行通信,协议采用自定义协议,以下是具体的代码:
服务器端
#接收连接和请求
def start_server(host, port):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((host, port))
server.listen(10)
inputs = [server]
while inputs:
readable, writable, exceptional = select.select(inputs, outputs, inputs)
# 可读
for s in readable:
if s is server: # 有连接进入
connection, client_address = s.accept()
inputs.append(connection)
else:
try:
data = s.recv(1024)
if data:
pack = json.loads(data.decode())
handle_request(pack, s)
else:
inputs.remove(s)
s.close()
except Exception as e:
print(e)
inputs.remove(s)
s.close()
# 异常
for s in exceptional:
inputs.remove(s)
s.close()
def handle_request(pack, s):
resp = None
if pack.get('type') == 'register':
resp = register(pack, s)
if pack.get('type') == 'login':
resp = login(pack, s)
if pack.get('type') == 'get_friend':
resp = get_friend(pack, s)
if pack.get('type') == 'send_msg':
resp = send_msg(pack, s)
if resp:
print(resp)
s.sendall(json.dumps(resp).encode())
# 转发信息
def send_msg(pack, s):
send = pack.get('send')
to = pack.get('to')
user = user_dict.get(to)
if not user:
return {'flag': False, 'msg': '用户不存在'}
if not user.get('online'):
return {'flag': False, 'msg': '用户不在线'}
to_s = user.get('s')
if to_s:
to_s.send(json.dumps({
'send': send,
'msg': pack.get('msg'),
}).encode())
fri = friend_dict.get(send, set())
fri.add(to)
friend_dict[send] = fri
fri = friend_dict.get(to, set())
fri.add(send)
friend_dict[send] = fri
return {'flag': True, 'msg': '发送成功'}
return {'flag': False, 'msg': '发送失败'}
if __name__ == '__main__':
# 从文件中加载用户信息
load_user_info()
tr = threading.Thread(target=start_server, args=("0.0.0.0", 8880), daemon=True)
tr.start()
while True:
print('1.查看好友列表')
print('2.查看用户信息')
print('3.修改用户信息')
n = int(input())
if n == 1:
show_friend()
elif n == 2:
show_info()
elif n == 3:
update_info()
客户端代码
# 获取好友
def get_friend():
if not user_no:
print('请先登录')
return
req = {
'type': 'get_friend',
'user_no': user_no,
}
s.send(json.dumps(req).encode())
# 子线程接收消息
def recv(s):
# 查看服务器是否返回同意报文
while True:
recv_data = s.recv(1024)
print(json.loads(recv_data.decode()))
def send():
while True:
print('1.注册')
print('2.登录')
print('3.好友列表')
print('4.选择好友私聊')
n = int(input())
if n == 1:
register()
elif n == 2:
login()
elif n == 3:
get_friend()
elif n == 4:
send_msg()
if __name__ == "__main__":
addr = '192.168.10.10'
port = 8880
s = socket.socket()
s.connect((addr, port))
# 接收进程
tr = threading.Thread(target=recv, args=(s,), daemon=True)
tr.start()
send()