局域网聊天程序.docx
《局域网聊天程序.docx》由会员分享,可在线阅读,更多相关《局域网聊天程序.docx(27页珍藏版)》请在冰豆网上搜索。
局域网聊天程序
一、题目
局域网聊天程序的设计与实现
该程序实现局域网内的聊天功能,包括服务器端程序和客户端程序两部分。
客户端程序:
可连接到服务器,并将消息发送到服务器端和接受服务器端发送来的信息。
服务器端程序:
可将消息发送到客户端和接受客户端发送来的信息
二、需求分析
Server(服务器端):
服务器ChatRoomServer启动后自动监听默认端口:
DEFAULT_PORT6666等待客户的连接,当有客户连接上来时,在文本域显示连接信息。
服务器端点击窗口关闭或点击窗体内的退出按钮可以关闭服务器。
Client(客户端):
客户端ChatRoomClient启动后显示客户端界面:
窗体上方有一个“连接”按钮和一个文本筐(文本筐在按钮的右面)。
在文本筐中输入服务器地址,再按左边的“连接”按钮或按键盘上的”Enter”键,连接服务器。
如果连接成功将显示连接成功信息,否则将显示连接失败信息。
连接成功后客户可以在窗体底部消息标签右边的文本筐中输入要发送的消息,然后点击文本筐右边的“发送“按钮或按键盘上的”Enter“键发送信息。
三、概要设计
导入声明:
importpackage
①服务器
Chatroomserver类:
声明成员变量,成员方法,构造函数
ChatFrame_WindowAdapter:
处理窗口关闭事件的适配器
BroadcastThread():
广播线程
communicateTread():
保持连接线程
jbInit():
初始化界面
导入声明:
importpackage
客户端
ChatRoomClient类:
声明成员变量,成员方法,构造函数
文本筐textField1的键击事件适配器
:
textField1_KeyAdapter
//窗口关闭事件适配器
classChatFrame_WindowAdapter
文本筐textField2的键击事件适配器
:
textField2_KeyAdapter
jbInit():
初始化界面
startConnect():
开始连接
stopRun():
终止线程
四、详细设计
①服务器
1、程序启动是初始化界面、并开始监听:
publicChatRoomServer(){
try{
jbInit();
}catch(Exceptione){
e.printStackTrace();
}
serverListen();//服务器开始监听
}
jbInit(){、、、、}初始化界面,注册button1(退出)按钮和窗口关闭事件。
serverListen(){、、、}打开并监听端口:
6666,
2.publicvoidrun(){//接受连接并记录线程信息
、、、、、、
try{
while(true){
clientSock=serverSock.accept();
CommunicateThreadct=newCommunicateThread(clientSock,this,index);//创建线程保持连接
clients.add(ct);//记录连接信息到clients数组
clientsInfor.add("Thread-"+i);//记录连接名称
、、、、、、、、、
}
CommunicateThreadct=newCommunicateThread(clientSock,this,index);
当有连接上来时,创建线程以保持连接。
3.publicvoidexit(){、、、}
退出并关闭seversock
4.classCommunicateThreadextendsThread{、、、、}//保持连接线程
5.classBroadcastThreadextendsThread{、、、}//广播线程
6.//处理窗口关闭事件的适配器
classChatFrame_WindowAdapterextendsjava.awt.event.WindowAdapter{、、、}
windowClosing:
退出程序
构造函数
Run():
读取每个线程的信息并发送出去
Broadcast():
广播信息
构造函数
ChatFrame_WindowAdapter:
处理窗口关闭事件的适配器
BroadcastThread():
广播线程
Stoprun():
终止线程
Run():
连接线程
构造函数
communicateTread():
保持连接线程
Exit():
退出
Run():
接受线程并记录信息
jbInit():
初始化界面
客户端ChatRoomClient
1. 初始化窗体
publicChatRoomClient(){
try{
jbInit();
}catch(Exceptione){
e.printStackTrace();
}
}
jbInit(){、、、、}初始化窗体,将button1(连接)、button2(发送)注册到ActionListener,将textField1(服务器地址)、textField2(消息)注册到keyListener,将窗体注册到WindowListener。
2. StartConnect(){、、、、}//连接服务器
点击button1或在textField1中按“Enter”键后调用startConnect()连接服务器并启动线程run(),读取服务器广播来的信息,打印到文本区域。
3.publicvoidexit(){、、、}//窗口关闭;如果有连接则关闭连接和相关的"流"
4.//文本筐textField1的键击事件适配器
classtextField1_KeyAdapterextendsjava.awt.event.KeyAdapter{}
5.//文本筐textField2的键击事件适配器
classtextField2_KeyAdapterextendsjava.awt.event.KeyAdapter{}
6.//窗口关闭事件适配器
stopRun():
终止线程
startConnect():
开始连接
jbInit():
初始化界面
classChatFrame_WindowAdapterextendsjava.awt.event.WindowAdapter{}
五、调试分析
在第一次调试时,客户端老是联不上,经分析得,服务器端不能接收信息
当客户端按“注册登录”,客户端服务器端均无反应,说明此按钮没有动作
在界面进行调试时,我觉得界面不够好,就换了颜色,加了标题,输出全用汉字。
在发送消息时,有的时候客户1的消息不能被客户2接到,说明线程有的时候不能连接上,在重新查看线程连接。
六、测试结果
七、源程序清单
服务器
importjava.awt.*;
importjava.awt.event.*;
importjava.io.*;
import.*;
importjavax.swing.*;
classChatRoomServerextendsFrameimplementsRunnable
{
Panelpanel;
ScrollPanesPanel;
TextAreatextArea;
Buttonbutton1;
//net
ServerSocketserverSock;
publicfinalstaticintDEFAULT_PORT=6666;//默认端口号
ThreadchatAcceptThread;//启动接受连接的线程
BroadcastThreadbroadcastThread;//广播thread
java.util.Vectorclients;//记录连接的线程
java.util.VectorclientsInfor;//记录连接线程的信息
publicstaticintindex=0;
publicChatRoomServer(){
try{
jbInit();
this.setTitle("这是聊天器服务端");
}catch(Exceptione){
e.printStackTrace();
}
serverListen();//服务器开始监听
}
privatevoidjbInit(){//初始化界面
panel=newPanel();
sPanel=newScrollPane();
textArea=newTextArea("服务器信息如下:
\n");
button1=newButton("退出");
button1.setBackground(Color.red);
textArea.setBackground(Color.pink);
sPanel.add(textArea);
button1.addActionListener(newjava.awt.event.ActionListener(){//退出按钮注册
publicvoidactionPerformed(ActionEvente){
button1_actionPerformed(e);
}
});
panel.add(button1);
this.addWindowListener(newChatFrame_WindowAdapter(this));//注册到继承了窗口适配器的类
this.setSize(800,700);
this.setBackground(Color.white);
this.setLayout(newBorderLayout());
this.add(sPanel,BorderLayout.CENTER);
this.add(panel,BorderLayout.NORTH);
this.show();
}
privatevoidbutton1_actionPerformed(ActionEvente){
exit();
}
publicvoidprocessMsg(Stringstr){//
textArea.append(str);
}
privatevoidserverListen(){
try{
serverSock=newServerSocket(DEFAULT_PORT);
}catch(IOExceptione){
processMsg(e.toString());
processMsg("serverfailed!
\n");
}
processMsg("客户端端口是:
"+DEFAULT_PORT+"\n");
clients=newjava.util.Vector();
clientsInfor=newjava.util.Vector();
chatAcceptThread=newThread(this);//启动接受连接的线程
chatAcceptThread.start();
broadcastThread=newBroadcastThread(this);//广播线程
broadcastThread.start();
//还有一个回收无用连接thread的线程
}
publicvoidrun(){//接受连接并记录线程信息
inti=0;
try{
while(true){
SocketclientSock=serverSock.accept();
CommunicateThreadct=newCommunicateThread(clientSock,this,index);//创建线程保持连接
clients.add(ct);//recordCommunicateThread;
i++;
index++;//version2
clientsInfor.add("Thread-"+i);
processMsg("客户-"+i+"上线了\n");
}
}catch(IOExceptione){
processMsg(e.toString());
}
}
publicvoidexit(){
broadcastThread.broadcast("Serverexit!
");
try{
serverSock.close();
}catch(IOExceptionioe){}
finally{
System.exit(0);
}
}
publicstaticvoidmain(String[]args){
ChatRoomServerchat=newChatRoomServer();
}
}
classCommunicateThreadextendsThread{//保持连接线程
protectedSocketclientSock;
protectedBufferedReaderin=null;
protectedPrintWriterout;
ChatRoomServerchatFrame;
booleanisTrue=true;//run()
java.util.VectorinforStack;
intindex2;//
publicCommunicateThread(SocketSock,ChatRoomServercFrame,intindex){
clientSock=Sock;
chatFrame=cFrame;
index2=index;
inforStack=newjava.util.Vector();
try{
in=newBufferedReader(newInputStreamReader(clientSock.getInputStream()));
out=newPrintWriter(clientSock.getOutputStream());
}catch(IOExceptionei){
try{
clientSock.close();
}catch(IOExceptionei2){}
chatFrame.processMsg(ei.toString());
return;
}
this.start();
}
publicvoidrun(){
Stringinfor;
try{
while(isTrue){
infor=in.readLine();
if(infor.equals("Clientexit!
")){
writeInformation(infor);//把信息写到信息栈,以倍广播出去
stopRun();
}elseif(infor!
=null){
writeInformation(infor);
}//elsebreak;
try{
Thread.sleep(100);//version2
}catch(InterruptedExceptionex){}
}
}catch(IOExceptione){;}
finally{
try{
in.close();
out.close();
clientSock.close();
chatFrame.clients.remove(index2);//在clients中清除本线程序
ChatRoomServer.index--;//
}catch(IOExceptionei){;}
}
}
publicvoidwriteInformation(Stringinfor){//写信息栈
inforStack.add(infor);
}
privatevoidstopRun(){//终止线程
isTrue=false;
}
publicvoidsendInformation(Stringstr){//发送信息
try{
out.println(str);
out.flush();
}catch(Exceptione){;}
}
}
classBroadcastThreadextendsThread{//广播线程
ChatRoomServerchatFrame2;
java.util.VectorchatClients;//连接线程信息
java.util.VectormsgStack;//信息栈
java.util.VectorclientMsg;//记录客户发送的信息
CommunicateThreadcomThread1;
CommunicateThreadcomThread2;
Stringstring;//informationininforStack
StringclientName;//clientthreadname
StringbroadcastInfor;//broadcastinformation=clientName+string;
publicBroadcastThread(ChatRoomServercFrame){
chatFrame2=cFrame;
chatClients=chatFrame2.clients;
clientMsg=chatFrame2.clientsInfor;
//this.start();
}
publicvoidbroadcast(Stringstr){//广播
for(intk=0;kcomThread2=(CommunicateThread)chatClients.get(k);
comThread2.sendInformation(str);
}
}
publicvoidrun(){
try{
while(true){
for(inti=0;icomThread1=(CommunicateThread)chatClients.get(i);
msgStack=comThread1.inforStack;//得到每个连接的信息栈
clientName=(String)clientMsg.get(i);//客户名
//读取每个连接线程的信息栈并把信息发送出去
for(intj=0;jstring=(String)msgStack.get(j);
broadcastInfor=clientName+"->"+string;
broadcast(broadcastInfor);
}
//cleartheinforStack
msgStack.removeAllElements();//清除以发送的信息
}
try{
Thread.sleep(100);//version2
}catch(InterruptedExceptionex){}
}
}catch(Exceptione){}
}
}
//处理窗口关闭事件的适配器
classChatFrame_WindowAdapterextendsjava.awt.event.WindowAdapter{ChatRoomServerchatFrame;
publicChatFrame_WindowAdapter(ChatRoomServerchatFrame){
this.chatFrame=chatFrame;
}
publicvoidwindowClosing(WindowEvente){//exitprogram
chatFrame.exit();//referencetothemethodexit()inChatRoomServer.
}
}客户端
importjava.awt.*;
importjava.awt.event.*;
importjava.io.*;
import.*;
classChatRoomClientextendsFrameimplementsRunnable{
Panelpanel1,panel2;
Buttonbutton1,button2;
TextFieldtextField1,textField2;
Labellabel1;
TextAreatextArea;
ScrollPanesPanel;
PrintWriterout;
BufferedReaderin=null;
Socketsock;
publicfinalstaticintDEFAULT_PORT=6666;
//创线程
ThreadreadThread;
booleanisTrue=true;//threadcangoonruning
publicChatRoomClient(){
try{
jbInit();
this.setTitle("这是聊天器客户端");
}catch(Exceptione){
e.printStackTrace();
}
}
publicstaticvoidmain(String[]args){