欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java多线程实现聊天客户端和服务器

程序员文章站 2024-03-12 22:42:57
本文实例为大家分享了java聊天室代码,供大家参考,具体内容如下 主要涉及知识 ·java中gui程序的编写,包括事件监听机制。 ·java的网络通信编程,ser...

本文实例为大家分享了java聊天室代码,供大家参考,具体内容如下

主要涉及知识

·java中gui程序的编写,包括事件监听机制。
·java的网络通信编程,serversocket,socket类的使用。
·java中多线程的编程,thread类,runnable接口的使用。

源代码

客户端

package project1; 
 
import java.awt.*; 
import java.awt.event.*; 
import java.io.*; 
import java.net.*; 
 
import javax.swing.*; 
 
public class client { 
 private jframe clientframe; 
 private jlabel iplabel; 
 private jlabel portlabel; 
 private jlabel saylabel; 
 private jlabel nicknamelabel; 
 private jtextfield iptext; 
 private jtextfield porttext; 
 private jtextfield nicknametext; 
 private jtextfield saytext; 
 private jbutton connectbutton; 
 private jbutton nicknamebutton; 
 private jbutton saybutton; 
 private jpanel jpanelnorth; 
 private jpanel jpanelsouth0; 
 private jpanel jpanelsouth1; 
 private jpanel jpanelsouth2; 
 private jtextarea clienttextarea; 
 private jscrollpane scroller; 
 private bufferedreader reader; 
 private printwriter writer; 
 private string nickname; 
 
 public static void main(string args[]) { 
  client aclient = new client(); 
  aclient.startup(); 
 } 
 
 // 初始化组件 
 public client() { 
  nickname = "客户端"; 
 
  clientframe = new jframe(); 
  jpanelnorth = new jpanel(); 
  iplabel = new jlabel("服务器ip", jlabel.left); 
  iptext = new jtextfield(10); 
  portlabel = new jlabel("服务器端口", jlabel.left); 
  porttext = new jtextfield(10); 
  connectbutton = new jbutton("连接"); 
  clienttextarea = new jtextarea(); 
  scroller = new jscrollpane(clienttextarea); 
  jpanelsouth0 = new jpanel(); 
  jpanelsouth1 = new jpanel(); 
  jpanelsouth2 = new jpanel(); 
  nicknamelabel = new jlabel("昵称", jlabel.left); 
  nicknametext = new jtextfield(nickname, 30); 
  nicknamebutton = new jbutton("确认"); 
  saylabel = new jlabel("消息", jlabel.left); 
  saytext = new jtextfield(30); 
  saybutton = new jbutton("确认"); 
 } 
 
 // 构建gui 
 private void buildgui() { 
  // 窗口的设置 
  clientframe.settitle("客户端"); 
  clientframe.setdefaultcloseoperation(jframe.exit_on_close); 
  clientframe.setsize(550, 550); 
 
  // 北区的组件 
  jpanelnorth.add(iplabel); 
  jpanelnorth.add(iptext); 
  jpanelnorth.add(portlabel); 
  jpanelnorth.add(porttext); 
  jpanelnorth.add(connectbutton); 
  clientframe.getcontentpane().add(borderlayout.north, jpanelnorth); 
 
  // 中间的组件 
  clienttextarea.setfocusable(false); 
  scroller.setverticalscrollbarpolicy(scrollpaneconstants.vertical_scrollbar_always); 
  scroller.sethorizontalscrollbarpolicy(scrollpaneconstants.horizontal_scrollbar_never); 
  clientframe.getcontentpane().add(borderlayout.center, scroller); 
 
  // 南区的组件 
  jpanelsouth1.add(nicknamelabel); 
  jpanelsouth1.add(nicknametext); 
  jpanelsouth1.add(nicknamebutton); 
  jpanelsouth2.add(saylabel); 
  jpanelsouth2.add(saytext); 
  jpanelsouth2.add(saybutton); 
  jpanelsouth0.setlayout(new boxlayout(jpanelsouth0, boxlayout.y_axis)); 
  jpanelsouth0.add(jpanelsouth1); 
  jpanelsouth0.add(jpanelsouth2); 
  clientframe.getcontentpane().add(borderlayout.south, jpanelsouth0); 
 
  // 设置窗口可见 
  clientframe.setvisible(true); 
 } 
 
