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

5 篇文章 0 订阅

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();
		}
	}
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();
}
}


 

 

 

 

 

 

 

 

 

 

 

 

        

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值