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

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

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

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

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

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

  释放资源:

  Utils.java

 package com.bjwyj.chat;

 import java.io.Closeable;

 public class Utils {
/**
* 释放资源
*/
public static void close(Closeable... targets) {
for(Closeable target:targets) {
try {
if(target!=null) {
target.close();
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
}

  服务器端:

  Chat.java

 package com.bjwyj.chat;

 import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.CopyOnWriteArrayList; /**
* 在线聊天室:服务端
* 目标:加入容器实现群聊和私聊
*
* @author 吴永吉
*
*/
public class Chat {
private static CopyOnWriteArrayList<Channel> all = new CopyOnWriteArrayList<>();
public static void main(String[] args) throws IOException {
System.out.println("------server------");
//1.指定端口:使用ServerSocket创建服务器
ServerSocket server = new ServerSocket(9999);
//2.阻塞式等待连接accept
while(true) {
Socket client = server.accept();
System.out.println("一个客户端建立了连接");
Channel c = new Channel(client);
all.add(c); //管理所有的成员
new Thread(c).start();
}
}
//一个客户代表一个Channel
static class Channel implements Runnable{
private DataInputStream dis;
private DataOutputStream dos;
private Socket client;
private boolean isRunning;
private String name; public Channel(Socket client) {
isRunning = true;
this.client = client;
try {
dis = new DataInputStream(client.getInputStream());
dos = new DataOutputStream(client.getOutputStream());
//获取名称
this.name = receive();
//欢迎你的到来
this.send("欢迎上线");
this.sendOthers(this.name+"上线啦!",true);
}catch(Exception e) {
release();
}
} //接收消息
public String receive() {
String msg = "";
try {
msg = dis.readUTF();
} catch (IOException e) {
System.out.println("-------Chat receive------");
release();
}
return msg;
}
//发送消息
public void send(String msg) {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
System.out.println("--------Chat send-------");
release();
}
}
/**
* 群聊:获取自己的消息,发给其他人
* 私聊:约定数据格式:@xxx:msg
* @param msg
*/
public void sendOthers(String msg,boolean isSys) {
boolean isPrivate = msg.startsWith("@");
if(isPrivate) { //私聊
int idx = msg.indexOf(":");
//获取目标和数据
String targetName = msg.substring(1,idx);
msg = msg.substring(idx+1);
for(Channel other:all) {
if(other.name.equals(targetName)) { //目标
other.send(this.name+"悄悄的对你说:"+msg);
break;
}
}
}else { //群聊
for(Channel other:all) {
if(this==other) { //自己
continue;
}
if(!isSys) {
other.send(this.name+"对所有人说:"+msg); //群聊消息
}else {
other.send(msg); //系统消息
}
}
}
}
//关闭资源
public void release() {
this.isRunning = false;
Utils.close(dis,dos,client);
//退出
all.remove(this);
sendOthers(this.name+"下线了!",true);
} @Override
public void run() {
while(isRunning) {
String msg = receive();
if(!msg.equals("")) {
//send(msg);
sendOthers(msg,false);
}
}
}
}
}

  客户端:

  Send.java

 package com.bjwyj.chat;

 import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket; /**
* 使用多线程封装了客户发送端:
* 1.发送消息
* 2.从控制台获取消息
* 3.释放资源
* 4.重写run
* @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,String name) {
isRunning = true;
this.client = client;
this.name = name;
console = new BufferedReader(new InputStreamReader(System.in));
try {
dos = new DataOutputStream(client.getOutputStream());
//发送名称
send(name);
} catch (IOException e) {
System.out.println("------Client Send------");
this.release();
}
} @Override
public void run() {
while(isRunning) {
String msg = this.getStringFromConsole();
if(!msg.equals("")) {
this.send(msg);
}
}
} /**
* 发送消息
*/
private void send(String msg) {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
System.out.println("------Client send------");
release();
}
} /**
* 从控制台获取消息
*/
private String getStringFromConsole() {
try {
return console.readLine();
} catch (IOException e) {
System.out.println("------Client console------");
release();
}
return "";
} //释放资源
private void release() {
this.isRunning = false;
Utils.close(dos,client);
}
}

  Receive.java

 package com.bjwyj.chat;

 import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket; /**
* 使用多线程封装了客户接收端
* 1.接收消息
* 2.释放资源
* 3.重写run
* @author 吴永吉
*
*/
public class Receive implements Runnable{
private DataInputStream dis;
private Socket client;
private boolean isRunning; public Receive(Socket client) {
this.isRunning = true;
this.client = client;
try {
dis = new DataInputStream(client.getInputStream());
} catch (IOException e) {
System.out.println("------Client Receive------");
this.release();
}
} //接收消息
public String receive() {
String msg = "";
try {
msg = dis.readUTF();
} catch (IOException e) {
System.out.println("-------Receive receive------");
release();
}
return msg;
} @Override
public void run() {
while(isRunning) {
String msg = this.receive();
if(!msg.equals("")) {
System.out.println(msg);
}
}
} //释放资源
private void release() {
this.isRunning = false;
Utils.close(dis,client);
}
}

  Client.java

 package com.bjwyj.chat;

 import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException; /**
* 在线聊天室:客户端
*
* @author 吴永吉
*
*/
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("------client------");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入名称:");
String name = br.readLine();
//建立连接:使用Socket创建客户端+服务器的地址和端口号
Socket client = new Socket("localhost",9999);
//客户端发送消息
new Thread(new Send(client,name)).start();
//获取消息
new Thread(new Receive(client)).start();
}
}

  运行结果:

