Socket-3 客户端之间的群聊和私聊

Socket-3 续
        实现客户端之间的群聊和私聊.

客户端 Client3:
创建一个客户端:
      1:向服务器发送数据
      2:接受服务器发送的数据

package v34;
 
	public class Client {
		/*属性:socket*/
		private Socket socket;
		public Client(){
			try {
				socket = new Socket("localhost",8088);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		public void start(){//获取服务端发送来的数据
			try {
				/*创建线程对象,获取服务端发送来的数据*/
				Thread t = new GetServerInfoHandler(socket);
				t.start();
				 
			 连接后:通信已经建立,通过Socket对象获取输出流进行信息传递
 
				OutputStream os = socket.getOutputStream();
				PrintWriter pw = 
					new PrintWriter(
							new OutputStreamWriter(os,"utf-8"),true);
				Scanner sc = new Scanner(System.in);
				System.out.println("请注册昵称:");
				String nickName = sc.next();
				pw.println(nickName);
				System.out.println("欢迎进入聊天室:");
				while(true){
					String input = sc.next();
					pw.println(nickName+":"+input);
					pw.flush();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}finally{
				try {
					System.out.println("您已经下线");
					socket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	//定义一个内部类对象--线程,就是处理客户端接收服务端发送来的数据

		class GetServerInfoHandler extends Thread{
			private Socket socket;
			public GetServerInfoHandler(Socket socket){
				this.socket = socket;
			}
			public void run(){
				try {
		  //通过socket对象获取输入流,接受服务端发送的数据 
					InputStream is = socket.getInputStream();
					BufferedReader br = 
						new BufferedReader(
							new InputStreamReader(is,"utf-8"));
					String line = "";
					while((line=br.readLine())!=null){
						System.out.println(line);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		public static void main(String[] args) {
			Client c = new Client();
			c.start();
		}
	}

服务端Server3
     完成任务:
              1:接受客户端发送的数据
              2:   将数据返回给客户端

package v34;
  
public class Server {
	 
	private ServerSocket server;
	/**属性:allOut*/
	//使用Map存服务端所获取的客户端的输出流
     //    key-value   key:nickname   value:pw
private Map<String,PrintWriter> allOut;public Server(){try { server = new ServerSocket(8088); allOut = new HashMap<String,PrintWriter>();} catch (Exception e) {e.printStackTrace();}} // 发送信息给所有的客户端: // public void sendMessage(String message){// for(PrintWriter pw:allOut){// pw.println(message);// pw.flush();// }// }/**群聊:遍历map*/public void sendMessage(String message){Set<String> keys = allOut.keySet();for(String key:keys){PrintWriter pw = allOut.get(key);//得到每个输出流pw.println(message);//每个流都发送同样的消息pw.flush();}}/**私聊:*/public void sendToOne(String message,String nickName){if(nickName!=null&&nickName.length()>0){if(allOut.containsKey(nickName)){PrintWriter pw = allOut.get(nickName);pw.println(message);pw.flush();}else{sendMessage(message);}}}/** * 保存所有的向客户端发送数据的输出流对象 * @param pw:向客户端发送数据的输出流对象。 */// public void savePW(PrintWriter pw){// if(pw!=null){// allOut.add(pw);// }// }/** * 将服务端获取的客户端的输出流进行保存 */public void savePW(String nickName,PrintWriter pw){if(nickName!=null&&nickName.length()>0){allOut.put(nickName, pw);}}// public void deletePW(PrintWriter pw){// if(pw!=null){// allOut.remove(pw);// }// }/** * 客户端下线,删除Map中的key-value。 */public void deletePW(String nickName){if(nickName!=null&&nickName.length()>0){allOut.remove(nickName);}}public void start(){try {/*循环接受多个客户端的请求连接*/while(true){System.out.println("--等待连接--");/* * 通过accept()获取客户端的连接请求 * 此方法有阻塞效果。当没有发现连接请求时 * 会一直阻塞在这里。不会执行后续的程序。 */Socket socket = server.accept();/* * 获取客户端的信息 */int port = socket.getPort();InetAddress add = socket.getInetAddress();String name = add.getHostName();System.out.println("客户端:"+name+",端口号:"+port+"已经连接上服务器");Thread t = new GetClientInfoHandler(socket);t.start();}} catch (Exception e) {e.printStackTrace();}}/** * 定义一个内部类--线程。 * 处理每一个客户端的信息。 * 接受客户端的信息和发送会给客户端 * 需要流,socket提供的。 */class GetClientInfoHandler extends Thread{private Socket socket;public GetClientInfoHandler(Socket socket){this.socket = socket;}public void run(){PrintWriter pw = null;String nickName = "";try {/*通过socket对象获取输入流, * 处理客户端发送过来的数据 * */InputStream is = socket.getInputStream();BufferedReader br = new BufferedReader(new InputStreamReader(is,"utf-8"));/* * 通过Socket对象获取输出流 * 作用是将收到的数据写回给客户端 */OutputStream os = socket.getOutputStream();pw = new PrintWriter(new OutputStreamWriter(os,"utf-8"),true);/* * 将向此客户端发送信息的输出流,保存在服务器 */nickName = br.readLine();savePW(nickName,pw);System.out.println("在线人数:"+allOut.size());String line = "";/*将从客户端读取的数据,发回给客户端 * 是一个循环操作 * */while((line=br.readLine())!=null){/*分析line是否是私聊部分*/if(line.contains("@")&&line.contains("#")){//进行截取int start = line.indexOf("@");int end = line.indexOf("#");String nick=line.substring(start+1, end);sendToOne(line.substring(end+1),nick);}else{sendMessage(line);}}} catch (Exception e) {e.printStackTrace();}finally{deletePW(nickName);sendMessage(nickName+"已经下线了");System.out.println("当前在线人数:"+allOut.size());try {socket.close();} catch (IOException e) {e.printStackTrace();}}}}public static void main(String[] args) {Server server = new Server();server.start();}}













        

猜你喜欢

转载自blog.csdn.net/xiaozelulu/article/details/80273190