网络编程之 使用Socket创建聊天室增强版加入私聊系统消息

21 篇文章 0 订阅
17 篇文章 0 订阅

上一篇写了使用 socket 实现群聊的功能,但是有点缺陷比如说说话的时候没有显示是谁说的,没有私聊,之类的

其实加个 客户端说话的时候是谁说的很简单,无非就是 获取当前客户端的用户名,私聊的话就是 发送给其他客户端的时候再进行限制一下,发给我指定的,比如说 @zzq:lcm 就是我对zzq说 lcm,约定 以 @ 开头,:结尾的中间的就是我们at的人。

所以这里我们在new 客户端的时候就应该给客户端加个用户名了,然后 初始化的时候输入用户名,发送消息线程 实例化的时候给服务端发送该客户端的用户名

改动后的代码:

客户端 ClientSend 类:

/**
 * 发送数据线程
 * @author snow
 *
 */
public class ClientSend implements Runnable {
	
	private BufferedInputStream bis;
	private BufferedOutputStream bos;
	private Socket client;
	private boolean isRuning = true ;
	private String name;
	
	/**
	 * 构造器初始化
	 * @param client 客户端
	 * @param name 聊天室的用户名
	 */
	public ClientSend(Socket client,String name) {
		this.bis = new BufferedInputStream( System.in );
		this.client = client;
		try {
			this.bos = new BufferedOutputStream( this.client.getOutputStream() );
			// 初始化完成后给服务端发送用户名
			this.name = name;
			this.send(name);
		} catch (IOException e) {
			e.printStackTrace();
			isRuning = false;
			CloseUtil.closeAll(bos,bis,client);
		}
	}
	
	/**
	 * 获取控制台输入的数据
	 * @return
	 */
	private String getMsg() {
		byte [] data = new byte[1024];
		int len = 0;
		try {
			len = bis.read(data);
		} catch (IOException e) {
			e.printStackTrace();
			isRuning = false;
			CloseUtil.closeAll(bos,bis,client);
		}
		return new String(data , 0 ,len);
	}
	
	/**
	 * 发送消息
	 */
	public void send(String msg) {
		try {
			this.bos.write(msg.getBytes());
			this.bos.flush();
		} catch (IOException e) {
			e.printStackTrace();
			isRuning = false;
			CloseUtil.closeAll(bos,bis,client);
		}
	}
	
	@Override
	public void run() {
		while(isRuning) {
			String msg = getMsg();
			send(msg);
		}
	}

}

MyClient类:

    public static void main(String[] args) throws UnknownHostException, IOException {
		Socket client = new Socket("127.0.0.1", 9999);
		System.out.println("请输入您的用户名:");
		String name = new BufferedReader( new InputStreamReader(System.in) ).readLine();
		// 发送消息
		new Thread(new ClientSend(client,name)).start();
		// 接收消息
		new Thread(new ClientReceive(client)).start();
	}

服务端  Server类 :

/**
 * 服务端的 server
 * @author snow
 *
 */
public class Server implements Runnable {
	
	private BufferedInputStream bis ;
	private BufferedOutputStream bos;
	private Socket server;
	private boolean isRuning = true;
	private ArrayList<Server> clients;
	private String clientName;
	
	public Server(Socket server,ArrayList<Server> clients) {
		try {
			this.bis = new BufferedInputStream( server.getInputStream() );
			this.bos = new BufferedOutputStream( server.getOutputStream() );
			this.server = server;
			this.clients = clients;
			
			// 获取客户端用户名
			this.clientName = this.receviceMsg();
			// 给当前客户端发送欢迎消息
			this.sendMsg("欢迎来到聊天室");
			// 给其他客户端发送提示信息,系统消息
			this.sendMsgToAllClient("["+clientName+"]已加入聊天室",true);
		} catch (IOException e) {
			e.printStackTrace();
			isRuning = false;
			CloseUtil.closeAll(server,bos,bis);
		}
	}
	
	/**
	 * 接收数据
	 * @return
	 */
	private String receviceMsg() {
		byte [] data = new byte[1024];
		int len = 0;
		try {
			len = this.bis.read(data);
		} catch (IOException e) {
			e.printStackTrace();
			isRuning = false;
			CloseUtil.closeAll(server,bos,bis);
		}
		return new String(data, 0, len);
	}
	
	/**
	 * 发送消息
	 */
	private void sendMsg(String data) {
		try {
			this.bos.write(data.getBytes());
			this.bos.flush();
		} catch (IOException e) {
			e.printStackTrace();
			isRuning = false;
			CloseUtil.closeAll(server,bos,bis);
		}
	}
	
	/**
	 * 发送给另外的客户端消息
	 */
	private void sendMsgToAllClient(String msg,boolean isSysMsg) {
		// 约定以  @ 开头,: 结尾的中间的为私聊的用户名,比如说 @zzq:lcm  就是 我对 zzq 说 lcm
		if( msg.startsWith("@") && msg.indexOf(":")>-1 ) {
			String atName = msg.substring(1,msg.indexOf(":")); // @zzq@lcm@1219:
			String[] atNames = atName.split("@"); // 获取所有 被at的人
			
			String content = msg.substring(msg.indexOf(":")+1); // 获取发送的消息
			// 系统给 @ 的用户名的客户端发送消息
			for (Server other : clients) {
				for (String name : atNames) {
					if(other.clientName.equals(name)) {
						other.sendMsg("[" + this.clientName + "]" + "悄悄的对你说:" + content);
					}
				}
			}
		}else {
			for (Server server : clients) {
				if( server == this ) {
					continue;
				}
				if(isSysMsg) {
					server.sendMsg("【系统消息】"+msg);
				}else {
					server.sendMsg("["+ this.clientName +"]对你们说:"+msg);
				}
			}
		}
	}
	
	@Override
	public void run() {
		while(isRuning) {
			String msg = receviceMsg();
			sendMsgToAllClient(msg,false);
		}
	}
	
}

服务端调用代码不用变,这样就实现 私聊,客户端说话的时候带客户端用户名啦!

效果示例:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值