Java网络编程案例---聊天室
网络编程是指编写运行在多个设备(计算机)的程序,这些设备都通过网络连接起来。
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网络编程案例---聊天室的更多相关文章
- C++ socket 网络编程 简单聊天室
操作系统里的进程通讯方式有6种:(有名/匿名)管道.信号.消息队列.信号量.内存(最快).套接字(最常用),这里我们来介绍用socket来实现进程通讯. 1.简单实现一个单向发送与接收 这是套接字的工 ...
- Java网络编程——UDP聊天程序
UDP简介 UDP协议的全称是用户数据报,在网络中它与TCP协议一样用于处理数据报.在OSI模型中,UDP位于第四层--传输层,处于IP协议额上一层.UDP有不提供数据报分组.组装以及不能对数据报排序 ...
- Java网络编程--简单聊天程序
背景 毕业设计前的练手,学校小比赛中的一个题目. 开发环境 Java(eclipse)+Mysql 简介 使用Java+Mysql开发以个简单的聊天工具,在本次项目中实现了: 1. 用户登录(客户端至 ...
- 基于JAVA网络编程的聊天小程序
package com.neusoft.edu.socket; import java.io.BufferedReader; import java.io.IOException; import ja ...
- Java 学习之网络编程案例
网络编程案例 一,概念 1,网络编程不等于网站编程 2,编程只和传输层打交道,即TCP和UDP两个协议 二,案例 1,TCP实现点对点的聊天 Server端:两个输入流:读客户端和控制台,一个输出端: ...
- JAVA 网络编程 - 实现 群聊 程序
在实现 这个 程序之前, 我们 需要 了解 一些 关于 Java 网络 编程 的 知识. 基本 的 网络知识: 网络模型 OSI (Open System Interconnection 开放系统互连 ...
- day05 Java网络编程socket 与多线程
java网络编程 java.net.Socket Socket(套接字)封装了TCP协议的通讯细节,是的我们使用它可以与服务端建立网络链接,并通过 它获取两个流(一个输入一个输出),然后使用这两个流的 ...
- 自定义异常、Java网络编程
day04 throw关键字 throw用来对外主动抛出一个异常,通常下面两种情况我们主动对外抛出异常: 1:当程序遇到一个满足语法,但是不满足业务要求时,可以抛出一个异常告知调用者. 2:程序执行遇 ...
- Java网络编程(一)
Java网络编程: 1.1: 网络编程:对于我这个“研究不深”的网络菜鸟来说,我觉得网络编程就是实现计算机与计算机之间通信的编程.写些能够实现计算机与计算机之间的通信就行了(目前来说). 1.2:一台 ...
随机推荐
- Confluence 6 关于 Decorators
Confluence 是使用开源的 SiteMesh 库构建的.一个 Web 页面的布局系统,这个布局系统能够在全站点中提供完整统一的界面和外观.SiteMesh 是通过 "decorato ...
- Java的家庭记账本程序(F)
日期:2019.2.17 博客期:034 星期日 我先配置了Android的相关环境,先试着做了Hello World的测试,但是却出现了很严重的问题,问题如下: Unable to get curr ...
- kafka消息存储与partition副本原理
消息的存储原理: 消息的文件存储机制: 前面我们知道了一个 topic 的多个 partition 在物理磁盘上的保存路径,那么我们再来分析日志的存储方式.通过 ll /tmp/kafka-logs/ ...
- 新增 修改,对xx名字或者其他属性做校验判断是否存在
需求描述:页面输入完xxName和xx编码,点击提交,根据两项内容做重复校验(就是看看数据库里有木有相同的) 解决思路:把这两个东西作为查询条件去查,查到有记录,提示已存在,就不执行新增或者修改操作. ...
- Winhex数据恢复笔记(五)
一.上次介绍了Windows API函数,这次对Windows API函数的参数做个笔记 1.IpFileName: 文件名指针,也可指向 MS-Dos设备名,同时支持文件和设备名,函数分为两个版本 ...
- cf1140E 回文串+染色方案dp
有点硬核的dp..要用到一个结论.. /* 把原串拆成奇偶串,再拆成极大连续的-1串:该串两端都是非-1数,中间都是-1,并且下标要么都是偶数,要么都是技术 然后对所有这些串进行dp,dp[i][0] ...
- bzoj 1002
表示我这种蒟蒻面对这种递推第一思想显然是打表啊 先贴个用来打表的暴力: #include <cstdio> struct node { int l,r; }p[]; ]; ]; i ...
- Java 获取窗口的宽、高
创建一个新窗口,通过getSize()获取这个窗口的宽.高. import javax.swing.JFrame; public class WindowInTheMiddle extends JFr ...
- python提取文件中的方法名称
#提取文件中的方法名称 # -*- coding:utf-8 -*- def Query_Method(filepath): file = open(filepath,'r',encoding= 'U ...
- Spring Cloud Eureka简介及原理
Eureka是Netflix开发的服务发现组件,本身是一个基于REST的服务.Spring Cloud将它集成在其子项目spring-cloud-netflix中,以实现Spring Cloud的服务 ...