收获: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. Pet BFS

    一天早上小明醒来时发现他的宠物仓鼠不见了. 他在房间寻找但是没找到仓鼠. 他想用奶酪诱饵去找回仓鼠. 他把奶酪诱饵放在房间并且等待了好几天. 但是可怜的小明除了老鼠和蟑螂没见到任何东西. 他找到学校的 ...

  2. niuke --abc

    链接:https://ac.nowcoder.com/acm/contest/1083/A来源:牛客网 给出一个字符串s,你需要做的是统计s中子串”abc”的个数.子串的定义就是存在任意下标a< ...

  3. 对短路变形POJ3615

    Farmer John wants the cows to prepare for the county jumping competition, so Bessie and the gang are ...

  4. Flask接口开发过程中的心得2019.10.03

    完善了一下慕课网实战中的post接口开发,得到了一些进步: 代码如下: #coding=utf-8 from flask import Flask from flask import request ...

  5. 运行一个nodejs服务,先发布为deployment,然后创建service,让集群外可以访问

    问题来源 海口-老男人 17:42:43 就是我要运行一个nodejs服务,先发布为deployment,然后创建service,让集群外可以访问 旧报纸 17:43:35 也就是 你的需求为 一个a ...

  6. CTFHub web技能树之RCE初步 命令注入+过滤cat

    在一个大佬的突然丢了个题过来,于是去玩了玩rce的两道题 大佬的博客跳转链接在此->>>大佬召唤机 叫 命令注入 一上来就是源码出现,上面有个ping的地方 <?php $re ...

  7. 神奇的Kivy,让Python快速开发移动app

    随着移动互联网的不断发展,手机.Pad等移动终端已经被普遍使用,充斥在人们的工作.学习和生活中,越来越多的程序都转向移动终端,各类app应用相拥而至. Kivy作为Python的Android和IOS ...

  8. 原生Js贪吃蛇游戏实战开发笔记

    前言 本课程是通过JavaScript结合WebAPI DOM实现的一版网页游戏---贪吃蛇的开发全过程,采用面向以象的思想设计开发.通过这个小游戏的开发, 不仅可以掌握JS的语法的应用,还可以学会D ...

  9. Metasploit学习笔记(一)

    1.更新 apt-get update:更新源 apt-get upgrade:更新软件包 apt-get dist-upgrade:升级系统 2. Metasploit基础 2.1专业名词 Auxi ...

  10. [C语言] 获得 pwd 的几种函数

    _getcwd() GetCurrentDirectory GetModuleFileName main函数参数 argv[0] // crt_getcwd.c // This program pla ...