java网络编程案例---聊天室

wuyongji      2022-05-02     548

关键词:

  网络编程是指编写运行在多个设备(计算机)的程序,这些设备都通过网络连接起来。

  java.net包中JavaSE的API包含有类和接口,它们提供低层次的通信细节。你可以直接使用这些类和接口,来专注于解决问题,而不用关注通信细节。

  java.net包中提供了两种常见的网络协议的支持:

  TCP:TCP是传输控制协议的缩写,它保障了两个应用程序之间的可靠通信。通常用于互联网协议,被称TCP/IP。

  UDP:UDP是用户数据报协议的缩写,一个无连接的协议。提供了应用程序之间要发送的数据的数据报。

  本案例以TCP协议为例,结合多线程,实现一个多人同时聊天的聊天室。

  释放资源:

  Utils.java

 1 package com.bjwyj.chat;
 2 
 3 import java.io.Closeable;
 4 
 5 public class Utils {
 6     /**
 7      * 释放资源
 8      */
 9     public static void close(Closeable... targets) {
10         for(Closeable target:targets) {
11             try {
12                 if(target!=null) {
13                     target.close();
14                 }
15             }catch(Exception e) {
16                 e.printStackTrace();
17             }
18         }
19     }
20 }

  服务器端:

  Chat.java

  1 package com.bjwyj.chat;
  2 
  3 import java.io.DataInputStream;
  4 import java.io.DataOutputStream;
  5 import java.io.IOException;
  6 import java.net.ServerSocket;
  7 import java.net.Socket;
  8 import java.util.concurrent.CopyOnWriteArrayList;
  9 
 10 /**
 11  * 在线聊天室:服务端
 12  * 目标:加入容器实现群聊和私聊
 13  * 
 14  * @author 吴永吉
 15  *
 16  */
 17 public class Chat {
 18     private static CopyOnWriteArrayList<Channel> all = new CopyOnWriteArrayList<>();
 19     public static void main(String[] args) throws IOException {
 20         System.out.println("------server------");
 21         //1.指定端口:使用ServerSocket创建服务器
 22         ServerSocket server = new ServerSocket(9999);
 23         //2.阻塞式等待连接accept
 24         while(true) {
 25             Socket client = server.accept();
 26             System.out.println("一个客户端建立了连接");
 27             Channel c = new Channel(client);
 28             all.add(c); //管理所有的成员
 29             new Thread(c).start();
 30         }
 31     }
 32     //一个客户代表一个Channel
 33     static class Channel implements Runnable{
 34         private DataInputStream dis;
 35         private DataOutputStream dos;
 36         private Socket client;
 37         private boolean isRunning;
 38         private String name;
 39         
 40         public Channel(Socket client) {
 41             isRunning = true;
 42             this.client = client;
 43             try {
 44                 dis = new DataInputStream(client.getInputStream());
 45                 dos = new DataOutputStream(client.getOutputStream());
 46                 //获取名称
 47                 this.name = receive();
 48                 //欢迎你的到来
 49                 this.send("欢迎上线");
 50                 this.sendOthers(this.name+"上线啦!",true);
 51             }catch(Exception e) {
 52                 release();
 53             }
 54         }
 55         
 56         //接收消息
 57         public String receive() {
 58             String msg = "";
 59             try {
 60                 msg = dis.readUTF();
 61             } catch (IOException e) {
 62                 System.out.println("-------Chat receive------");
 63                 release();
 64             }
 65             return msg;
 66         }
 67         //发送消息
 68         public void send(String msg) {
 69             try {
 70                 dos.writeUTF(msg);
 71                 dos.flush();
 72             } catch (IOException e) {
 73                 System.out.println("--------Chat send-------");
 74                 release();
 75             }
 76         }
 77         /**
 78          * 群聊:获取自己的消息,发给其他人
 79          * 私聊:约定数据格式:@xxx:msg
 80          * @param msg
 81          */
 82         public void sendOthers(String msg,boolean isSys) {
 83             boolean isPrivate = msg.startsWith("@");
 84             if(isPrivate) { //私聊
 85                 int idx = msg.indexOf(":");
 86                 //获取目标和数据
 87                 String targetName = msg.substring(1,idx);
 88                 msg = msg.substring(idx+1);
 89                 for(Channel other:all) {
 90                     if(other.name.equals(targetName)) { //目标
 91                         other.send(this.name+"悄悄的对你说:"+msg);
 92                         break;
 93                     }
 94                 }
 95             }else { //群聊
 96                 for(Channel other:all) {
 97                     if(this==other) { //自己
 98                         continue;
 99                     }
100                     if(!isSys) {
101                         other.send(this.name+"对所有人说:"+msg); //群聊消息
102                     }else {
103                         other.send(msg); //系统消息
104                     }
105                 }
106             }
107         }
108         //关闭资源
109         public void release() {
110             this.isRunning = false;
111             Utils.close(dis,dos,client);
112             //退出
113             all.remove(this);
114             sendOthers(this.name+"下线了!",true);
115         }
116 
117         @Override
118         public void run() {
119             while(isRunning) {
120                 String msg = receive();
121                 if(!msg.equals("")) {
122                     //send(msg);
123                     sendOthers(msg,false);
124                 }
125             }
126         }
127     }
128 }

  客户端:

  Send.java

 1 package com.bjwyj.chat;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.DataOutputStream;
 5 import java.io.IOException;
 6 import java.io.InputStreamReader;
 7 import java.net.Socket;
 8 
 9 /**
10  * 使用多线程封装了客户发送端:
11  * 1.发送消息
12  * 2.从控制台获取消息
13  * 3.释放资源
14  * 4.重写run
15  * @author 吴永吉
16  *
17  */
18 public class Send implements Runnable{
19     private BufferedReader console;
20     private DataOutputStream dos;
21     private Socket client;
22     private boolean isRunning;
23     private String name;
24     
25     public Send(Socket client,String name) {
26         isRunning = true;
27         this.client = client;
28         this.name = name;
29         console = new BufferedReader(new InputStreamReader(System.in));
30         try {
31             dos = new DataOutputStream(client.getOutputStream());
32             //发送名称
33             send(name);
34         } catch (IOException e) {
35             System.out.println("------Client Send------");
36             this.release();
37         }
38     }
39     
40     @Override
41     public void run() {
42         while(isRunning) {
43             String msg = this.getStringFromConsole();
44             if(!msg.equals("")) {
45                 this.send(msg);
46             }
47         }
48     }
49     
50     /**
51      * 发送消息
52      */
53     private void send(String msg) {
54         try {
55             dos.writeUTF(msg);
56             dos.flush();
57         } catch (IOException e) {
58             System.out.println("------Client send------");
59             release();
60         }
61     }
62     
63     /**
64      * 从控制台获取消息
65      */
66     private String getStringFromConsole() {
67         try {
68             return console.readLine();
69         } catch (IOException e) {
70             System.out.println("------Client console------");
71             release();
72         }
73         return "";
74     }
75     
76     //释放资源
77     private void release() {
78         this.isRunning = false;
79         Utils.close(dos,client);
80     }
81 }

  Receive.java

 1 package com.bjwyj.chat;
 2 
 3 import java.io.DataInputStream;
 4 import java.io.IOException;
 5 import java.net.Socket;
 6 
 7 /**
 8  * 使用多线程封装了客户接收端
 9  * 1.接收消息
10  * 2.释放资源
11  * 3.重写run
12  * @author 吴永吉
13  *
14  */
15 public class Receive implements Runnable{
16     private DataInputStream dis;
17     private Socket client;
18     private boolean isRunning;
19     
20     public Receive(Socket client) {
21         this.isRunning = true;
22         this.client = client;
23         try {
24             dis = new DataInputStream(client.getInputStream());
25         } catch (IOException e) {
26             System.out.println("------Client Receive------");
27             this.release();
28         }
29     }
30     
31     //接收消息
32     public String receive() {
33         String msg = "";
34         try {
35             msg = dis.readUTF();
36         } catch (IOException e) {
37             System.out.println("-------Receive receive------");
38             release();
39         }
40         return msg;
41     }
42     
43     @Override
44     public void run() {
45         while(isRunning) {
46             String msg = this.receive();
47             if(!msg.equals("")) {
48                 System.out.println(msg);
49             }
50         }
51     }
52     
53     //释放资源
54     private void release() {
55         this.isRunning = false;
56         Utils.close(dis,client);
57     }
58 }

  Client.java

 1 package com.bjwyj.chat;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.IOException;
 5 import java.io.InputStreamReader;
 6 import java.net.Socket;
 7 import java.net.UnknownHostException;
 8 
 9 /**
10  * 在线聊天室:客户端
11  * 
12  * @author 吴永吉
13  *
14  */
15 public class Client {
16     public static void main(String[] args) throws UnknownHostException, IOException {
17         System.out.println("------client------");
18         BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
19         System.out.println("请输入名称:");
20         String name = br.readLine();
21         //建立连接:使用Socket创建客户端+服务器的地址和端口号
22         Socket client = new Socket("localhost",9999);
23         //客户端发送消息
24         new Thread(new Send(client,name)).start();
25         //获取消息
26         new Thread(new Receive(client)).start();
27     }
28 }

  运行结果:

