Java复习之知识点整理(十九)--- QQ通信案例(二):服务器部分

37 篇文章 3 订阅
-----------------------------------------------------------------------------------
-------- 三、服务器部分:(test.qq.server) -----------------------
-----------------------------------------------------------------------------------

3.1 服务器主类Main入口类:
---------------------------------------------------------------------------------------
public class ServerMain {

	public static void main(String[] args) {
		
		QQServer ser = new QQServer();
		System.out.println("服务器启动了...");
		ser.startServer();
	}
}


3.2 QQ服务器端:
---------------------------------------------------------------------------------------
/**
 * QQ服务器端 
 */
public class QQServer {

	//好友列表
	public Map<String,Socket> allClientSockets = new HashMap<String,Socket>();
	
	
	/**
	 * 开启服务器
	 */
	public void startServer()
	{
		try 
		{			
			ServerSocket ss = new ServerSocket(8888);
			while(true)
			{
				//有人上线,有新连接
				Socket s = ss.accept();
				//添加到连接列表
				allClientSockets.put(Util.getClientInfo(s),s);				
				//群发好友列表(有人上线,群发一下好友列表,让客户端更新)
				new ClientMsgReceiver(s , this).start();
				broadcastFriendListToAllClient();
			}		
		} 
		catch (Exception e) 
		{
			e.printStackTrace();
		}		
	}



	
	/**
	 * 提取所有客户端用户信息列表
	 */
	public ArrayList<String> getFrinendList()
	{	
		return new ArrayList<String>(allClientSockets.keySet());
	}

	
	/**
	 * 发送消息给所有的客户端
	 */
	public void broadcastMassageToAllClient(byte[] serverToClientMsgBytes) {
		
		Collection<Socket> ss =  allClientSockets.values();
		for (Socket socket : ss) {
			try {
				OutputStream os =  socket.getOutputStream();
				os.write(serverToClientMsgBytes);
				os.flush();
				
			} catch (IOException e) {
				e.printStackTrace();
			}
		}		
	}
	
	
	/**
	 * 群发好友列表
	 */
	public void broadcastFriendListToAllClient()
	{
		byte [] bs = MessageFactory.popServerFriends(getFrinendList());
		broadcastMassageToAllClient(bs);
	}



	/**
	 * 在好友列表中删除掉线的客户端
	 */
	public void removeFriend(String clientInfo) {
		
		if(allClientSockets.containsKey(clientInfo))
		{
			allClientSockets.remove(clientInfo);
		}
		
	}	
}


3.3 与每个链接的客户端进行通信的类
---------------------------------------------------------------------------------------
/**
 * 服务器开辟的线程,用来与单个客户端进行通信
 * 每有一个客户端连接服务器,就会产生这样一个和客户端进行连接通信的线程
 * 有多少客户端就有多少这个线程
 * 保证了客户端可以和所有的线程进行通信
 */
public class ClientMsgReceiver extends Thread
{
	//与客户端进行通信的socket
	private Socket clientSocket;
	//与客户端进行通信的输入流(客户端输入进来的)
	private InputStream is;
	//与客户端进行通信的输出流(输出信息到客户端)
	private OutputStream os;
	//唯一的服务器本身
	private QQServer qqServer;
	//本线程连接的客户端信息
	private String clientInfo;
	
	
	
	
	public ClientMsgReceiver(Socket s , QQServer ser) {
		try {
			this.clientSocket = s;
			this.qqServer = ser;
			this.is = clientSocket.getInputStream();
			this.os = clientSocket.getOutputStream();
			this.clientInfo = Util.getClientInfo(clientSocket);
			
		} catch (Exception e) {			
			e.printStackTrace();
		}
		
	}

	public void run(){
		
		try {
			//与客户端进行通讯
			while(true)
			{
				//解析流
				Message msg = MessageFactory.parseMessageFromInputStream(is);				
				//客户端请求刷新好友列表
				if(msg.getClass() == ClientReflashFriendsListMessage.class)
				{
					//TODO 获取好友列表,并发送给所有客户端()			
					os.write(MessageFactory.popServerFriends(qqServer.getFrinendList()));
					os.flush();				
				}				
				//如果是客户端发来的聊天信息--群聊
				else if(msg.getClass() == ClientSendChatMessage.class)
				{
					//客户端聊天信息
					ClientSendChatMessage msg1 = (ClientSendChatMessage)msg;
					byte [] chat = msg1.getMessageContent();
					//服务器进行组装(添加用户信息。然后转发所有人),得到byte[]
					byte [] serverToClientMsgBytes = MessageFactory.popServerChatMessage(clientInfo, chat);
					//群发给所有客户端
					qqServer.broadcastMassageToAllClient(serverToClientMsgBytes);				
				}
				//如果是客户端发来的聊天信息--私聊
				else if(msg.getClass() == ClientSendChatMessageSingle.class)
				{
					//客户端聊天信息
					ClientSendChatMessageSingle msg1 = (ClientSendChatMessageSingle)msg;
					ChatSingleBean chat = msg1.getMessageContent();
					String reveInfo = chat.getReceiver();
					
					//组装消息
					byte [] serverToClientMsgBytes = MessageFactory.popServerChatMessageSingle(clientInfo, chat.getChat());
					//获取发送方的socket
					Socket sock = qqServer.allClientSockets.get(reveInfo);
					OutputStream out = sock.getOutputStream();
					out.write(serverToClientMsgBytes);
					out.flush();		
				}
			}
		
		}
		catch(Exception e)
		{
			//客户端掉线了,要删除
			qqServer.removeFriend(clientInfo);		
			qqServer.broadcastFriendListToAllClient();
			//e.printStackTrace();
		}	
	}	
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值