天天看点

聊天室--java socket

这是我用java socket写的一个简单的聊天室程序,以下是我的设计文档和源代码: ChatRoom 聊天室设计文档

  客户端和服务器界面:

聊天室--java socket

                      客户端       

聊天室--java socket

                     服务器端

ChatRoom 聊天室程序功能简介:

      服务器接受每个连接客户发来的信息,再广播给每个客户。

Server:

       服务器 ChatRoomServer 启动后自动监听默认端口:DEFAULT_PORT 6666等待客户的连接,当有客户连接上来时,在文本域显示连接信息。

       服务器端点击窗口关闭或点击窗体内的退出按钮可以关闭服务器。

Client:

       客户端ChatRoomClient 启动后显示客户端界面:窗体上方有一个“连接”按钮和一个文本筐(文本筐在按钮的右面)。在文本筐中输入服务器地址,再按左边的

“连接”

按钮或按键盘上的”

Enter

”键,连接服务器。如果连接成功将显示连接成功信息,否则将显示连接失败信息。

       连接成功后客户可以在窗体底部

消息

标签右边的

文本筐

中输入要发送的消息,然后点击文本筐右边的

“发送“

按钮或按键盘上的

Enter

键发送信息。

       客户端受到的信息将显示在窗体中部的文本域中。

ChatRoomServer.java ——说明:       // 由于在程序中做了较多注释,所以这里只做简单的叙述: 1 .程序启动是初始化界面、并开始监听:            public ChatRoomServer(){               try{                      jbInit();               }catch(Exception e){                      e.printStackTrace();               }               serverListen();// 服务器开始监听        }     jbInit(){ 、、、、} 初始化界面,注册button1 (退出)按钮和窗口关闭事件。 serverListen(){ 、、、} 打开并监听端口:6666 2 .public void run(){// 接受连接并记录线程信息 、、、、、、        try{               while(true){                      Socket clientSock=serverSock.accept();               CommunicateThread ct=new CommunicateThread(clientSock,this,index);// 创建线程保持连接                             clients.add(ct);// 记录连接信息到clients 数组                             clientsInfor.add("Thread-"+i);// 记录连接名称 、、、、、、、、、        } CommunicateThread ct=new CommunicateThread(clientSock,this,index); 当有连接上来时,创建线程以保持连接。 3 .public void exit(){ 、、、} 退出并关闭seversock 4.class CommunicateThread extends Thread{ 、、、、}// 保持连接线程 5 . class BroadcastThread extends Thread{ 、、、} // 广播线程 6 .// 处理窗口关闭事件的适配器 class ChatFrame_WindowAdapter extends java.awt.event.WindowAdapter{ 、、、} ChatRoomClient.java ——说明: 1.             初始化窗体 public ChatRoomClient(){               try{                      jbInit();               }catch(Exception e){                      e.printStackTrace();               }        }        jbInit(){ 、、、、} 初始化窗体,将button1 (连接)、button2 (发送)注册到ActionListener, 将textField1 (服务器地址) 、textField2 (消息)注册到keyListener ,将窗体注册到WindowListener 2 .  StartConnect (){ 、、、、}// 连接服务器 点击button1 或在textField1 中按“Enter ”键后调用startConnect ()连接服务器并启动线程run (),读取服务器广播来的信息,打印到文本区域。 3 .public void exit(){ 、、、}// 窗口关闭;如果有连接则关闭连接和相关的" 流" 4 .// 文本筐textField1 的键击事件适配器 class textField1_KeyAdapter extends java.awt.event.KeyAdapter{} 5 .// 文本筐textField2 的键击事件适配器 class textField2_KeyAdapter extends java.awt.event.KeyAdapter{} 6 .// 窗口关闭事件适配器 class ChatFrame_WindowAdapter extends java.awt.event.WindowAdapter{}

聊天室服务器端源程序:

package chatserver2;

//Chat Room Server

//this software is designed by Chen Heping(陈和平)

import java.awt.*;

import java.awt.event.*;

import java.io.*;

import java.net.*;

public class ChatRoomServer extends Frame implements Runnable{

 Panel panel;

 ScrollPane sPanel;

 TextArea textArea;

 Button button1;

 //net

 ServerSocket serverSock;

 public final static int DEFAULT_PORT=6666;//默认端口号