技术图片技术图片

技术图片技术图片

java网络编程:案例四:多个客户端群聊(代码片段)

  需求:模拟聊天室群聊  客户端要先登录,登录成功之后才能发送和接收消息  分析:  服务器端,需要为每个客户端开启一个线程通信,这样才能实现多个客户端“同时”与服务器通信  客户端,需要把... 查看详情

golang网络聊天室案例(代码片段)

1.聊天室设计分析一.概览实现个网络聊天室(群)功能分析:上线下线聊天,其他人,自己都可以看到聊天消息查询当前聊天室用户名字who可以修改自己名字rename|Duke超时踢出技术点分析:1.socktcp编程2.map... 查看详情

golang网络聊天室案例(代码片段)

1.聊天室设计分析一.概览实现个网络聊天室(群)功能分析:上线下线聊天,其他人,自己都可以看到聊天消息查询当前聊天室用户名字who可以修改自己名字rename|Duke超时踢出技术点分析:1.socktcp编程2.map... 查看详情

javasocket编程--聊天小案例

  很久以前写过socket聊天室,都快忘完了,心血来潮又重新写一遍。服务器端:packagecom.fancy;importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStream;importjava.io.InputStreamReader;importjava.io.OutputStream;imp 查看详情

[8421论坛]2019socket网络编程入门到进阶与实战完整视频教程

