java网络编程_194_TCP_Socket通信_聊天室_私聊_实现_练习

package 网络编程_194_TCP_Socket通信_聊天室_私聊_实现_练习;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

/**
私聊如何实现
/
public class Server { //server服务器
//把一条管道变成多条管道;加入容器并遍历容器
private List all = new ArrayList();
/

* @throws IOException
*/
public static void main(String[] args) throws IOException {
new Server().start();
}

public void start() throws IOException{
	ServerSocket server = new ServerSocket(9999);//声明异常;ServerSocket服务端
	//如果接收多个客户端就加入循环;
	//程序这里出现问题  :谁先到谁先交流,一个客户端就一根管道
	while(true){
		//先处理一个
		Socket client = server.accept();//Socket套接字;client客户;accept接受
		//因为下面容器的加入,由一条道路现在变成很多道路
		MyChannel channel = new MyChannel(client);//因为MyChannel是内部类,而这里又是静态方法;所以报异常
												//创建一个start()类;并移动到start()里面
		//加入管道
		all.add(channel);//统一管理
		//创建线程
		new Thread(channel).start();//一条道路
	}
}
/**
 * 一个客户端一条管道
 * 创建方法,将输出流输入流封装; 
 * 输入流-->接收数据
 * 输出流-->发送数据
 * @author Administrator
 *   
 */
private class MyChannel implements Runnable{
	private DataInputStream dis;
	private DataOutputStream dos;
	private boolean isRunning = true;
	
	private String name;//为私聊完善
	
	//初始化
	public MyChannel(Socket client) {
		try {
			dis = new DataInputStream( client.getInputStream());
			dos = new  DataOutputStream(client.getOutputStream());
		
			//为私聊完善; 读取名称
		this.name = dis.readUTF();
		//测试 是否读取
		// System.out.println(this.name);
		this.send("欢迎进入聊天室");//发给自己
		//发给其他人
		sendOthers(this.name+"进入了聊天室",true);//如果为true 就是系统发的信息
		
		} catch (IOException e) {
			//e.printStackTrace();
			CloseUtil.closeAll(dos,dis);
			isRunning = false;
		}
	} 
	/**
	 * 接收(读取)数据
	 */
	private String receive(){
		String msg = "";
		try {
			msg = dis.readUTF();//处理异常
		} catch (IOException e) {
			//e.printStackTrace();
			CloseUtil.closeAll(dis);
			isRunning = false;
			
			all.remove(this);//出异常就把自己移出去
		} 
		return msg;
	}
	/**
	 * 发送数据
	 */
	private void send(String msg){
		if(null==msg||msg.equals("")){
			return ;
		}
		try {
			dos.writeUTF(msg);
			dos.flush();
		} catch (IOException e) {
			//e.printStackTrace();
			CloseUtil.closeAll(dos);
			isRunning = false;
			
			all.remove(this);//出异常就把自己移出去
		}
	} 
	/**
	 * 
	 * 把自己的信息,发送给其他客户端;如何实现私聊
	 */
	private void sendOthers(String msg,boolean sys){//boolean sys代表系统
		//判断,是否为私聊;因为没有显示的界面,所以后台自己约定的私聊标识 
		
		if(msg.startsWith("@")&& msg.indexOf(":")>-1){//用@代表私聊
			
			String  name = msg.substring(1,msg.indexOf(":"));//从0开始 ,后面是需要的内容;
			//content内容 ;substring子字符串;indexOf查找字符或者子串第一次出现的地方
			String content = msg.substring(msg.indexOf(":")+1);//从':'开始,后面是需要的内容;左闭右开所以加'1'
			//遍历容器name
			for(MyChannel other:all){//other其他的
				if(other.name.equals(name)){//判断;如果与你发送私聊的名字相同
					other.send(this.name+"对您悄悄的说:"+content);
				}
			}
		}else{//所有人
			//遍历容器 类型是MyChannel
			for(MyChannel other:all){//other其他的
				if(other==this){//判断;
					continue;//如果等于自身就 跳过
				}
				if(sys){//系统信息
					other.send("系统信息:"+msg);
				}else{
					//否则发给其他客户端
					other.send(this.name+"对所有人说:"+msg);//从容器中获取的内容发给其他客户端
				}
			}
		}
	}
	/**
	 * 循环读取和发送
	 */
	@Override
	public void run() { 
		while(isRunning){
			//send(receive());//这个是自己发给自己
			//receive(send());
			sendOthers(receive(),false);//不是系统发的就是false
		}  	  
	}
}

}
//--------------------------------------------------------
package 网络编程_194_TCP_Socket通信_聊天室_私聊_实现_练习;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;

/**

  • 如何加入私聊

*/
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
//输入提示
System.out.println(“请输入名称:”);
//键盘输入
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String name = br.readLine();//读取
if(name.equals("")){
return ;

	 }
	//服务器吧的地址以及端口
	Socket client = new Socket("localhost",9999);//localhost本地服务器;声明异常 
	 	
	//控制台的输入流;已经封装    //为私聊完善,添加name
	new Thread(new Send(client,name)).start();//Thread线程;Send发送;  start启动
	
	new Thread(new Receive(client)).start();//第二条路径
}

}

//其他方法 同’‘193’'一致;没有添加新内容

//结果-----------------------------------------------
1.启动服务器
在这里插入图片描述
2.启动客户端 输入a
在这里插入图片描述
3…启动客户端 输入b
在这里插入图片描述
在这里插入图片描述
4…启动客户端 输入c 在输入’’@b:你好",回车
在这里插入图片描述
在这里插入图片描述
测试
5.a客户端没有收到消息 程序运行正确
在这里插入图片描述
6. 输入’'大家好 ‘’ 回车
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值