网页版在线聊天java Socket实现
本文为大家分享了一个满足在线网页交流需求的实例,由于javaSocket实现的网页版在线聊天功能,供大家参考,具体内容如下
实现步骤:
1、使用awt组件和socket实现简单的单客户端向服务端持续发送消息;
2、结合线程,实现多客户端连接服务端发送消息;
3、实现服务端转发客户端消息至所有客户端,同时在客户端显示;
4、把awt组件生成的窗口界面改成前端jsp或者html展示的界面,javasocket实现的客户端改为前端技术实现。
这里首先实现第一步的简单功能,难点在于:
1、没有用过awt组件,没有用过java相关的监听事件;
2、长时间没有使用socket进行客户端和服务端的交互,并且没有真正进行过cs结构的开发。
实现功能的代码:
在线聊天客户端:
1、生成图形窗口界面轮廓
2、为轮廓添加关闭事件
3、在轮廓中加入输入区域和内容展示区域
4、为输入区域添加回车事件
5、建立服务端连接并发送数据
packagechat.chat;
importjava.awt.BorderLayout;
importjava.awt.Frame;
importjava.awt.TextArea;
importjava.awt.TextField;
importjava.awt.event.ActionEvent;
importjava.awt.event.ActionListener;
importjava.awt.event.WindowAdapter;
importjava.awt.event.WindowEvent;
importjava.io.DataOutputStream;
importjava.io.IOException;
importjava.net.Socket;
importjava.net.UnknownHostException;
/**
*在线聊天客户端1、生成图形窗口界面轮廓2、为轮廓添加关闭事件3、在轮廓中加入输入区域和内容展示区域4、为输入区域添加回车事件
*5、建立服务端连接并发送数据
*
*@authortuzongxun123
*
*/
publicclassChatClientextendsFrame{
//用户输入区域
privateTextFieldtfTxt=newTextField();
//内容展示区域
privateTextAreatarea=newTextArea();
privateSocketsocket=null;
//数据输出流
privateDataOutputStreamdataOutputStream=null;
publicstaticvoidmain(String[]args){
newChatClient().launcFrame();
}
/**
*建立一个简单的图形化窗口
*
*@author:tuzongxun
*@Title:launcFrame
*@param
*@returnvoid
*@dateMay18,20169:57:00AM
*@throws
*/
publicvoidlauncFrame(){
setLocation(300,200);
this.setSize(200,400);
add(tfTxt,BorderLayout.SOUTH);
add(tarea,BorderLayout.NORTH);
pack();
//监听图形界面窗口的关闭事件
this.addWindowListener(newWindowAdapter(){
@Override
publicvoidwindowClosing(WindowEvente){
System.exit(0);
disConnect();
}
});
tfTxt.addActionListener(newTFLister());
setVisible(true);
connect();
}
/**
*连接服务器
*
*@author:tuzongxun
*@Title:connect
*@param
*@returnvoid
*@dateMay18,20169:56:49AM
*@throws
*/
publicvoidconnect(){
try{
//新建服务端连接
socket=newSocket("127.0.0.1",8888);
//获取客户端输出流
dataOutputStream=newDataOutputStream(socket.getOutputStream());
System.out.println("连上服务端");
}catch(UnknownHostExceptione){
e.printStackTrace();
}catch(IOExceptione){
e.printStackTrace();
}
}
/**
*关闭客户端资源
*
*@author:tuzongxun
*@Title:disConnect
*@param
*@returnvoid
*@dateMay18,20169:57:46AM
*@throws
*/
publicvoiddisConnect(){
try{
dataOutputStream.close();
socket.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
/**
*向服务端发送消息
*
*@author:tuzongxun
*@Title:sendMessage
*@param@paramtext
*@returnvoid
*@dateMay18,20169:57:56AM
*@throws
*/
privatevoidsendMessage(Stringtext){
try{
dataOutputStream.writeUTF(text);
dataOutputStream.flush();
}catch(IOExceptione1){
e1.printStackTrace();
}
}
/**
*图形窗口输入区域监听回车事件
*
*@authortuzongxun123
*
*/
privateclassTFListerimplementsActionListener{
@Override
publicvoidactionPerformed(ActionEvente){
Stringtext=tfTxt.getText().trim();
tarea.setText(text);
tfTxt.setText("");
//回车后发送数据到服务器
sendMessage(text);
}
}
}
服务端:
packagechat.chat;
importjava.io.DataInputStream;
importjava.io.EOFException;
importjava.io.IOException;
importjava.net.BindException;
importjava.net.ServerSocket;
importjava.net.Socket;
/**
*java使用socket和awt组件简单实现在线聊天功能服务端可以实现一个客户端连接后不断向服务端发送消息
*但不支持多个客户端同时连接,原因在于代码中获得客户端连接后会一直循环监听客户端输入,造成阻塞
*以至于服务端无法二次监听另外的客户端,如要实现,需要使用异步或者多线程
*
*@authortuzongxun123
*
*/
publicclassChatServer{
publicstaticvoidmain(String[]args){
//是否成功启动服务端
booleanisStart=false;
//服务端socket
ServerSocketss=null;
//客户端socket
Socketsocket=null;
//服务端读取客户端数据输入流
DataInputStreamdataInputStream=null;
try{
//启动服务器
ss=newServerSocket(8888);
}catch(BindExceptione){
System.out.println("端口已在使用中");
//关闭程序
System.exit(0);
}catch(Exceptione){
e.printStackTrace();
}
try{
isStart=true;
while(isStart){
booleanisConnect=false;
//启动监听
socket=ss.accept();
System.out.println("oneclientconnect");
isConnect=true;
while(isConnect){
//获取客户端输入流
dataInputStream=newDataInputStream(
socket.getInputStream());
//读取客户端传递的数据
Stringmessage=dataInputStream.readUTF();
System.out.println("客户端说:"+message);
}
}
}catch(EOFExceptione){
System.out.println("clientclosed!");
}catch(Exceptione){
e.printStackTrace();
}finally{
//关闭相关资源
try{
dataInputStream.close();
socket.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
}
继续,在单客户端连接的基础上,这里第二步需要实现多客户端的连接,也就需要使用到线程。每当有一个新的客户端连接上来,服务端便需要新启动一个线程进行处理,从而解决之前的循环读取中造成阻塞的问题。
写线程通常有两种方法,集成Thread或者实现runnable接口,原则上是能实现runnable的情况下就不继承,因为实现接口的方式更加灵活。
客户端代码相较之前没有变化,变得是服务端,因此这里便只贴出服务端代码:
java使用socket和awt组件以及多线程简单实现在线聊天功能服务端:
实现多个客户端连接后不断向服务端发送消息,相对于第一个版本,重点在于使用了多线程。服务端还未实现转发功能,客户端图形窗口中只能看到自己输入的信息,不能看到其他客户端发送的消息。
packagechat.chat;
importjava.io.DataInputStream;
importjava.io.EOFException;
importjava.io.IOException;
importjava.net.BindException;
importjava.net.ServerSocket;
importjava.net.Socket;
importjava.net.SocketException;
/**
**
*@authortuzongxun123
*
*/
publicclassChatServer{
publicstaticvoidmain(String[]args){
newChatServer().start();
}
//是否成功启动服务端
privatebooleanisStart=false;
//服务端socket
privateServerSocketss=null;
//客户端socket
privateSocketsocket=null;
publicvoidstart(){
try{
//启动服务器
ss=newServerSocket(8888);
}catch(BindExceptione){
System.out.println("端口已在使用中");
//关闭程序
System.exit(0);
}catch(Exceptione){
e.printStackTrace();
}
try{
isStart=true;
while(isStart){
//启动监听
socket=ss.accept();
System.out.println("oneclientconnect");
//启动客户端线程
Clientclient=newClient(socket);
newThread(client).start();
}
}catch(Exceptione){
e.printStackTrace();
}finally{
//关闭服务
try{
ss.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
/**
*客户端线程
*
*@authortuzongxun123
*
*/
classClientimplementsRunnable{
//客户端socket
privateSocketsocket=null;
//客户端输入流
privateDataInputStreamdataInputStream=null;
privatebooleanisConnect=false;
publicClient(Socketsocket){
this.socket=socket;
try{
isConnect=true;
//获取客户端输入流
dataInputStream=newDataInputStream(socket.getInputStream());
}catch(IOExceptione){
e.printStackTrace();
}
}
@Override
publicvoidrun(){
isConnect=true;
try{
while(isConnect){
//读取客户端传递的数据
Stringmessage=dataInputStream.readUTF();
System.out.println("客户端说:"+message);
}
}catch(EOFExceptione){
System.out.println("clientclosed!");
}catch(SocketExceptione){
System.out.println("ClientisClosed!!!!");
}catch(Exceptione){
e.printStackTrace();
}finally{
//关闭相关资源
try{
dataInputStream.close();
socket.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
}
}
上面主要介绍了利用线程使服务端实现了能够接收多客户端请求的功能,这里便需要客户端接收多客户端消息的同时还能把消息转发到每个连接的客户端,并且客户端要能在内容显示区域显示出来,从而实现简单的在线群聊。
在实现客户端转发,无非就是增加输出流;而之前客户端都只发不收,这里也需要更改客户端达到循环接收服务端消息的目的,因此也需要实现多线程。
在实现这个功能的时候,偶然想起随机生成验证码的功能,于是也灵机一动随机给每个客户端生成一个名字,从而在输出的时候看起来更加像是群聊,不仅有消息输出,还能看到是谁。
实现这些功能之后,基本上就可以几个人同时在线群聊了,因为代码中有main方法,因此可以把服务端和客户端都打成可执行jar包,可参考我的另一篇博文:使用eclipse创建java程序可执行jar包
之后在桌面双击相应的jar文件启动服务端和客户端即可,不需要再依赖eclipse运行。
修改后的客户端代码如下:
packagechat.chat;
importjava.awt.BorderLayout;
importjava.awt.Frame;
importjava.awt.TextArea;
importjava.awt.TextField;
importjava.awt.event.ActionEvent;
importjava.awt.event.ActionListener;
importjava.awt.event.WindowAdapter;
importjava.awt.event.WindowEvent;
importjava.io.DataInputStream;
importjava.io.DataOutputStream;
importjava.io.IOException;
importjava.net.Socket;
importjava.net.UnknownHostException;
importjava.util.Random;
/**
*在线聊天客户端步骤:
*1、生成图形窗口界面轮廓
*2、为轮廓添加关闭事件
*3、在轮廓中加入输入区域和内容展示区域
*4、为输入区域添加回车事件
*5、建立服务端连接并发送数据
*
*@authortuzongxun123
*
*/
publicclassChatClientextendsFrame{
/**
*
*/
privatestaticfinallongserialVersionUID=1L;
//用户输入区域
privateTextFieldtfTxt=newTextField();
//内容展示区域
privateTextAreatarea=newTextArea();
privateSocketsocket=null;
//数据输出流
privateDataOutputStreamdataOutputStream=null;
//数据输入流
privateDataInputStreamdataInputStream=null;
privatebooleanisConnect=false;
ThreadtReceive=newThread(newReceiveThread());
Stringname="";
publicstaticvoidmain(String[]args){
ChatClientchatClient=newChatClient();
chatClient.createName();
chatClient.launcFrame();
}
/**
*建立一个简单的图形化窗口
*
*@author:tuzongxun
*@Title:launcFrame
*@param
*@returnvoid
*@dateMay18,20169:57:00AM
*@throws
*/
publicvoidlauncFrame(){
setLocation(300,200);
this.setSize(200,400);
add(tfTxt,BorderLayout.SOUTH);
add(tarea,BorderLayout.NORTH);
//根据窗口里面的布局及组件的preferedSize来确定frame的最佳大小
pack();
//监听图形界面窗口的关闭事件
this.addWindowListener(newWindowAdapter(){
@Override
publicvoidwindowClosing(WindowEvente){
System.exit(0);
disConnect();
}
});
tfTxt.addActionListener(newTFLister());
//设置窗口可见
setVisible(true);
connect();
//启动接受消息的线程
tReceive.start();
}
/**
*连接服务器
*
*@author:tuzongxun
*@Title:connect
*@param
*@returnvoid
*@dateMay18,20169:56:49AM
*@throws
*/
publicvoidconnect(){
try{
//新建服务端连接
socket=newSocket("127.0.0.1",8888);
//获取客户端输出流
dataOutputStream=newDataOutputStream(socket.getOutputStream());
dataInputStream=newDataInputStream(socket.getInputStream());
System.out.println("连上服务端");
isConnect=true;
}catch(UnknownHostExceptione){
e.printStackTrace();
}catch(IOExceptione){
e.printStackTrace();
}
}
//生成随机的客户端名字
publicvoidcreateName(){
String[]str1={"a","b","c","d","e","f","g","h","i","j",
"k","l","m","n","o","p","q","r","s","t","u","v",
"w","x","y","z","1","2","3","4","5","6","7","8",
"9","0","A","B","C","D","E","F","G","H","I","J",
"K","L","M","N","O","P","Q","R","S","T","U","V",
"W","X","Y","Z"};
Randomran=newRandom();
for(inti=0;i<6;i++){
//longnum=Math.round(Math.random()*(str1.length-0)+0);
//intn=(int)num;
intn=ran.nextInt(str1.length);
if(n<str1.length){
Stringstr=str1[n];
name=name+str;
System.out.println(name);
}else{
i--;
continue;
}
}
this.setTitle(name);
}
/**
*关闭客户端资源
*
*@author:tuzongxun
*@Title:disConnect
*@param
*@returnvoid
*@dateMay18,20169:57:46AM
*@throws
*/
publicvoiddisConnect(){
try{
isConnect=false;
//停止线程
tReceive.join();
}catch(InterruptedExceptione){
e.printStackTrace();
}finally{
try{
if(dataOutputStream!=null){
dataOutputStream.close();
}
if(socket!=null){
socket.close();
socket=null;
}
}catch(IOExceptione){
e.printStackTrace();
}
}
}
/**
*向服务端发送消息
*
*@author:tuzongxun
*@Title:sendMessage
*@param@paramtext
*@returnvoid
*@dateMay18,20169:57:56AM
*@throws
*/
privatevoidsendMessage(Stringtext){
try{
dataOutputStream.writeUTF(name+":"+text);
dataOutputStream.flush();
}catch(IOExceptione1){
e1.printStackTrace();
}
}
/**
*图形窗口输入区域监听回车事件
*
*@authortuzongxun123
*
*/
privateclassTFListerimplementsActionListener{
@Override
publicvoidactionPerformed(ActionEvente){
Stringtext=tfTxt.getText().trim();
//清空输入区域信息
tfTxt.setText("");
//回车后发送数据到服务器
sendMessage(text);
}
}
privateclassReceiveThreadimplementsRunnable{
@Override
publicvoidrun(){
try{
while(isConnect){
Stringmessage=dataInputStream.readUTF();
System.out.println(message);
Stringtxt=tarea.getText();
if(txt!=null&&!"".equals(txt.trim())){
message=tarea.getText()+"\n"+message;
}
tarea.setText(message);
}
}catch(IOExceptione){
e.printStackTrace();
}
}
}
}
修改后的服务端代码如下:
packagechat.chat;
importjava.io.DataInputStream;
importjava.io.DataOutputStream;
importjava.io.EOFException;
importjava.io.IOException;
importjava.net.BindException;
importjava.net.ServerSocket;
importjava.net.Socket;
importjava.net.SocketException;
importjava.util.ArrayList;
importjava.util.List;
/**
*java使用socket和awt组件以及多线程简单实现在线聊天功能服务端:
*实现服务端把接收到的客户端信息转发到所有连接的客户端,并且让客户端读取到这些信息并显示在内容显示区域中。
*
*@authortuzongxun123
*
*/
publicclassChatServer{
publicstaticvoidmain(String[]args){
newChatServer().start();
}
//是否成功启动服务端
privatebooleanisStart=false;
//服务端socket
privateServerSocketss=null;
//客户端socket
privateSocketsocket=null;
//保存客户端集合
List<Client>clients=newArrayList<Client>();
publicvoidstart(){
try{
//启动服务器
ss=newServerSocket(8888);
}catch(BindExceptione){
System.out.println("端口已在使用中");
//关闭程序
System.exit(0);
}catch(Exceptione){
e.printStackTrace();
}
try{
isStart=true;
while(isStart){
//启动监听
socket=ss.accept();
System.out.println("oneclientconnect");
//启动客户端线程
Clientclient=newClient(socket);
newThread(client).start();
clients.add(client);
}
}catch(Exceptione){
e.printStackTrace();
}finally{
//关闭服务
try{
ss.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
/**
*客户端线程
*
*@authortuzongxun123
*
*/
privateclassClientimplementsRunnable{
//客户端socket
privateSocketsocket=null;
//客户端输入流
privateDataInputStreamdataInputStream=null;
//客户端输出流
privateDataOutputStreamdataOutputStream=null;
privatebooleanisConnect=false;
publicClient(Socketsocket){
this.socket=socket;
try{
isConnect=true;
//获取客户端输入流
dataInputStream=newDataInputStream(socket.getInputStream());
//获取客户端输出流
dataOutputStream=newDataOutputStream(
socket.getOutputStream());
}catch(IOExceptione){
e.printStackTrace();
}
}
/**
*向客户端群发(转发)数据
*
*@author:tuzongxun
*@Title:sendMessageToClients
*@param@parammessage
*@returnvoid
*@dateMay18,201611:28:10AM
*@throws
*/
publicvoidsendMessageToClients(Stringmessage){
try{
dataOutputStream.writeUTF(message);
}catch(SocketExceptione){
}catch(IOExceptione){
e.printStackTrace();
}
}
@Override
publicvoidrun(){
isConnect=true;
Clientc=null;
try{
while(isConnect){
//读取客户端传递的数据
Stringmessage=dataInputStream.readUTF();
System.out.println("客户端说:"+message);
for(inti=0;i<clients.size();i++){
c=clients.get(i);
c.sendMessageToClients(message);
}
}
}catch(EOFExceptione){
System.out.println("clientclosed!");
}catch(SocketExceptione){
if(c!=null){
clients.remove(c);
}
System.out.println("ClientisClosed!!!!");
}catch(Exceptione){
e.printStackTrace();
}finally{
//关闭相关资源
try{
if(dataInputStream!=null){
dataInputStream.close();
}
if(socket!=null){
socket.close();
socket=null;
}
}catch(IOExceptione){
e.printStackTrace();
}
}
}
}
}
就先为大家介绍到这里,之后如果有新的内容再为大家进行更新。
关于网页在线聊天功能的实现大,大家还可以参考一下几篇文章进行学习:
java实现一个简单TCPSocket聊天室功能分享
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家可以继续关注毛票票的更多精彩内容。