python使用socket实现多人在线聊天

几天前做了个实验,使用python socket 实现多人在线聊天

要求:1.使用socket搭建聊天服务器端,允许多客户端接入

2.使用socket 搭建聊天客户端

3.实现一对一聊天

 

服务器

import socket
import time
import select
import datetime


skt_dict = dict()
now = datetime.datetime.strftime(datetime.datetime.now(),'%Y-%m-%d %H:%M:%S')

class User(object):
	"""docstring for User"""
	def __init__(self, skt, nick_name, addr):
		super(User, self).__init__()
		self.skt = skt
		self.nick_name = nick_name
		self.addr = addr	


	def connect_in(self):
		print("new user::"+self.nick_name+"--"+str(self.addr[0])+":"+str(self.addr[1]))
	def print_name(self):
		print(self.nick_name)


def parse_cmd(cmd_char,user):
	# to parse cmd char
	# distinguish different cmd and react
	if cmd_char.find("online"):
		str_to_send = ""
		for v in skt_dict.values():
			str_to_send += v.nick_name+","
		str_to_send = "users online:" + str_to_send
		user.skt.send(str_to_send.encode("utf-8"))
	if cmd_char.find("room"):
		pass


def parse_talk(data,user):
	# to deal with talk
	# only talk to the people
	# data formation : [0]->None [1]->talkto [2]->msg
	data_list = data.split("/!/")
	for v in skt_dict.values():
		if v.nick_name == data_list[1]:
			msg_to_send = "【Private】"+user.nick_name+"("+now+"):"+data_list[2]
			v.skt.send(msg_to_send.encode("utf-8"))

def main():
	print("server running...")
	tcp_skt = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
	tcp_skt.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
	tcp_skt.bind(("",7789))
	tcp_skt.listen(128)
	# create epoll variable
	epl = select.epoll()
	epl.register(tcp_skt.fileno(),select.EPOLLIN)
	while True:
		epoll_list = epl.poll()
		for fd,event in epoll_list:
			if fd == tcp_skt.fileno():
				# listen socket has someone linked in
				new_skt,client_addr = tcp_skt.accept()
				cli_nick_name = new_skt.recv(1024).decode("utf-8")
				user = User(new_skt,cli_nick_name,client_addr)
				epl.register(new_skt.fileno(),select.EPOLLIN)
				skt_dict[new_skt.fileno()] = user
				user.connect_in()
			elif event == select.EPOLLIN:
				# other socket have msg in
				data = skt_dict[fd].skt.recv(1024).decode("utf-8")
				if data:
					if data.find("~-")!=-1:
						# now data is cmd char
						parse_cmd(data,skt_dict[fd])
						
					elif data.find("~:/!/")!=-1:
						parse_talk(data,skt_dict[fd])

					elif data.find("~?")!=-1:
						new_id = data.split("?")[1]
						skt_dict[fd].nick_name = new_id

					else:
						data_to_send = "【Broadcast】"+skt_dict[fd].nick_name+"("+now+"):"+data
						for v in skt_dict.values():
							if v.nick_name != skt_dict[fd].nick_name:	
								v.skt.send(data_to_send.encode("utf-8"))

				else:
					skt_dict[fd].skt.close()
					print("quit::"+skt_dict[fd].nick_name)
					del skt_dict[fd]


if __name__ == '__main__':
		main()

 

 客户端:

import socket
import time
import threading
import os

def connect_to_server(cli_skt):
	dst_ip = str(input("server ip:"))
	try:
		cli_skt.connect((dst_ip,7789))
	except Exception as e:
		print("something wrong occurs...try again..")
		# print(str(e))
		connect_to_server(cli_skt)
	else:
		nick_name = input("your nick name:")
		cli_skt.send(nick_name.encode("utf-8"))

def get_commend(cli_skt):
	while True:
		print("commend list: -online -chat -exit -brdcst -cgId")
		cmd_char = input("please input commend :")
		if cmd_char == "-exit" :
			print("this program will close in 5 seconds")
			for i in range(5):
				print(str(5-i)+"...")
				time.sleep(1)	
			break
		elif cmd_char == "-online":
			check_online(cli_skt)
			continue
		elif cmd_char == "-brdcst":
			broadcast(cli_skt)
		elif cmd_char == "-cgId":
			new_id = input("your new id:")
			cgid_to_send = "~?"+new_id
			try:
				cli_skt.send(cgid_to_send.encode("utf-8"))
			except Exception as e:
				print(str(e))
			else:
				print("Id has changed")
		elif cmd_char == "-chat":
			talkto = input("who to talk :")
			talk(cli_skt,talkto)
		elif cmd_char == "-room":
			check_room(cli_skt)

		else :
			print("invalid input ,try again")
			continue
def check_room(cli_skt):
	check_room_cmd = "~-room"
	try:
		cli_skt.send(check_room_cmd.encode("utf-8"))
	except Exception as e:
		pass
	try:
		response = cli_skt.recv(1024).decode("utf-8")
	except Exception as e:
		pass
	else:
		print(response)


def check_online(cli_skt):
	# check online users

	check_online_cmd = "~-online"
	# send a check online request
	try:
		cli_skt.send(check_online_cmd.encode("utf-8"))
	except Exception as e:
		pass
	# receive the server response
	try:
		response = cli_skt.recv(1024).decode("utf-8")
	except Exception as e:
		pass
	else:
		print(response)

def talk(cli_skt,talkto):
	# data formation : [0]->~: [1]->talkto [2]->msg
	try:
		while True:
			input_msg = input()
			if input_msg == "exit":
				break
			msg_to_send = "~:/!/"+talkto+"/!/"+input_msg
			cli_skt.send(msg_to_send.encode("utf-8"))
	except Exception as e:
		print("input error")
		print(str(e))

def broadcast(cli_skt):
	while True:
		msg = input()
		if msg == "exit":
			break
		else:
			try:
				cli_skt.send(msg.encode("utf-8"))
			except Exception as e:
				print("broadcast error")
				print(str(e))

def recv_msg(cli_skt):
	print("you are in broadcast channel")
	while True:
		try:
			print("\n---"+cli_skt.recv(1024).decode("utf-8"))
		except Exception as e:
			continue
			# print("no recv")
			# print(str(e))

def main():
	cli_skt = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
	cli_skt.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
	
	connect_to_server(cli_skt)
	cli_skt.setblocking(False)
	t = threading.Thread(target = recv_msg,args = (cli_skt,))
	t.start()
	get_commend(cli_skt)
	os._exit(0)

if __name__ == '__main__':
	main()

 

服务器使用epoll单进程单线程,客户端两线程。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值