 Thread chatAcceptThread;//启动接受连接的线程

 BroadcastThread broadcastThread;//广播thread; run when server is listening

 java.util.Vector clients;//记录连接的线程

 java.util.Vector clientsInfor;//记录连接线程的信息

 public static int index=0;

 public ChatRoomServer(){

  try{

   jbInit();

  }catch(Exception e){

   e.printStackTrace();

  }

  serverListen();//服务器开始监听

 }

 private void jbInit(){//初始化界面

  panel=new Panel();

  sPanel=new ScrollPane();

  textArea=new TextArea("server information:/n");

  button1=new Button("退出");

  sPanel.add(textArea);

  button1.addActionListener(new java.awt.event.ActionListener(){//退出按钮注册

   public void actionPerformed(ActionEvent e){

    button1_actionPerformed(e);

   }

  });

  panel.add(button1);

  this.addWindowListener(new ChatFrame_WindowAdapter(this));//注册到继承了窗口适配器的类

  this.setSize(600,600);

  this.setLayout(new BorderLayout());

  this.add(sPanel,BorderLayout.CENTER);

  this.add(panel,BorderLayout.SOUTH);

  this.show();

 }

 private void button1_actionPerformed(ActionEvent e){

  exit();

 }

 public void processMsg(String str){//

  textArea.append(str);

 }

 private void serverListen(){

  try{

   serverSock=new ServerSocket(DEFAULT_PORT);

  }catch(IOException e){

   processMsg(e.toString());

   processMsg("server failed!/n");

  }

  processMsg("server listening on port:"+DEFAULT_PORT);

  clients=new java.util.Vector();

  clientsInfor=new java.util.Vector();

  chatAcceptThread=new Thread(this);//启动接受连接的线程

  chatAcceptThread.start();

  broadcastThread=new BroadcastThread(this);//广播线程

  broadcastThread.start();

  //还有一个回收无用连接thread 的线程

 }

 public void run(){//接受连接并记录线程信息

  int i=0;

  try{

   while(true){

    Socket clientSock=serverSock.accept();

    CommunicateThread ct=new CommunicateThread(clientSock,this,index);//创建线程保持连接

    clients.add(ct);//record Communicate Thread;

    i++;

    index++;//version2

    clientsInfor.add("Thread-"+i);

    processMsg("Thread-"+i+"join in/n");

   }

  }catch(IOException e){

   processMsg(e.toString());

  } 

 }

 public void exit(){

  broadcastThread.broadcast("Server exit!");

  try{

   serverSock.close();

  }catch(IOException ioe){}

  finally{

   System.exit(0);

  }

 }

 public static void main(String[] args){

  ChatRoomServer chat=new ChatRoomServer();

 }

}

class CommunicateThread extends Thread{//保持连接线程

 protected Socket clientSock;

 protected BufferedReader in=null;

 protected PrintWriter out;

 ChatRoomServer chatFrame;

 boolean isTrue=true;//run()

 java.util.Vector inforStack;

 int index2;//

 public CommunicateThread(Socket Sock,ChatRoomServer cFrame,int index){

  clientSock=Sock;

  chatFrame=cFrame;

  index2=index;

  inforStack=new java.util.Vector();

  try{

   in=new BufferedReader(new InputStreamReader(clientSock.getInputStream()));

   out=new PrintWriter(clientSock.getOutputStream());

  }catch(IOException ei){

   try{

    clientSock.close();

   }catch(IOException ei2){ }

   chatFrame.processMsg(ei.toString());

   return;

  }

  this.start();

 }

 public void run(){

  String infor;

  try{

   while(isTrue){

    infor=in.readLine();

    if(infor.equals("Client exit!")){

     writeInformation(infor);//把信息写到信息栈,以倍广播出去

     stopRun();

    }else if(infor!=null){

     writeInformation(infor);

    }//else break;

    try{

     Thread.sleep(100);//version2

    }catch(InterruptedException ex){}

   }

  }catch(IOException e){ ;}

  finally{

   try{

    in.close();

    out.close();

    clientSock.close();

    chatFrame.clients.remove(index2);//在clients中清除本线程序

    ChatRoomServer.index--;//

   }catch(IOException ei){;}

  }

 }

 public void writeInformation(String infor){//写信息栈

  inforStack.add(infor);

 }

