Java TCP案例网络聊天室

收获:1,加深了对多线程的一边一边的理解,可以将行为写成不同的类然后多线程

2,IO流的复习!

3,多线程中一边读取一边操作时容器最好(CopyOnWriteArrayList);

4,Tcp流程的熟悉;

5,封装!!!代码的复用以及整洁!!!

改进:1,注释

2,对其中更多内容的封装,比如消息等

/**
 * 聊天室服务端
 * 实现接受和发送消息
 * 私聊
 * @author 小帆敲代码
 *
 */
public class ChatServer {
 static CopyOnWriteArrayList<Channel> all=new CopyOnWriteArrayList();
 public static void main(String[] args) throws IOException {
  ServerSocket server=new ServerSocket(8888);
  while(true) {
  Socket client=server.accept();
  System.out.println("一个客户端已连接");
  //添加至系统容器
  Channel channel=new Channel(client);
  all.add(channel);
  new Thread(channel).start();
  }
 }
 static class Channel implements Runnable{
  private DataInputStream dis;
  private DataOutputStream dos;
  private boolean isRunning=true;
  private Socket client;
  private boolean isName;
  private String name;
  
  public Channel(Socket client) {
   isName=true;
   isRunning=true;
   this.client=client;
   try {
    dis=new DataInputStream(client.getInputStream());
    dos=new DataOutputStream(client.getOutputStream());
   } catch (IOException e) {
    release();
   }
  }
  //接受消息
  public String receive() {
   String msg="";
   try {
    msg=dis.readUTF();
   } catch (IOException e) {
    release();
   }
   return msg;
  }
  //发送消息
  public void send(String msg) {
   if(!msg.equals("")) {
    try {
     dos.writeUTF(msg);
     dos.flush();
    } catch (IOException e) {
     release();
    }
   }
  }
  //给别人发送消息
  public void sendOthers(String msg) {
   //私聊
   //获取名字和内容
   if(msg.startsWith("@"))
   {
   int idx=msg.indexOf(":");
   String othername=msg.substring(1, idx);
   msg=msg.substring(idx+1);
   for(Channel others:all) {
    if(others.getName().equals(othername))
     {
     others.send(this.name+"悄悄对你说:"+msg);
     break;
     }
   }
   }
   else if(!msg.equals("")) {
    for(Channel others:all) {
     if(others==this)
      this.send("我:"+msg);
     else
      others.send(this.name+":"+msg);
    }
   }
  }
  //释放资源
  public void release() {
   isRunning=false;
   Utils.close(dis,dos,client);
  }
  @Override
  public void run() {
   String msg;
   while(isRunning) {
    if(isName)
    {
     msg=receive();//读
     this.name=msg;
     isName=false;
    }
    else
    {
    msg=receive();//读
    sendOthers(msg);//写
    }
   }
   release();//释放资源
  }
  public String getName() {
   return this.name;
  }
}
}

/**
 * 客户端
 *
 * @author 小帆敲代码
 *
 */
public class ChatClient {
 public static void main(String[] args) throws UnknownHostException, IOException {
  Socket client=new Socket("localhost",8888);
  
  new Thread(new Send(client)).start();
  new Thread(new Receive(client)).start();
 }
}
/**
 * 接收类
 * @author 小帆敲代码
 *
 */
public class Receive implements Runnable{
 private DataInputStream dis;
 private Socket client;
 private boolean isRunning;
 
 public Receive(Socket client) {
  isRunning=true;
  this.client=client;
  try {
   dis=new DataInputStream(client.getInputStream());
  } catch (IOException e) {
   System.out.println("==4==");
   release();
  }
 }
 private String receive() {
  try {
   return dis.readUTF();
  } catch (IOException e) {
   System.out.println("==5==");
   release();
  }
  return "";
 }
 @Override
 public void run() {
  while(isRunning) {
   String msg=receive();
   System.out.println(msg);
  }
  
 }
 public void release() {
  isRunning=false;
  Utils.close(dis,client);
 }
}
/**
 * 发送类
 * @author 小帆敲代码
 *
 */
public class Send implements Runnable{
 private BufferedReader console;
 private DataOutputStream dos;
 private Socket client;
 private boolean isRunning;
 private String name;
 
 public Send(Socket client) {
  isRunning=true;
  this.client=client;
  console=new BufferedReader(new InputStreamReader(System.in));
  try {
   System.out.println("请输入用户名:");
   this.name=console.readLine();
   System.out.println(name+"欢迎回来");
   dos=new DataOutputStream(client.getOutputStream());
   this.send(name);
  } catch (IOException e) {
   System.out.println("==1==");
   release();
  }
 }
/*
 * 约定格式:
 * 私聊:@xxx:msg
 */
 private void send(String msg) {
  if(msg!="") {
   try {
    dos.writeUTF(msg);
    dos.flush();
   } catch (IOException e) {
    System.out.println("==2==");
    release();
   }
  }
 }
 private String getStrFromConsole() {
  try {
   return console.readLine();
  } catch (IOException e) {
   System.out.println("==3==");
   release();
  }
  return "";
 }
 @Override
 public void run() {
  while(isRunning) {
   String msg=getStrFromConsole();
   send(msg);
  }
  
 }
 private void release() {
  isRunning=false;
  Utils.close(console,dos,client);
 }
}
/**
 * 工具类
 * @author 小帆敲代码
 *
 */
public class Utils {
 /**
  *释放资源
  */
 static void close(Closeable... targets) {
  for(Closeable target:targets) {
   try {
    if(target!=null)
     target.close();
   }catch(Exception e){
    
   }
  }
 }
}
上一篇:数组去重


下一篇:Longest Common Subsequence & Substring & prefix