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. 输入’'大家好 ‘’ 回车