 private void stopRun(){//终止线程

  isTrue=false;

 }

 public void sendInformation(String str){//发送信息

  try{

   out.println(str);

   out.flush();

  }catch(Exception e){;} 

 }  

}

class BroadcastThread extends Thread{//广播线程

 ChatRoomServer chatFrame2;

 java.util.Vector chatClients;//连接线程信息

 java.util.Vector msgStack;//信息栈

 java.util.Vector clientMsg;//记录客户发送的信息

 CommunicateThread comThread1;

 CommunicateThread comThread2;

 String string;//information in inforStack

 String clientName;//client thread name

 String broadcastInfor;//broadcast information=clientName+string;

 public BroadcastThread(ChatRoomServer cFrame){

  chatFrame2=cFrame;

  chatClients=chatFrame2.clients;

  clientMsg=chatFrame2.clientsInfor;

  //this.start();

 }

 public void broadcast(String str){//广播  

  for(int k=0;k<chatClients.size();k++){//send to everyone分别调用每个连接线程,发送信息

   comThread2=(CommunicateThread)chatClients.get(k);

   comThread2.sendInformation(str);

  }

 }

 public void run(){

  try{

   while(true){

    for(int i=0;i<chatClients.size();i++){

     comThread1=(CommunicateThread)chatClients.get(i);

     msgStack=comThread1.inforStack;//得到每个连接的信息栈

     clientName=(String)clientMsg.get(i);//客户名

     //读取每个连接线程的信息栈并把信息发送出去

     for(int j=0;j<msgStack.size();j++){

      string=(String)msgStack.get(j);

      broadcastInfor=clientName+"->"+string;

      broadcast(broadcastInfor);

     }

     //clear the inforStack

     msgStack.removeAllElements();//清除以发送的信息

    }

    try{

     Thread.sleep(100);//version2

    }catch(InterruptedException ex){}

   }

  }catch(Exception e){}

 }

}

//处理窗口关闭事件的适配器

class ChatFrame_WindowAdapter extends java.awt.event.WindowAdapter{

 ChatRoomServer chatFrame;

 public ChatFrame_WindowAdapter(ChatRoomServer chatFrame){

  this.chatFrame=chatFrame;

 }

 public void windowClosing(WindowEvent e){//exit program

  chatFrame.exit();//reference to the method exit() in ChatRoomServer.

 }

}

聊天室客户端源程序:

package chatclient_test;

//ChatRoomClient

//designed by Chen Heping(陈和平)

import java.awt.*;

import java.awt.event.*;

import java.io.*;

import java.net.*;

public class ChatRoomClient extends Frame implements Runnable{

 Panel panel1,panel2;

 Button button1,button2;

 TextField textField1,textField2;

 Label label1;

 TextArea textArea;

 ScrollPane sPanel;

 //net

 PrintWriter out;

 BufferedReader in=null;

 Socket sock;

 public final static int DEFAULT_PORT=6666;

 //create Thread to Read information from Server

 Thread readThread;

 boolean isTrue=true;//thread can go on runing ??

 public ChatRoomClient(){

  try{

   jbInit();

  }catch(Exception e){

   e.printStackTrace();

  }

 }

 public static void main(String[] args){//main method

  ChatRoomClient c=new ChatRoomClient();

  c.show();

 }

 private void jbInit(){//should set size,position and Font of every component

  button1=new Button("连接");// set Font

  button2=new Button("发送");

  textField1=new TextField("input Server address here!");

  textField2=new TextField("input Message here and send to server");

  label1=new Label("消息:");

  panel1=new Panel();

  panel2=new Panel();

  sPanel=new ScrollPane();

  textArea=new TextArea();

  //panel1 

  //press button1: 连接 to connect the client to server

  button1.addActionListener(new java.awt.event.ActionListener(){

   public void actionPerformed(ActionEvent e){

    button1_actionPerformed(e);

   }

  });

  //textField1:for input the address of server;be registered to KeyListener.

  //press key:Enter to connect the client to server

  textField1.addKeyListener(new textField1_KeyAdapter(this));//java.awt.event.KeyAdapter()

  panel1.add(button1);

  panel1.add(textField1);

  //sPanel  ScrollPane

  sPanel.add(textArea);

  //panel2

  //press button2: 发送 to send message

  button2.addActionListener(new java.awt.event.ActionListener(){

   public void actionPerformed(ActionEvent e){

    button2_actionPerformed(e);

   }

  });

  //textField2:for input message;be registered to KeyListener.

  //press key:Enter to send message

  textField2.addKeyListener(new textField2_KeyAdapter(this));

  panel2.add(label1);

  panel2.add(textField2);

  panel2.add(button2);

  //frame

  this.addWindowListener(new ChatFrame_WindowAdapter(this));//frame is registered to WindowListener

  this.setLayout(new BorderLayout());

  this.setSize(500,400);

  this.add(panel1,BorderLayout.NORTH);

  this.add(sPanel,BorderLayout.CENTER);

  this.add(panel2,BorderLayout.SOUTH);

  //this.show()

 }