...章 课程介绍及java语言简介第二章 快速入门Socket网络编程第三章 快速入门Socket UDP第四章 快速入门Socket TCP第五章 UDP辅助TCP实现点对点传输案例第六章 简易聊天室案例第七章 服务器传输优化-NIO... 查看详情

p2p网络编程-3-案例实践:pubsub(代码片段)

libp2p网络通信中还有一种方式就是PubSub模式,也称订阅发布的模式,官方给出了订阅发布模式的一个案例=>聊天室在此学习记录一下官方代码地址:https://github.com/libp2p/go-libp2p/tree/master/examples/pubsub一、效果演示二... 查看详情

java利用tcp编程实现简单聊天室

前言:本文是我在学习尚学堂JAVA300集第二季网络编程部分仿照视频内容实现而成具体可以去尚学堂官网观看视频学习一、实现思路  实现聊天室的最核心部分就是JAVA的TCP网络编程。  TCP传输控制协议是一种面向连接的、可... 查看详情

第99题java高级技术-网络编程18(简易聊天室13:聊天室服务端)(代码片段)

回城传送–》《JAVA筑基100例》文章目录零、前言一、题目描述二、解题思路三、代码详解多学一个知识点四、推荐专栏五、示例源码下载零、前言​今天是学习JAVA语言打卡的第99天,每天我会提供一篇文章供群成员阅读࿰... 查看详情

网络编程之java简易聊天室实现

最近浅学习了一些关于网络编程方面的知识,视频是跟着狂神学习的,可能学习的不是很深说到网络,相信大家都对TCP、UDP和HTTP协议这些都不是很陌生,学习这部分应该先对端口、Ip地址这些基础知识有一定了解,后面我们都是... 查看详情

12.6-全栈java笔记:java网络编程

上节回顾:在学习了Socket建立客户端和服务器双向交流后,我们发现它的问答形式不够灵活。本节课我们讲解如何在服务器和客户端之间实现聊天室~需要思考的问题:服务器端:一个线程专门发送消息,一个线程专门接收消息... 查看详情

java网络编程udp案例

Java网络编程、UDP案例发送端import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.SocketException;import&nb 查看详情

java网络编程udp案例

Java网络编程、UDP案例发送端import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.SocketException;import&nb 查看详情

html5聊天案例|趣聊h5|仿微信界面聊天|红包|语音聊天|地图

之前有开发过一个h5微直播项目,当时里面也用到过聊天模块部分,今天就在之前聊天部分的基础上重新抽离模块,开发了这个h5趣聊项目,功能效果比较类似微信聊天界面。采用html5+css3+Zepto+swiper+wcPop+flex等技术融合开发,实现... 查看详情

第98题java高级技术-网络编程17(简易聊天室12:实现客户端一对一聊天)

回城传送–》《JAVA筑基100例》文章目录零、前言一、题目描述二、解题思路三、代码详解多学一个知识点四、推荐专栏五、示例源码下载零、前言​今天是学习JAVA语言打卡的第98天,每天我会提供一篇文章供群成员阅读(不需... 查看详情

java学习网络编程全总结——tcpudp多线程io流socket简易在线咨询聊天室java爬虫(代码片段)

目录网络编程1.1、概述1.2、网络通信的要素1.3、IP1.4、端口(port)1.5、通信协议1.6、TCP文件上传Tomcat1.7、UDP发送消息构造方法摘要构造方法摘要咨询DatagramPacket.getData()与DatagramPacket.getLength()的误区trimstartsWith在线咨询:两个人都... 查看详情

第92题java高级技术-网络编程11(简易聊天室6:使用socket通信)

回城传送–》《JAVA筑基100例》文章目录零、前言一、题目描述二、解题思路三、代码详解四、推荐专栏五、示例源码下载零、前言​今天是学习JAVA语言打卡的第92天,每天我会提供一篇文章供群成员阅读(不需要订阅付钱),... 查看详情

第89题java高级技术-网络编程8(简易聊天室3:连接超时)(代码片段)

回城传送–》《JAVA筑基100例》文章目录零、前言一、题目描述二、解题思路三、代码详解四、推荐专栏五、示例源码下载零、前言​今天是学习JAVA语言打卡的第89天,每天我会提供一篇文章供群成员阅读(不需要订阅付... 查看详情

第93题java高级技术-网络编程12(简易聊天室7:使用socket传递对象)

回城传送–》《JAVA筑基100例》文章目录零、前言一、题目描述二、解题思路三、代码详解四、推荐专栏五、示例源码下载零、前言​今天是学习JAVA语言打卡的第93天,每天我会提供一篇文章供群成员阅读(不需要订阅付钱),... 查看详情