Java网络编程案例---聊天室的更多相关文章

  1. C++ socket 网络编程 简单聊天室

    操作系统里的进程通讯方式有6种:(有名/匿名)管道.信号.消息队列.信号量.内存(最快).套接字(最常用),这里我们来介绍用socket来实现进程通讯. 1.简单实现一个单向发送与接收 这是套接字的工 ...

  2. Java网络编程——UDP聊天程序

    UDP简介 UDP协议的全称是用户数据报,在网络中它与TCP协议一样用于处理数据报.在OSI模型中,UDP位于第四层--传输层,处于IP协议额上一层.UDP有不提供数据报分组.组装以及不能对数据报排序 ...

  3. Java网络编程--简单聊天程序

    背景 毕业设计前的练手,学校小比赛中的一个题目. 开发环境 Java(eclipse)+Mysql 简介 使用Java+Mysql开发以个简单的聊天工具,在本次项目中实现了: 1. 用户登录(客户端至 ...

  4. 基于JAVA网络编程的聊天小程序

    package com.neusoft.edu.socket; import java.io.BufferedReader; import java.io.IOException; import ja ...

  5. Java 学习之网络编程案例

    网络编程案例 一,概念 1,网络编程不等于网站编程 2,编程只和传输层打交道,即TCP和UDP两个协议 二,案例 1,TCP实现点对点的聊天 Server端:两个输入流:读客户端和控制台,一个输出端: ...

  6. JAVA 网络编程 - 实现 群聊 程序

    在实现 这个 程序之前, 我们 需要 了解 一些 关于 Java 网络 编程 的 知识. 基本 的 网络知识: 网络模型 OSI (Open System Interconnection 开放系统互连 ...

  7. day05 Java网络编程socket 与多线程

    java网络编程 java.net.Socket Socket(套接字)封装了TCP协议的通讯细节,是的我们使用它可以与服务端建立网络链接,并通过 它获取两个流(一个输入一个输出),然后使用这两个流的 ...

  8. 自定义异常、Java网络编程

    day04 throw关键字 throw用来对外主动抛出一个异常,通常下面两种情况我们主动对外抛出异常: 1:当程序遇到一个满足语法,但是不满足业务要求时,可以抛出一个异常告知调用者. 2:程序执行遇 ...

  9. Java网络编程(一)

    Java网络编程: 1.1: 网络编程:对于我这个“研究不深”的网络菜鸟来说,我觉得网络编程就是实现计算机与计算机之间通信的编程.写些能够实现计算机与计算机之间的通信就行了(目前来说). 1.2:一台 ...

随机推荐

  1. Confluence 6 home 修改 Home 目录的位置

    当 Confluence 第一次启动的时候,Confluence 将会读取 confluence-init.properties 文件并从这个文件中确定如何去查找 Home 目录. 希望修改 home ...

  2. Confluence 6 生产环境备份策略

    如果你是下面的情况,Confluence 的自动每日 XML 备份可能适合你: 正在评估使用 Confluence 你对数据库的管理并不是非常熟悉同时你的 Confluence 安装实例的数据量并不大 ...

  3. RemoveDuplicatesfromSortedList

    给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次. 示例 1: 输入: 1->1->2 输出: 1->2 示例 2: 输入: 1->1->2->3-&g ...

  4. rpm命令用法小结

    rpm 是用来管理 Redhat系列的包管理工具: 通过将打包编译好的程序包文件放置在各自的位置上,就完成了安装: rpm   [OPTIONS]   PACHAGE_FILE 1 安装:: -i : ...

  5. uva11865 二分流量+最小生成树

    uva好题真多 本题用二分法找flow,把流量小于flow的全部筛掉,剩下的边建立最小树形图,如果权值大于c或者不能建图,那么修改二分边界 上代码,觉得最小树形图的代码很优美 /* 题意:给定n个点, ...

  6. 配置webpack loader vue 报错:Module build failed: TypeError: this._init is not a function

    单文件组件 引入时报错 配置webpage.config.js中的vue 需要如下写法 { test: /\.vue/, loader: "vue-loader", } 之前写的l ...

  7. Android取得系统时间

    Time t = new Time();//实例化Time类 t.setToNow();//取得当前的系统时间 int month = t.month;//获取月 int year = t.year; ...

  8. 目标检测算法之Fast R-CNN算法详解

    在介绍Fast R-CNN之前我们先介绍一下SPP Net 一.SPP Net SPP:Spatial Pyramid Pooling(空间金字塔池化) 众所周知,CNN一般都含有卷积部分和全连接部分 ...

  9. Spring Cloud与Spring Boot版本匹配关系

    Spring Cloud是什么? “Spring Cloud provides tools for developers to quickly build some of the common pat ...

  10. 【C++ Primer | 07】常用算法

    第一部分 常用泛型算法: find(beg, end, val); equal(beg1, end1, beg2); fill(beg, end, val); fill_n(beg, cnt, val ...