Java实现在线聊天室层层递进_第1页
Java实现在线聊天室层层递进_第2页
Java实现在线聊天室层层递进_第3页
Java实现在线聊天室层层递进_第4页
Java实现在线聊天室层层递进_第5页
已阅读5页,还剩14页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第Java实现在线聊天室(层层递进)本文实例为大家分享了Java实现在线聊天室的具体代码,供大家参考,具体内容如下

-本文讲述了从实现单个多个客户的收发信息(基础简易版),到各种实现代码的封装(oop版),实现群聊(群聊过渡版),到最后实现私聊(终极版)的过程

-本文内容是在初步学习网络编程时,练习强化记忆时的学习总结

-主要利用了TCP网络编程和多线程

-如有问题,欢迎指出

综合案例:在线聊天室

需求:使用TCP的Socket实现一个聊天室

服务器端:一个线程专门发送消息,一个线程专门接收消息客户端:一个线程专门发送消息,一个线程专门接收消息

1.基础简易版

1.1一个客户收发多条消息

目标:实现一个客户可以正常收发多条信息

服务器

/**

*在线聊天室:服务器

*目标:实现一个客户可以正常收发多条消息

*

服务器不生产内容,相当于一个转发站,将客户端的请求转发

publicclassMutiChat{

publicstaticvoidmain(String[]args)throwsIOException{

System.out.println("-----Server-----");

//1、指定端口

使用ServerSocket创建服务器

ServerSocketserver=newServerSocket(8888);

//2、利用Socket的accept方法,监听客户端的请求。阻塞,等待连接的建立

Socketclient=server.accept();

System.out.println("一个客户端建立了连接");

DataInputStreamdis=newDataInputStream(client.getInputStream());

DataOutputStreamdos=newDataOutputStream(client.getOutputStream());

booleanisRunning=true;

while(isRunning){

//3、接收消息

Stringmsg=dis.readUTF();

//4、返回消息

dos.writeUTF(msg);

dos.flush();

}

//5、释放资源

dos.close();

dis.close();

client.close();

}

}

客户端

/**

*在线聊天室:客户端

*目标:实现一个客户可以正常收发(多条)信息

publicclassMutiClient{

publicstaticvoidmain(String[]args)throwsIOException{

System.out.println("-----Client-----");

//1、建立连接:使用Socket创建客户端+服务的地址和端口

Socketclient=newSocket("localhost",8888);

//2、客户端发送消息

BufferedReaderconsole=newBufferedReader(newInputStreamReader(System.in));

//对接控制台

DataOutputStreamdos=newDataOutputStream(client.getOutputStream());

DataInputStreamdis=newDataInputStream(client.getInputStream());

booleanisRunning=true;

while(isRunning){

Stringmsg=console.readLine();

dos.writeUTF(msg);

dos.flush();

//3、获取消息

msg=dis.readUTF();

System.out.println(msg);

}

//4、释放资源

dos.close();

dis.close();

client.close();

}

}

1.2多个客户收发多条消息(不使用多线程)

目标:实现多个客户可以正常收发多条信息出现排队问题:其他客户必须等待之前的客户退出,才能收发消息

服务器

publicclassMutiChat{

publicstaticvoidmain(String[]args)throwsIOException{

System.out.println("-----Server-----");

//1、指定端口

使用ServerSocket创建服务器

ServerSocketserver=newServerSocket(8888);

//2、利用Socket的accept方法,监听客户端的请求。阻塞,等待连接的建立

while(true){

Socketclient=server.accept();

System.out.println("一个客户端建立了连接");

DataInputStreamdis=newDataInputStream(client.getInputStream());

DataOutputStreamdos=newDataOutputStream(client.getOutputStream());

booleanisRunning=true;

while(isRunning){

//3、接收消息

Stringmsg=dis.readUTF();

//4、返回消息

dos.writeUTF(msg);

dos.flush();

}

//5、释放资源

dos.close();

dis.close();

client.close();

}

}

}

1.3多个客户收发多条消息(多线程)

目标:实现多个客户可以正常收发多条信息出现的问题:利用Lambda太复杂,代码过多不好维护;客户端读写没有分开,必须先写后读

服务器代码

publicclassThreadMutiChat{

publicstaticvoidmain(String[]args)throwsIOException{

System.out.println("-----Server-----");

//1、指定端口

使用ServerSocket创建服务器

ServerSocketserver=newServerSocket(8888);

//2、利用Socket的accept方法,监听客户端的请求。阻塞,等待连接的建立

while(true){

Socketclient=server.accept();

System.out.println("一个客户端建立了连接");

//加入多线程

newThread(()-{

DataInputStreamdis=null;

DataOutputStreamdos=null;

try{

dis=newDataInputStream(client.getInputStream());

dos=newDataOutputStream(client.getOutputStream());

}catch(IOExceptione){

e.printStackTrace();

}

booleanisRunning=true;

while(isRunning){

//3、接收消息

Stringmsg=null;

try{

msg=dis.readUTF();

//4、返回消息

dos.writeUTF(msg);

dos.flush();

}catch(IOExceptione){

//

e.printStackTrace();

isRunning=false;

//停止线程

}

}

//5、释放资源

try{

if(null==dos){

dos.close();

}

}catch(IOExceptione){

e.printStackTrace();

}

try{

if(null==dis){

dis.close();

}

}catch(IOExceptione){

e.printStackTrace();

}

try{

if(null==client){

client.close();

}

}catch(IOExceptione){

e.printStackTrace();

}

}).start();

}

}

}

2.oop封装版

目标:封装使用多线程实现多个客户可以正常收发多条消息

1、线程代理Channel,一个客户代表一个Channel2、实现方法:接收消息-receive;发送消息-send;释放资源-release;3、其中释放资源release方法中利用工具类Utils:实现Closeable接口、可变参数好处:利用封装,是代码简洁,便于维护

服务器端

示例代码:

publicclassThreadMutiChat{

publicstaticvoidmain(String[]args)throwsIOException{

System.out.println("---服务器开始工作---");

//1、指定端口

使用ServerSocket创建服务器

ServerSocketserver=newServerSocket(8888);

//2、利用Socket的accept方法,监听客户端的请求。阻塞,等待连接的建立

while(true){

Socketclient=server.accept();

System.out.println("一个客户端建立了连接");

newThread(newChannel(client)).start();

}

}

//一个客户代表一个Channel

staticclassChannelimplementsRunnable{

privateDataInputStreamdis=null;

privateDataOutputStreamdos=null;

privateSocketclient;

privatebooleanisRunning;

publicChannel(Socketclient){

this.client=client;

try{

dis=newDataInputStream(client.getInputStream());

dos=newDataOutputStream(client.getOutputStream());

isRunning=true;

}catch(IOExceptione){

System.out.println("---构造时出现异常---");

release();

}

}

//接收消息

privateStringreceive(){

Stringmsg="";

//避免空指针

try{

msg=dis.readUTF();

}catch(IOExceptione){

System.out.println("---接受消息出现异常---");

release();

}

returnmsg;

}

//发送消息

privatevoidsend(Stringmsg){

try{

dos.writeUTF(msg);

dos.flush();

}catch(IOExceptione){

System.out.println("---发送消息出现异常---");

release();

}

}

//释放资源

privatevoidrelease(){

this.isRunning=false;

//封装

Utils.close(dis,dos,client);

}

//线程体

@Override

publicvoidrun(){

while(isRunning){

Stringmsg=receive();

if(!msg.equals("")){

send(msg);

}

}

}

}

}

工具类Utils:实现Closeable接口,利用可变参数,达到释放资源的作用

示例代码

publicclassUtils{

publicstaticvoidclose(Closeable...targets){

//Closeable是IO流中接口,"..."可变参数

//IO流和Socket都实现了Closeable接口,可以直接用

for(Closeabletarget:targets){

try{

//只要是释放资源就要加入空判断

if(null!=target){

target.close();

}

}catch(Exceptione){

e.printStackTrace();

}

}

}

}

客户端:启用两个线程Send和Receive实现收发信息的分离

示例代码

publicclassThreadMutiClient{

publicstaticvoidmain(String[]args)throwsIOException{

System.out.println("-----客户端开始工作-----");

Socketclient=newSocket("localhost",8888);

newThread(newSend(client)).start();

newThread(newReceive(client)).start();

}

}

使用多线程封装客户的发送端Send类

实现方法:

1、发送消息-send()

2、从控制台获取消息-getStrFromConsole()

3、释放资源-release()

4、线程体-run()

示例代码

publicclassSendimplementsRunnable{

privateBufferedReaderconsole;

privateDataOutputStreamdos;

privateSocketclient;

privatebooleanisRunning;

publicSend(Socketclient){

this.client=client;

console=newBufferedReader(newInputStreamReader(System.in));

//对接控制台

try{

dos=newDataOutputStream(client.getOutputStream());

isRunning=true;

}catch(IOExceptione){

System.out.println("---客户发送端构造时异常---");

release();

}

}

//从控制台获取消息

privateStringgetStrFromConsole(){

try{

returnconsole.readLine();

}catch(IOExceptione){

e.printStackTrace();

return"";

}

}

//发送消息

privatevoidsend(Stringmsg){

try{

dos.writeUTF(msg);

dos.flush();

}catch(IOExceptione){

System.out.println("---客户发送端发送消息异常---");

release();

}

}

@Override

publicvoidrun(){

while(isRunning){

Stringmsg=getStrFromConsole();

if(!msg.equals("")){

send(msg);

}

}

}

//释放资源

privatevoidrelease(){

this.isRunning=false;

Utils.close(dos,client);

}

}

使用多线程封装客户的接收端Receive类

实现方法:

1、接收消息-send

2、释放资源-release()

3、线程体-run()

示例代码

publicclassReceiveimplementsRunnable{

privateDataInputStreamdis;

privateSocketclient;

privatebooleanisRunning;

publicReceive(Socketclient){

this.client=client;

try{

dis=newDataInputStream(client.getInputStream());

isRunning=true;

}catch(IOExceptione){

System.out.println("---客户接收端构造时异常---");

release();

}

}

//接收消息

privateStringreceive(){

Stringmsg="";

try{

msg=dis.readUTF();

}catch(IOExceptione){

System.out.println("---客户接收端接收消息异常---");

release();

}

returnmsg;

}

//释放资源

privatevoidrelease(){

isRunning=false;

Utils.close(dis,client);

}

@Override

publicvoidrun(){

while(isRunning){

Stringmsg=receive();

if(!msg.equals("")){

System.out.println(msg);

}

}

}

}

3.群聊过渡版

目标:加入容器,实现群聊

服务器端

1、建立CopyOnWriteArrayListChannel容器,容器中的元素是Channel客户端代理。要对元素进行修改同时遍历时,推荐使用此容器,避免出问题。

2、实现方法voidsendOthers(Stringmsg)将信息发送给除自己外的其他人。

服务器端实现代码

publicclassChat{

//建立CopyOnWriteArrayListChannel容器

privatestaticCopyOnWriteArrayListChannelall=newCopyOnWriteArrayList();

publicstaticvoidmain(String[]args)throwsIOException{

System.out.println("---服务器开始工作---");

ServerSocketserver=newServerSocket(8888);

while(true){

Socketclient=server.accept();

System.out.println("一个客户端建立了连接");

Channelc=newChannel(client);

all.add(c);

//管理所有的成员

newThread(c).start();

}

}

//一个客户代表一个Channel

staticclassChannelimplementsRunnable{

privateDataInputStreamdis;

privateDataOutputStreamdos;

privateSocketclient;

privatebooleanisRunning;

privateStringname;

publicChannel(Socketclient){

this.client=client;

try{

dis=newDataInputStream(client.getInputStream());

dos=newDataOutputStream(client.getOutputStream());

isRunning=true;

//获取名称

=receive();

//欢迎

this.send("欢迎你的到来");

sendOthers(+"加入群聊",true);

}catch(IOExceptione){

System.out.println("---构造时出现问题---");

release();

}

}

//接收消息

privateStringreceive(){

Stringmsg="";

//避免空指针

try{

msg=dis.readUTF();

}catch(IOExceptione){

System.out.println("---接受消息出现问题---");

release();

}

returnmsg;

}

//发送消息

privatevoidsend(Stringmsg){

try{

dos.writeUTF(msg);

dos.flush();

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论