 // 客户端运行 
 public void startup() { 
  buildgui(); 
 
  // 接收服务器消息的线程 
  runnable incomingreader = new runnable() { 
   @override 
   public void run() { 
    string message; 
    try { 
     while ((message = reader.readline()) != null) { 
      clienttextarea.append(message + "\n"); 
     } 
    } catch (exception ex) { 
     ex.printstacktrace(); 
    } 
   } 
  }; 
 
  // 监听connect按钮,实现服务器的连接 
  connectbutton.addactionlistener(new actionlistener() { 
   @override 
   public void actionperformed(actionevent e) { 
    string aserverip = iptext.gettext(); 
    string aserverport = porttext.gettext(); 
 
    if (aserverip.equals("") || aserverport.equals("")) { 
     joptionpane.showmessagedialog(clientframe, "请输入 完整的 ip和端口!"); 
    } else { 
     try { 
      @suppresswarnings("resource") 
      socket clientsocket = new socket(aserverip, integer.parseint(aserverport)); 
      inputstreamreader streamreader = new inputstreamreader(clientsocket.getinputstream()); 
      reader = new bufferedreader(streamreader); 
      writer = new printwriter(clientsocket.getoutputstream()); 
 
      clienttextarea.append("服务器已连接...\n"); 
 
      thread readerthread = new thread(incomingreader); 
      readerthread.start(); 
     } catch (exception ex) { 
      joptionpane.showmessagedialog(clientframe, "连接不上服务器!\n请确认 ip 和 端口 输入正确。"); 
     } 
    } 
   } 
  }); 
 
  // 监听nickname,设置昵称 
  actionlistener nicknamelistener = new actionlistener() { 
   @override 
   public void actionperformed(actionevent e) { 
    string atext = nicknametext.gettext(); 
    if (!atext.equals("")) { 
     nickname = atext; 
    } 
   } 
  }; 
  nicknamebutton.addactionlistener(nicknamelistener); 
  nicknametext.addactionlistener(nicknamelistener); 
  nicknametext.addfocuslistener(new focuslistener() { 
   @override 
   public void focusgained(focusevent e) { 
   } 
 
   @override 
   public void focuslost(focusevent e) { 
    string atext = nicknametext.gettext(); 
    if (!atext.equals("")) { 
     nickname = atext; 
    } 
   } 
  }); 
 
  // 发送消息到服务器 
  actionlistener saylistener = new actionlistener() { 
   @override 
   public void actionperformed(actionevent e) { 
    string atext = saytext.gettext(); 
    if (atext.equals("")) { 
     joptionpane.showmessagedialog(clientframe, "内容不能为空!"); 
    } else { 
     try { 
      writer.println(nickname + ":" + atext); 
      writer.flush(); 
     } catch (exception ex) { 
      ex.printstacktrace(); 
     } 
     saytext.settext(""); 
    } 
   } 
  }; 
  saybutton.addactionlistener(saylistener); 
  saytext.addactionlistener(saylistener); 
 
 } 
 
} 

服务器

package project1; 
 
import java.awt.*; 
import java.awt.event.*; 
import java.io.*; 
import java.net.*; 
import java.util.arraylist; 
import java.util.iterator; 
import javax.swing.*; 
 
public class server { 
 private jframe serverframe; 
 private jlabel portlabel; 
 private jlabel saylabel; 
 private jlabel nicknamelabel; 
 private jtextfield porttext; 
 private jtextfield saytext; 
 private jtextfield nicknametext; 
 private jbutton startbutton; 
 private jbutton saybutton; 
 private jbutton nicknamebutton; 
 private jpanel jpanelnorth; 
 private jpanel jpanelsouth0; 
 private jpanel jpanelsouth1; 
 private jpanel jpanelsouth2; 
 private jscrollpane scroller; 
 private jtextarea servertextarea; 
 private arraylist<printwriter> clientoutputstreams; 
 private string nickname; 
 
 public static void main(string[] args) { 
  server aserver = new server(); 
  aserver.startup(); 
 } 
 
 // 初始化组件 
 public server() { 
  nickname = "服务器"; 
 
  serverframe = new jframe(); 
  jpanelnorth = new jpanel(); 
  portlabel = new jlabel("端口", jlabel.left); 
  porttext = new jtextfield(30); 
  startbutton = new jbutton("开始"); 
  servertextarea = new jtextarea(); 
  scroller = new jscrollpane(servertextarea); 
  nicknamelabel = new jlabel("昵称", jlabel.left); 
  nicknametext = new jtextfield(nickname, 30); 
  nicknamebutton = new jbutton("确认"); 
  jpanelsouth0 = new jpanel(); 
  jpanelsouth1 = new jpanel(); 
  jpanelsouth2 = new jpanel(); 
  saylabel = new jlabel("消息", jlabel.left); 
  saytext = new jtextfield(30); 
  saybutton = new jbutton("确认"); 
 } 
 
