收获: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){
    
   }
  }
 }
}

Java TCP案例网络聊天室的更多相关文章

  1. Java WebSocket实现网络聊天室(群聊+私聊)

    1.简单说明 在网上看到一份比较nice的基于webSocket网页聊天项目,准备看看学习学习,如是有了这篇文章!原博主博客:http://blog.csdn.net/Amayadream/artic ...

  2. Qt NetWork即时通讯网络聊天室(基于TCP)

    本文使用QT的网络模块来创建一个网络聊天室程序,主要包括以下功能: 1.基于TCP的可靠连接(QTcpServer.QTcpSocket) 2.一个服务器,多个客户端 3.服务器接收到某个客户端的请求 ...

  3. 基于Linux的TCP网络聊天室

    1.实验项目名称:基于Linux的TCP网络聊天室 2.实验目的:通过TCP完成多用户群聊和私聊功能. 3.实验过程: 通过socket建立用户连接并传送用户输入的信息,分别来写客户端和服务器端,利用 ...

  4. php websocket-网页实时聊天之PHP实现websocket(ajax长轮询和websocket都可以时间网络聊天室)

    php websocket-网页实时聊天之PHP实现websocket(ajax长轮询和websocket都可以时间网络聊天室) 一.总结 1.ajax长轮询和websocket都可以时间网络聊天室 ...

  5. 基于TCP协议的聊天室控制台版

    我之前写过一篇博客,主要是基于TCP协议实现的聊天室swing版,在此再写一个基于TCP协议实现的聊天室控制台版,便于学习和比较. package 聊天室console版.utils; import ...

  6. Python3 网络通信 网络聊天室 文件传输

    Python3 网络通信 网络聊天室 文件传输 功能描述 该项目将实现一个文字和文件传输的客户端和服务器程序通信应用程序.它将传输和接收视频文件. 文本消息必须通过TCP与服务器通信,而客户端自己用U ...

  7. Java NIO示例:多人网络聊天室

    一个多客户端聊天室,支持多客户端聊天,有如下功能: 功能1: 客户端通过Java NIO连接到服务端,支持多客户端的连接 功能2:客户端初次连接时,服务端提示输入昵称,如果昵称已经有人使用,提示重新输 ...

  8. JAVA实现webSocket网页聊天室

    一.什么是webSocket WebSocket 是一种网络通信协议,是持久化协议.RFC6455 定义了它的通信标准. WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全 ...

  9. 使用socket搭建一个网络聊天室

    #服务器端import socket import threading #创建一个TCP端 sock = socket.socket(socket.AF_INET, socket.SOCK_STREA ...

随机推荐

  1. S - Primitive Primes CodeForces - 1316C 数学

    数学题 在f(x)和g(x)的系数里找到第一个不是p的倍数的数,然后相加就是答案 为什么? 设x1为f(x)中第一个不是p的倍数的系数,x2为g(x)...... x1+x2前的系数为(a[x1+x2 ...

  2. J - Recommendations CodeForces - 1315D

    https://blog.csdn.net/w_udixixi/article/details/104479288 大意:n个数,每个数只能向上加,a[i]+1需要的时间是t[i],求使这n个数无重复 ...

  3. Git敏捷开发--reset和clean

    reset 丢弃本地所有修改,强行和上游分支保持一致 git reset --hard HEAD 若仅丢弃某个文件的改动,利用checkout git checkout your_file clean ...

  4. Matlab学习-(4)

    1. 函数 1.1 原始方法 之前我调用函数的方法是,首先写好函数文件,然后保存,然后在主函数中调用.这种方法的不足在于会导致你的工作目录的文件太多,从而导致很乱.在网上找了一些解决方法. 1.2 本 ...

  5. Laravel异步队列全攻略

    最近项目需求,研究了laravel的异步队列.官方文档虽然很是详细,但也有些晦涩难懂,在此记录下步骤,供大家参考. 1.修改/config/queue.php文件 <?php return [ ...

  6. 程序选择结构if和switch的定义以及使用方法

       什么是if选择结构 if选择结构是根据条件判断之后在做处理 基本的if选择结构的语法 if(条件){//条件为真则执行代码1,否则不执行  //代码块1 }   if-else选择结构 为什么使 ...

  7. Java IO 流 -- 设计模式:装饰设计模式

    在java IO 流中我们经常看到这样的写法: ObjectOutputStream oos = new ObjectOutputStream( new BufferedOutputStream(ne ...

  8. ubuntu17.10安装lnmp安装包的核心问题-gcc版本、g++版本

    大致碰到的问题都是这样,不是php安装失败,就是MySQL安装失败,或者Nginx也安装失败 基本上是花式报错.后来在军哥的论坛中找到了这个帖子:https://bbs.vpser.net/viewt ...

  9. python-trade

    https://tool.lu/pyc/在线反编译pyc import base64 correct = 'XlNkVmtUI1MgXWBZXCFeKY+AaXNt' flag = base64.b6 ...

  10. (第一篇)linux简介与发展历史以及软件的安装

    1.Linux操作系统基本结构介绍: 操作系统: 英文名称Operating System,简称OS,是计算机系统中必不可少的基础系统软件,它是应用程序运行以及用户操作必备的基础环境支撑,是计算机系统 ...