收获: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. Problem D. Ice Cream Tower

    题解:二分加贪心,,,二分答案,然后进行判断,判断的时候,首先给每一组配一个最大的球,然后在向每一组里面填球,注意填球的时候要按组进行,每一组先填一个,然后更新每一组内的最小值,方便下一次寻找. #i ...

  2. 14. 最长公共前缀----LeetCode

    编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower","flow" ...

  3. jdbctemplate打印sql

    在logback.xml里加入如下配置即可: <include resource="org/springframework/boot/logging/logback/base.xml& ...

  4. 常问的MySQL面试题整理

    char.varchar 的区别是什么? varchar是变长而char的长度是固定的.如果创建的列是固定大小的,你会得到更好的性能 truncate 和 delete 的区别是什么? delete ...

  5. MVC-基础02

    MVC是Model(模型).View(视图)和Controller(控制). 1)最上面的一层,是直接面向最终用户的"视图层"(View).它是提供给用户的操作界面,是程序的外壳. ...

  6. Java中的匿名对象代码实例

    /* 匿名对象:就是没有名字的对象. 匿名对象的应用场景: A:调用场景,仅仅只调用一次的时候. 注意:调用多次的时候,不合适. 那么,这种匿名调用有什么好处吗? 有,匿名对象调用完毕就是垃圾.可以被 ...

  7. 新的知识点来了-ES6 Proxy代理 和 去银行存款有什么关系?

    ES给开发者提供了一个新特性:Proxy,就是代理的意思.也就是我们这一节要介绍的知识点. 以前,ATM还没有那么流行的时候(暴露年纪),我们去银行存款或者取款的时候,需要在柜台前排队,等柜台工作人员 ...

  8. 常用mysql 语句

    ALTER TABLE table_name AUTO_INCREMENT = 1;重置自增字段值从1开始 truncate table `table_name` 清空表,保留数据结构

  9. 2019-2020-1 20199308《Linux内核原理与分析》第二周作业

    <Linux内核分析> 第一章 计算机工作原理 1.1 存储程序计算机工作模型 冯·诺依曼体系结构 各种计算机体系结构需要遵从的一个"客观规律" 结构图 冯·诺依曼体系 ...

  10. 数据挖掘入门系列教程(十一点五)之CNN网络介绍

    在前面的两篇博客中,我们介绍了DNN(深度神经网络)并使用keras实现了一个简单的DNN.在这篇博客中将介绍CNN(卷积神经网络),然后在下一篇博客中将使用keras构建一个简单的CNN,对cifa ...