 // 构建gui 
 private void buildgui() { 
  // 窗口的设置 
  serverframe.settitle("服务器"); 
  serverframe.setdefaultcloseoperation(jframe.exit_on_close); 
  serverframe.setsize(550, 550); 
 
  // 北区的组件 
  jpanelnorth.add(portlabel); 
  jpanelnorth.add(porttext); 
  jpanelnorth.add(startbutton); 
  serverframe.getcontentpane().add(borderlayout.north, jpanelnorth); 
 
  // 中间的组件 
  servertextarea.setfocusable(false); 
  scroller.setverticalscrollbarpolicy(scrollpaneconstants.vertical_scrollbar_always); 
  scroller.sethorizontalscrollbarpolicy(scrollpaneconstants.horizontal_scrollbar_never); 
  serverframe.getcontentpane().add(borderlayout.center, scroller); 
 
  // 南区的组件 
  jpanelsouth1.add(nicknamelabel); 
  jpanelsouth1.add(nicknametext); 
  jpanelsouth1.add(nicknamebutton); 
  jpanelsouth2.add(saylabel); 
  jpanelsouth2.add(saytext); 
  jpanelsouth2.add(saybutton); 
  jpanelsouth0.setlayout(new boxlayout(jpanelsouth0, boxlayout.y_axis)); 
  jpanelsouth0.add(jpanelsouth1); 
  jpanelsouth0.add(jpanelsouth2); 
  serverframe.getcontentpane().add(borderlayout.south, jpanelsouth0); 
 
  // 设置窗口可见 
  serverframe.setvisible(true); 
 } 
 
 // 服务器运行 
 public void startup() { 
  buildgui(); 
 
  // 监听start按钮,建立端口 
  actionlistener startlistener = new actionlistener() { 
   @override 
   public void actionperformed(actionevent e) { 
    clientoutputstreams = new arraylist<printwriter>(); 
    string aport = porttext.gettext(); 
 
    if (aport.equals("")) { 
     joptionpane.showmessagedialog(serverframe, "请输入正确的端口号!"); 
    } else { 
     try { 
      // 等待客户端连接的线程 
      runnable serverrunnable = new runnable() { 
       @override 
       public void run() { 
        serversocket serversocket; 
        try { 
         serversocket = new serversocket(integer.parseint(aport)); 
         servertextarea.append("正在等待客户端连接...\n"); 
         while (true) { 
          socket clientsocket = serversocket.accept(); 
          servertextarea.append("客户端已连接...\n"); 
 
          printwriter writer = new printwriter(clientsocket.getoutputstream()); 
          clientoutputstreams.add(writer); 
 
          thread t = new thread(new clienthandler(clientsocket)); 
          t.start(); 
         } 
        } catch (numberformatexception | ioexception e) { 
         e.printstacktrace(); 
        } 
       } 
      }; 
      thread serverthread = new thread(serverrunnable); 
      serverthread.start(); 
     } catch (exception ex) { 
      ex.printstacktrace(); 
     } 
    } 
   } 
  }; 
  startbutton.addactionlistener(startlistener); 
  porttext.addactionlistener(startlistener); 
 
  // 监听nickname,设置昵称 
  actionlistener nicknamelistener = new actionlistener() { 
   @override 
   public void actionperformed(actionevent e) { 
    string atext = nicknametext.gettext(); 
    if (!atext.equals("")) { 
     nickname = atext; 
    } 
   } 
  }; 
  nicknamebutton.addactionlistener(nicknamelistener); 
  nicknametext.addactionlistener(nicknamelistener); 
  nicknametext.addfocuslistener(new focuslistener() { 
   @override 
   public void focusgained(focusevent e) { 
   } 
 
   @override 
   public void focuslost(focusevent e) { 
    string atext = nicknametext.gettext(); 
    if (!atext.equals("")) { 
     nickname = atext; 
    } 
   } 
  }); 
 
  // 监听say按钮,发送消息 
  actionlistener saylistener = new actionlistener() { 
   @override 
   public void actionperformed(actionevent e) { 
    string atext = saytext.gettext(); 
    if (!atext.equals("")) { 
     atext = nickname + ":" + atext; 
     sendtoeveryclient(atext); 
     servertextarea.append(atext + "\n"); 
     saytext.settext(""); 
    } else { 
     joptionpane.showmessagedialog(serverframe, "内容不能为空!"); 
    } 
   } 
  }; 
  saybutton.addactionlistener(saylistener); 
  saytext.addactionlistener(saylistener); 
 } 
 
 // 多客户端的线程 
 public class clienthandler implements runnable { 
  bufferedreader breader; 
  socket asocket; 
 
  public clienthandler(socket clientsocket) { 
   try { 
    asocket = clientsocket; 
    inputstreamreader isreader = new inputstreamreader(asocket.getinputstream()); 
    breader = new bufferedreader(isreader); 
   } catch (exception ex) { 
    ex.printstacktrace(); 
   } 
  } 
 
  @override 
  public void run() { 
   string message; 
   try { 
    while ((message = breader.readline()) != null) { 
     sendtoeveryclient(message); 
     servertextarea.append(message + "\n"); 
    } 
   } catch (exception ex) { 
    ex.printstacktrace(); 
   } 
  } 
 } 
 
 // 发送消息给所有客户端的方法 
 private void sendtoeveryclient(string message) { 
  iterator<printwriter> it = clientoutputstreams.iterator(); 
  while (it.hasnext()) { 
   try { 
    printwriter writer = (printwriter) it.next(); 
    writer.println(message); 
    writer.flush(); 
   } catch (exception ex) { 
    ex.printstacktrace(); 
   } 
  } 
 } 
 
} 

gui运行截图:

Java多线程实现聊天客户端和服务器

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。