java Scoket的c\s结构聊天室

客户端端代码:

package javaSocket;
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class SocketClient {
 private JFrame frame;
 private JTextArea area;
 private JLabel label;
 private JTextField field;
 private JButton button;
 private Socket s;
 private String userName;
 private BufferedReader br;
 private PrintWriter pw;
 private static final Log log = LogFactory.getLog(SocketClient.class);
 
 public SocketClient(){
  frame=new JFrame("顺网研发中心聊天室");
  area=new JTextArea(15,30);
  label=new JLabel();
  field=new JTextField(30);
  button=new JButton("发送");
  createConnection();
  init();
  addEventHandler();
 }
 
 private void createConnection(){
  do {
   String hostName = JOptionPane.showInputDialog(frame, "请输入服务器地址:");
   String port = JOptionPane.showInputDialog(frame, "请输入端口号:");
   try {
    s = new Socket(hostName, Integer.parseInt(port));
    pw=new PrintWriter(s.getOutputStream());
    br=new BufferedReader(new InputStreamReader(s.getInputStream()));
   } catch (IOException e) {
    JOptionPane.showMessageDialog(frame, "连接参数不正确,请重新输入!");
   }
  } while (s==null); 
  
  userName=JOptionPane.showInputDialog(frame,"请输入用户名:");
  label.setText(userName+":");
 }
 
 
 private void init(){
  field.setFont(new Font("",Font.BOLD,20));
  area.setFont(new Font("",Font.BOLD,24));
  JScrollPane jsp=new JScrollPane(area);
  JPanel panel=new JPanel();
  panel.add(label);
  panel.add(field);
  panel.add(button);
  
  frame.add(jsp,BorderLayout.CENTER);
  frame.add(panel,BorderLayout.SOUTH);
  
 }
 
 private void addEventHandler(){
  button.addActionListener(new ActionListener(){
   public void actionPerformed(ActionEvent arg0) {
    //得到field的内容,将其写入到pw中,userName+":"+field.getText()
    //将field清空
    if(field.getText().trim().equals("")){
     JOptionPane.showMessageDialog(frame, "不能发送空内容!");
     return;
    }
    pw.println(userName+":"+field.getText());
    pw.flush();
    field.setText("");
   }
  });
  
  frame.addWindowListener(new WindowAdapter(){
   public void windowClosing(WindowEvent arg0) {
    //弹出对话框询问是否确定退出?
    //给服务器发送退出请求:userName+":%GOODBYE%"
    //等待200毫秒,再关闭socket,退出程序。
    int op=JOptionPane.showConfirmDialog(frame, "确定离开聊天室吗?","确认退出",JOptionPane.YES_NO_OPTION);
    if(op==JOptionPane.YES_OPTION){
     pw.println(userName+":%GOODBYE%");
     log.info(userName+"离开聊天室-----");
     pw.flush();
     try {
      Thread.sleep(200);
     } catch (Exception e) {
      e.printStackTrace();
     }finally{
      try{s.close();}catch(IOException e){}
     }
     System.exit(0);
    }
   }
  });
 }
 
 public void showMe(){
  frame.pack();
  frame.setVisible(true);
  frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
  new Thread(){
   public void run(){
    //不停的从br中读数据,每读到一行就将其显示在area中。
    while(true){
     try {
      String str=br.readLine();
      area.append(str+" ");
     } catch (IOException e) {
      e.printStackTrace();
     }
    }
   }
  }.start();
 }
 
 public static void main(String[] args){
  new SocketClient().showMe();
 }
 

}

服务器代码:

package javaSocket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class SocketServer {
 private ServerSocket ss;
 private HashSet<Socket> allSockets;
 private static final Log log = LogFactory.getLog(SocketServer.class);
 public SocketServer(){
  try {
   ss=new ServerSocket(8888);
   allSockets=new HashSet<Socket>();
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
 
 public void startService()throws IOException{
  while(true){
   log.info("服务器成功启动,等待客户端相应.....");
   Socket s=ss.accept();
   log.info(new Date()+" ip:"+s.getLocalAddress()+"   "+"登入了聊天室!");
   allSockets.add(s);
   new ChatRoomServerThread(s).start();
  }
 }
 
 class ChatRoomServerThread extends Thread{
  private Socket s;
  
  public ChatRoomServerThread(Socket s){
   this.s=s;
  }
  public void run(){
   //得到s的输入流,并包装成BufferedReader
   //循环不停的从BufferedReader中读取数据。
   //每读到一行数据就将这一行数据转发给所有在线的客户端。
   //   循环遍历allSockets,得到每一个socket,
   //   然后得到该socket的输出流,并包装,再向输出流中写数据。
   //
   BufferedReader br=null;
   try {
    br=new BufferedReader(new InputStreamReader(s.getInputStream()));
    while(true){
     String str=br.readLine();
     if(str.split(":")[1].equals("%GOODBYE%")){
      allSockets.remove(s);
      sendMessageToAllClient(str.split(":")[0]+",离开聊天室!");
      log.info(str.split(":")[0]+",离开聊天室!");
      s.close();
      break;
     }
     sendMessageToAllClient(str);
    }
   } catch (IOException e) {
    e.printStackTrace();
   }
  }//run end!
  
  public void sendMessageToAllClient(String str)throws IOException{
   Date date=new Date();
   SimpleDateFormat sf=new SimpleDateFormat("hh-mm-ss");
   String dateStr = sf.format(date);
   for(Socket temp:allSockets){
    PrintWriter pw=new PrintWriter(temp.getOutputStream());
    pw.println(str+" ["+dateStr+"]");
    pw.flush();
   }
  }
  
 }//thread class end!
 
 public static void main(String[] args){
  try {
   new SocketServer().startService();
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
 
}

原文地址:https://www.cnblogs.com/alaricblog/p/3278352.html