 public void startConnect(){//开始连接

  try{

   sock=new Socket(textField1.getText(),DEFAULT_PORT);

   if(sock!=null){//connection successed

    processMsg("Connect successfully!");

   }

   in=new BufferedReader(new InputStreamReader(sock.getInputStream()));

   out=new PrintWriter(sock.getOutputStream());

  }catch(IOException ex){

   processMsg(ex.toString());

   processMsg("Connect failed!");

  }

  readThread=new Thread(this);

  readThread.start(); 

 }

 //public void endConnect(){//close IOstream

 public void sendInformation(){

  out.println(textField2.getText());

  out.flush();

 }

 private void button1_actionPerformed(ActionEvent e){//连接按钮

  startConnect();

 }

 private void button2_actionPerformed(ActionEvent e){//发送按钮

  sendInformation();

 }

 public void stopRun(){//to stop the running thread

  isTrue=false;

 } 

 public void processMsg(String msg){//客户端处理消息

  textArea.append(msg);

  textArea.append("/n");

 }

 public void run(){

  String msg;

  isTrue=true;

  while(isTrue){

   try{

    msg=in.readLine();

    if(msg.equals("Server exit!")){//server exit

     processMsg(msg);

     stopRun();//终止线程

    }else if(msg!=null){

     processMsg(msg);

    }

    Thread.sleep(1000);    

   }catch(IOException e){

    processMsg(e.toString());

   }catch(InterruptedException ei){

    processMsg(ei.toString());

   }

  }

  //endConnect();

  try{//服务器退出关闭连接和相关的"流"

   sock.close();

   in.close();

   out.close();

  }catch(IOException ioe){} 

 }

 public void exit(){//窗口关闭;如果有连接则关闭连接和相关的"流"

  try{//send "Client exit!" to Server!

   out.println("Client exit!");

   out.flush();

  }catch(Exception exc){}

  //endConnect();

  try{//close IOstream

   sock.close();

   in.close();

   out.close();

  }catch(IOException ioe){}

  finally{ 

   System.exit(0);

  }

 }

}

//文本筐textField1的键击事件适配器

class textField1_KeyAdapter extends java.awt.event.KeyAdapter{

 ChatRoomClient chatFrame;

 public textField1_KeyAdapter(ChatRoomClient chatFrame){

  this.chatFrame=chatFrame;

 }

 public void keyPressed(KeyEvent e){//输入的是enter,开始连接!

  int j=e.getKeyCode();

  if(j==e.VK_ENTER){

   chatFrame.startConnect();

  }

 }

}

//文本筐textField2的键击事件适配器

class textField2_KeyAdapter extends java.awt.event.KeyAdapter{

 ChatRoomClient chatFrame;

 public textField2_KeyAdapter(ChatRoomClient chatFrame){

  this.chatFrame=chatFrame;

 }

 public void keyPressed(KeyEvent e){//键击Enter键,发送信息!

  int j=e.getKeyCode();

  if(j==e.VK_ENTER){

   chatFrame.sendInformation();

  }

 }

}

//窗口关闭事件适配器

class ChatFrame_WindowAdapter extends java.awt.event.WindowAdapter{

 ChatRoomClient chatFrame;

 public ChatFrame_WindowAdapter(ChatRoomClient chatFrame){

  this.chatFrame=chatFrame;

 }

 public void windowClosing(WindowEvent e){//exit program

  chatFrame.exit();//reference to the method exit() in ChatRoomClient.

 }

}