Python网络编程之聊天室

需求

python通过tcp/socket实现多人聊天室

思路

  1. 服务器以多线程方式处理客户端数据
  2. 客户端连接上服务器先把客户端名字发送给服务器(#name#)
  3. 服务器把在线客户端存放在字典中{client_socket:name}
  4. 客户端A给客户端B发送数据格式(B:内容),假如群发的话直接发送(内容)

服务器

  1. 创建socket并设置为端口复用
  2. 绑定ip和port
  3. 设置为被动socket(listen)
  4. 等待客户端到来
  5. 每一个客户端到来创建一个线程收发数据

实现代码

#!/usr/bin/env python3
# coding=utf-8

from socket import *
from threading import Thread

def recv_data(client_socket, client_addr, dict_client):
	while True:
		# 接收到的数据按照utf-8解码
		data = client_socket.recv(1024).decode("utf-8")
		if data:
			if data.startswith("#") and data.endswith("#"):
				name = data[1:len(data)-1]
				print("\"{}\"已上线!".format(name))
				dict_client.setdefault(client_socket, name)
			else:
				name = dict_client[client_socket]
				send_data(dict_client, data, name)
		else:
			# 有客户端断开连接的话将对于的client_socket:name从字典中删除,同时将对应的client_socket关闭
			del_name = dict_client.pop(client_socket)
			print("\"{}\"已下线!".format(del_name))
			break

	client_socket.close()

def send_data(dict_client, source_data, source_name):
	if source_data.startswith("@") and source_data.endswith(";"):
		temp_data = source_data[1:len(source_data)-1]
		print("temp_data={}".format(temp_data))
	
		if ":" in temp_data:
			#单发
			n = temp_data.find(":")
			target_name = temp_data[:n]
			target_data = temp_data[n+1:]
			print("\"{}\" send \"{}\" to \"{}\"".format(source_name, target_data, target_name))
			for client_socket, name in dict_client.items():
				if name == target_name:
					client_socket.send((source_name + ":" + target_data).encode("utf-8"))

		else:
			#群发
			print("\"{}\" send \"{}\" to all".format(source_name, temp_data))
			for client_socket, name in dict_client.items():
				if name != source_name:
					client_socket.send((source_name + ":" + temp_data).encode("utf-8"))

def main():
	# 1、创建socket
	server_socket = socket(AF_INET, SOCK_STREAM)

	# 2、设置端口复用
	server_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, True)

	# 3、绑定端口
	server_socket.bind(("", 8888))

	# 4、设置为被动socket
	server_socket.listen(64)
	print("Listen...")
	
	# 创建一个字典用来保存客户端{client_socket:name}
	dict_client = {}

	try:
		while True:
			# 5、等待客户端连接
			client_socket, client_addr = server_socket.accept()
			#print("新客户:[{},{}]已连接".format(client_addr[0], client_addr[1]))

			# 6、创建一个线程处理客户端的数据
			t1 = Thread(target=recv_data, args=(client_socket, client_addr, dict_client))
			
			# 7、设置线程守护
			t1.setDaemon(True)

			# 8、启动线程
			t1.start()

	finally:
		# 当为所有的客户端服务完成之后再进行关闭,表示不再接收新的客户端的连接
		server_socket.close()
	
if __name__ == "__main__":
	main()

客户端

  1. 创建socket
  2. 连接服务器
  3. 发送用户名给服务器
  4. 创建两个线程用于收发数据

实现代码


from socket import *
from threading import Thread

def recv_data(my_socket):
	while True:
		data = my_socket.recv(1024).decode("utf-8")
		if data:
			n = data.find(":")
			source_name = data[:n]
			source_data = data[n+1:]
			print("\t{}\t{}\n>".format(source_name, source_data), end="")
		else:
			my_socket.close()
			break

def send_data(my_socket,name):
	while True:
		temp_data = input(">")
		data = "@" + temp_data + ";"
		my_socket.send(data.encode("utf-8"))

def main():
	# 设置用户名
	name = input("请输入用户名:")
	# 创建socket
	my_socket = socket(AF_INET, SOCK_STREAM)
	# 连接
	my_socket.connect(("127.0.0.1", 8888))
	# 收发数据
	data = "#" + name + "#"
	my_socket.send(data.encode("utf-8"))
	tr = Thread(target=recv_data, args=(my_socket,))
	ts = Thread(target=send_data, args=(my_socket,name))

	#tr.setDaemon(True)
	#ts.setDaemon(True)

	tr.start()
	ts.start()

if __name__ == "__main__":
	main()

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值