java局域网聊天小程序
程序员文章站
2024-02-25 19:56:27
本文实例为大家分享了java局域网聊天程序的具体代码,供大家参考,具体内容如下
有服务器端 和客户端两个界面,运行需要加上自己的ip地址,端口可以随意,但是客户端端口,和...
本文实例为大家分享了java局域网聊天程序的具体代码,供大家参考,具体内容如下
有服务器端 和客户端两个界面,运行需要加上自己的ip地址,端口可以随意,但是客户端端口,和服务器端口要一样,然后就可以几个人一块聊天了
简单贴几个代码吧
client.java 客户端代码
package chat; import java.awt.borderlayout;//布置容器的边框布局 import java.awt.color; import java.awt.container; import java.awt.gridlayout;//布局处理器 import java.awt.toolkit;//抽象超类 import java.awt.event.actionevent;//指示发生了组件定义的动作的语义事件 import java.awt.event.actionlistener;//用于接收操作事件的侦听器接口 import java.awt.event.mouseevent;//指示组件中发生鼠标动作的事件 import java.awt.event.mouselistener;//鼠标事件的侦听器接口 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 java.util.hashmap;// hashmap 是 map 接口的常用实现类 import java.util.map;//存数据,将键映射到值的对象 import java.util.stringtokenizer;//允许应用程序将字符串分解为标记 import javax.swing.borderfactory;//创建一个浮雕式的边框 import javax.swing.defaultlistmodel;//列表模型 import javax.swing.jbutton;//按钮 import javax.swing.jframe;//窗口 import javax.swing.jlabel;//标签 import javax.swing.jlist;//列表 import javax.swing.joptionpane;//对话框 import javax.swing.jpanel; import javax.swing.jscrollpane;//视图 import javax.swing.jsplitpane;//分隔 import javax.swing.jtextarea;//多行文本 import javax.swing.jtextfield;//文本 import javax.swing.border.emptyborder;//一个占用空间但不执行绘制的空透明边框 import javax.swing.border.titledborder;//该类实现在指定位置以指定对齐方式显示字符串标题的任意边框 import oldchat.chatframe; public class client { private jframe frame; private jlist userlist; private jtextarea textarea; private jtextfield textfield; private jtextfield txt_port; private jtextfield txt_hostip; private jtextfield txt_name; private jbutton btn_start; private jbutton btn_stop; private jbutton btn_send; private jpanel northpanel; private jpanel southpanel; private jscrollpane rightscroll; private jscrollpane leftscroll; private jsplitpane centersplit; private defaultlistmodel listmodel; private boolean isconnected = false; private socket socket;//创建套接字 private printwriter writer; private bufferedreader reader; private messagethread messagethread;// 负责接收消息的线程 private map<string, user> onlineusers = new hashmap<string, user>();// 所有在线用户 // 主方法,程序入口 public static void main(string[] args) { new client(); } // 执行发送 public void send() { if (!isconnected) { joptionpane.showmessagedialog(frame, "还没有连接服务器,无法发送消息!", "错误", joptionpane.error_message); return; } string message = textfield.gettext().trim(); if (message == null || message.equals("")) { joptionpane.showmessagedialog(frame, "消息不能为空!", "错误", joptionpane.error_message); return; } sendmessage(frame.gettitle() + "@" + "all" + "@" + message); textfield.settext(null); } // 构造方法 public client() { textarea = new jtextarea(); textarea.seteditable(false); textarea.setforeground(color.blue); textfield = new jtextfield(); txt_port = new jtextfield("6666"); txt_hostip = new jtextfield(); txt_name = new jtextfield(); btn_start = new jbutton("连接"); btn_stop = new jbutton("断开"); btn_send = new jbutton("发送"); listmodel = new defaultlistmodel(); userlist = new jlist(listmodel); northpanel = new jpanel(); northpanel.setlayout(new gridlayout(1, 7)); northpanel.add(new jlabel("端口")); northpanel.add(txt_port); northpanel.add(new jlabel("服务器ip")); northpanel.add(txt_hostip); northpanel.add(new jlabel("姓名")); northpanel.add(txt_name); northpanel.add(btn_start); northpanel.add(btn_stop); northpanel.setborder(new titledborder("连接信息")); rightscroll = new jscrollpane(textarea); rightscroll.setborder(new titledborder("群聊消息显示区")); leftscroll = new jscrollpane(userlist); leftscroll.setborder(new titledborder("在线用户(双击私聊)")); southpanel = new jpanel(new borderlayout()); southpanel.add(textfield, "center"); southpanel.add(btn_send, "east"); southpanel.setborder(new titledborder("写消息")); centersplit = new jsplitpane(jsplitpane.horizontal_split, leftscroll, rightscroll); centersplit.setdividerlocation(100); frame = new jframe("客户端"); // 更改jframe的图标: //frame.seticonimage(toolkit.getdefaulttoolkit().createimage(client.class.getresource("qq.jpg"))); frame.setlayout(new borderlayout()); frame.add(northpanel, "north"); frame.add(centersplit, "center"); frame.add(southpanel, "south"); frame.setsize(600, 400); int screen_width = toolkit.getdefaulttoolkit().getscreensize().width; int screen_height = toolkit.getdefaulttoolkit().getscreensize().height; frame.setlocation((screen_width - frame.getwidth()) / 2, (screen_height - frame.getheight()) / 2); frame.setvisible(true); // 写消息的文本框中按回车键时事件 textfield.addactionlistener(new actionlistener() { public void actionperformed(actionevent arg0) { send(); } }); // 单击发送按钮时事件 btn_send.addactionlistener(new actionlistener() { public void actionperformed(actionevent e) { send(); } }); // 单击连接按钮时事件 btn_start.addactionlistener(new actionlistener() { public void actionperformed(actionevent e) { int port; if (isconnected) { joptionpane.showmessagedialog(frame, "已处于连接上状态,不要重复连接!", "错误", joptionpane.error_message); return; } try { try { port = integer.parseint(txt_port.gettext().trim()); } catch (numberformatexception e2) { throw new exception("端口号不符合要求!端口为整数!"); } string hostip = txt_hostip.gettext().trim(); string name = txt_name.gettext().trim(); if (name.equals("") || hostip.equals("")) { throw new exception("姓名、服务器ip不能为空!"); } boolean flag = connectserver(port, hostip, name); if (flag == false) { throw new exception("与服务器连接失败!"); } frame.settitle(name); joptionpane.showmessagedialog(frame, "成功连接!"); } catch (exception exc) { joptionpane.showmessagedialog(frame, exc.getmessage(), "错误", joptionpane.error_message); } } }); //双击聊天(私聊) userlist.addmouselistener(new mouselistener() { public void mousereleased(mouseevent e) {} public void mousepressed(mouseevent e) {} public void mouseexited(mouseevent e) {} public void mouseentered(mouseevent e) {} public void mouseclicked(mouseevent e) { if(e.getclickcount()==2) { user user=onlineusers.get(userlist.getselectedvalue()); chatframe.main(user.getip());; } } }); // 单击断开按钮时事件 btn_stop.addactionlistener(new actionlistener() { public void actionperformed(actionevent e) { if (!isconnected) { joptionpane.showmessagedialog(frame, "已处于断开状态,不要重复断开!", "错误", joptionpane.error_message); return; } try { boolean flag = closeconnection();// 断开连接 if (flag == false) { throw new exception("断开连接发生异常!"); } joptionpane.showmessagedialog(frame, "成功断开!"); } catch (exception exc) { joptionpane.showmessagedialog(frame, exc.getmessage(), "错误", joptionpane.error_message); } } }); // 关闭窗口时事件 frame.addwindowlistener(new windowadapter() { public void windowclosing(windowevent e) { if (isconnected) { closeconnection();// 关闭连接 } system.exit(0);// 退出程序 } }); } /** * 连接服务器 * * @param port * @param hostip * @param name */ public boolean connectserver(int port, string hostip, string name) { // 连接服务器 try { socket = new socket(hostip, port);// 根据端口号和服务器ip建立连接 writer = new printwriter(socket.getoutputstream()); reader = new bufferedreader(new inputstreamreader(socket .getinputstream())); // 发送客户端用户基本信息(用户名和ip地址) sendmessage(name + "@" + socket.getlocaladdress().tostring()); // 开启接收消息的线程 messagethread = new messagethread(reader, textarea); messagethread.start(); isconnected = true;// 已经连接上了 return true; } catch (exception e) { textarea.append("与端口号为:" + port + " ip地址为:" + hostip + " 的服务器连接失败!" + "\r\n"); isconnected = false;// 未连接上 return false; } } /** * 发送消息 * * @param message */ public void sendmessage(string message) { writer.println(message); writer.flush(); } /** * 客户端主动关闭连接 */ @suppresswarnings("deprecation") public synchronized boolean closeconnection() { try { sendmessage("close");// 发送断开连接命令给服务器 messagethread.stop();// 停止接受消息线程 // 释放资源 if (reader != null) { reader.close(); } if (writer != null) { writer.close(); } if (socket != null) { socket.close(); } isconnected = false; return true; } catch (ioexception e1) { e1.printstacktrace(); isconnected = true; return false; } } // 不断接收消息的线程 class messagethread extends thread { private bufferedreader reader; private jtextarea textarea; // 接收消息线程的构造方法 public messagethread(bufferedreader reader, jtextarea textarea) { this.reader = reader; this.textarea = textarea; } // 被动的关闭连接 public synchronized void closecon() throws exception { // 清空用户列表 listmodel.removeallelements(); // 被动的关闭连接释放资源 if (reader != null) { reader.close(); } if (writer != null) { writer.close(); } if (socket != null) { socket.close(); } isconnected = false;// 修改状态为断开 } public void run() { string message = ""; while (true) { try { message = reader.readline(); stringtokenizer stringtokenizer = new stringtokenizer(message, "/@"); string command = stringtokenizer.nexttoken();// 命令 if (command.equals("close"))// 服务器已关闭命令 { textarea.append("服务器已关闭!\r\n"); closecon();// 被动的关闭连接 return;// 结束线程 } else if (command.equals("add")) {// 有用户上线更新在线列表 string username = ""; string userip = ""; if ((username = stringtokenizer.nexttoken()) != null && (userip = stringtokenizer.nexttoken()) != null) { user user = new user(username, userip); onlineusers.put(username, user); listmodel.addelement(username); } } else if (command.equals("delete")) {// 有用户下线更新在线列表 string username = stringtokenizer.nexttoken(); user user = (user) onlineusers.get(username); onlineusers.remove(user); listmodel.removeelement(username); } else if (command.equals("userlist")) {// 加载在线用户列表 int size = integer .parseint(stringtokenizer.nexttoken()); string username = null; string userip = null; for (int i = 0; i < size; i++) { username = stringtokenizer.nexttoken(); userip = stringtokenizer.nexttoken(); user user = new user(username, userip); onlineusers.put(username, user); listmodel.addelement(username); } } else if (command.equals("max")) {// 人数已达上限 textarea.append(stringtokenizer.nexttoken() + stringtokenizer.nexttoken() + "\r\n"); closecon();// 被动的关闭连接 joptionpane.showmessagedialog(frame, "服务器缓冲区已满!", "错误", joptionpane.error_message); return;// 结束线程 } else {// 普通消息 textarea.append(message + "\r\n"); } } catch (ioexception e) { e.printstacktrace(); } catch (exception e) { e.printstacktrace(); } } } } }
server.java
package chat; import java.awt.borderlayout; import java.awt.color; import java.awt.gridlayout; import java.awt.toolkit; 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.bindexception; import java.net.serversocket; import java.net.socket; import java.util.arraylist; import java.util.stringtokenizer; import javax.swing.defaultlistmodel; import javax.swing.jbutton; import javax.swing.jframe; import javax.swing.jlabel; import javax.swing.jlist; import javax.swing.joptionpane; import javax.swing.jpanel; import javax.swing.jscrollpane; import javax.swing.jsplitpane; import javax.swing.jtextarea; import javax.swing.jtextfield; import javax.swing.border.titledborder; public class server { private jframe frame; private jtextarea contentarea; private jtextfield txt_message; private jtextfield txt_max; private jtextfield txt_port; private jbutton btn_start; private jbutton btn_stop; private jbutton btn_send; private jpanel northpanel; private jpanel southpanel; private jscrollpane rightpanel; private jscrollpane leftpanel; private jsplitpane centersplit; private jlist userlist; private defaultlistmodel listmodel; private serversocket serversocket; private serverthread serverthread; private arraylist<clientthread> clients; private boolean isstart = false; // 主方法,程序执行入口 public static void main(string[] args) { new server(); } // 执行消息发送 public void send() { if (!isstart) { joptionpane.showmessagedialog(frame, "服务器还未启动,不能发送消息!", "错误", joptionpane.error_message); return; } if (clients.size() == 0) { joptionpane.showmessagedialog(frame, "没有用户在线,不能发送消息!", "错误", joptionpane.error_message); return; } string message = txt_message.gettext().trim(); if (message == null || message.equals("")) { joptionpane.showmessagedialog(frame, "消息不能为空!", "错误", joptionpane.error_message); return; } sendservermessage(message);// 群发服务器消息 contentarea.append("服务器说:" + txt_message.gettext() + "\r\n"); txt_message.settext(null); } // 构造放法 public server() { frame = new jframe("服务器"); // 更改jframe的图标: //frame.seticonimage(toolkit.getdefaulttoolkit().createimage(client.class.getresource("qq.png"))); //frame.seticonimage(toolkit.getdefaulttoolkit().createimage(server.class.getresource("qq.jpg"))); contentarea = new jtextarea(); contentarea.seteditable(false); contentarea.setforeground(color.blue); txt_message = new jtextfield(); txt_max = new jtextfield("30"); txt_port = new jtextfield("6666"); btn_start = new jbutton("启动"); btn_stop = new jbutton("停止"); btn_send = new jbutton("发送"); btn_stop.setenabled(false); listmodel = new defaultlistmodel(); userlist = new jlist(listmodel); southpanel = new jpanel(new borderlayout()); southpanel.setborder(new titledborder("写消息")); southpanel.add(txt_message, "center"); southpanel.add(btn_send, "east"); leftpanel = new jscrollpane(userlist); leftpanel.setborder(new titledborder("在线用户")); rightpanel = new jscrollpane(contentarea); rightpanel.setborder(new titledborder("群聊消息显示区")); centersplit = new jsplitpane(jsplitpane.horizontal_split, leftpanel, rightpanel); centersplit.setdividerlocation(100); northpanel = new jpanel(); northpanel.setlayout(new gridlayout(1, 6)); northpanel.add(new jlabel("人数上限")); northpanel.add(txt_max); northpanel.add(new jlabel("端口")); northpanel.add(txt_port); northpanel.add(btn_start); northpanel.add(btn_stop); northpanel.setborder(new titledborder("配置信息")); frame.setlayout(new borderlayout()); frame.add(northpanel, "north"); frame.add(centersplit, "center"); frame.add(southpanel, "south"); frame.setsize(600, 400); //frame.setsize(toolkit.getdefaulttoolkit().getscreensize());//设置全屏 int screen_width = toolkit.getdefaulttoolkit().getscreensize().width; int screen_height = toolkit.getdefaulttoolkit().getscreensize().height; frame.setlocation((screen_width - frame.getwidth()) / 2, (screen_height - frame.getheight()) / 2); frame.setvisible(true); // 关闭窗口时事件 frame.addwindowlistener(new windowadapter() { public void windowclosing(windowevent e) { if (isstart) { closeserver();// 关闭服务器 } system.exit(0);// 退出程序 } }); // 文本框按回车键时事件 txt_message.addactionlistener(new actionlistener() { public void actionperformed(actionevent e) { send(); } }); // 单击发送按钮时事件 btn_send.addactionlistener(new actionlistener() { public void actionperformed(actionevent arg0) { send(); } }); // 单击启动服务器按钮时事件 btn_start.addactionlistener(new actionlistener() { public void actionperformed(actionevent e) { if (isstart) { joptionpane.showmessagedialog(frame, "服务器已处于启动状态,不要重复启动!", "错误", joptionpane.error_message); return; } int max; int port; try { try { max = integer.parseint(txt_max.gettext()); } catch (exception e1) { throw new exception("人数上限为正整数!"); } if (max <= 0) { throw new exception("人数上限为正整数!"); } try { port = integer.parseint(txt_port.gettext()); } catch (exception e1) { throw new exception("端口号为正整数!"); } if (port <= 0) { throw new exception("端口号 为正整数!"); } serverstart(max, port); contentarea.append("服务器已成功启动!人数上限:" + max + ",端口:" + port + "\r\n"); joptionpane.showmessagedialog(frame, "服务器成功启动!"); btn_start.setenabled(false); txt_max.setenabled(false); txt_port.setenabled(false); btn_stop.setenabled(true); } catch (exception exc) { joptionpane.showmessagedialog(frame, exc.getmessage(), "错误", joptionpane.error_message); } } }); // 单击停止服务器按钮时事件 btn_stop.addactionlistener(new actionlistener() { public void actionperformed(actionevent e) { if (!isstart) { joptionpane.showmessagedialog(frame, "服务器还未启动,无需停止!", "错误", joptionpane.error_message); return; } try { closeserver(); btn_start.setenabled(true); txt_max.setenabled(true); txt_port.setenabled(true); btn_stop.setenabled(false); contentarea.append("服务器成功停止!\r\n"); joptionpane.showmessagedialog(frame, "服务器成功停止!"); } catch (exception exc) { joptionpane.showmessagedialog(frame, "停止服务器发生异常!", "错误", joptionpane.error_message); } } }); } // 启动服务器 public void serverstart(int max, int port) throws java.net.bindexception { try { clients = new arraylist<clientthread>(); serversocket = new serversocket(port); serverthread = new serverthread(serversocket, max); serverthread.start(); isstart = true; } catch (bindexception e) { isstart = false; throw new bindexception("端口号已被占用,请换一个!"); } catch (exception e1) { e1.printstacktrace(); isstart = false; throw new bindexception("启动服务器异常!"); } } // 关闭服务器 @suppresswarnings("deprecation") public void closeserver() { try { if (serverthread != null) serverthread.stop();// 停止服务器线程 for (int i = clients.size() - 1; i >= 0; i--) { // 给所有在线用户发送关闭命令 clients.get(i).getwriter().println("close"); clients.get(i).getwriter().flush(); // 释放资源 clients.get(i).stop();// 停止此条为客户端服务的线程 clients.get(i).reader.close(); clients.get(i).writer.close(); clients.get(i).socket.close(); clients.remove(i); } if (serversocket != null) { serversocket.close();// 关闭服务器端连接 } listmodel.removeallelements();// 清空用户列表 isstart = false; } catch (ioexception e) { e.printstacktrace(); isstart = true; } } // 群发服务器消息 public void sendservermessage(string message) { for (int i = clients.size() - 1; i >= 0; i--) { clients.get(i).getwriter().println("服务器:" + message); clients.get(i).getwriter().flush(); } } // 服务器线程 class serverthread extends thread { private serversocket serversocket; private int max;// 人数上限 // 服务器线程的构造方法 public serverthread(serversocket serversocket, int max) { this.serversocket = serversocket; this.max = max; } public void run() { while (true) {// 不停的等待客户端的链接 try { socket socket = serversocket.accept(); if (clients.size() == max) {// 如果已达人数上限 bufferedreader r = new bufferedreader( new inputstreamreader(socket.getinputstream())); printwriter w = new printwriter(socket .getoutputstream()); // 接收客户端的基本用户信息 string inf = r.readline(); stringtokenizer st = new stringtokenizer(inf, "@"); user user = new user(st.nexttoken(), st.nexttoken()); // 反馈连接成功信息 w.println("max@服务器:对不起," + user.getname() + user.getip() + ",服务器在线人数已达上限,请稍后尝试连接!"); w.flush(); // 释放资源 r.close(); w.close(); socket.close(); continue; } clientthread client = new clientthread(socket); client.start();// 开启对此客户端服务的线程 clients.add(client); listmodel.addelement(client.getuser().getname());// 更新在线列表 contentarea.append(client.getuser().getname() + client.getuser().getip() + "上线!\r\n"); } catch (ioexception e) { e.printstacktrace(); } } } } // 为一个客户端服务的线程 class clientthread extends thread { private socket socket; private bufferedreader reader; private printwriter writer; private user user; public bufferedreader getreader() { return reader; } public printwriter getwriter() { return writer; } public user getuser() { return user; } // 客户端线程的构造方法 public clientthread(socket socket) { try { this.socket = socket; reader = new bufferedreader(new inputstreamreader(socket .getinputstream())); writer = new printwriter(socket.getoutputstream()); // 接收客户端的基本用户信息 string inf = reader.readline(); stringtokenizer st = new stringtokenizer(inf, "@"); user = new user(st.nexttoken(), st.nexttoken()); // 反馈连接成功信息 writer.println(user.getname() + user.getip() + "与服务器连接成功!"); writer.flush(); // 反馈当前在线用户信息 if (clients.size() > 0) { string temp = ""; for (int i = clients.size() - 1; i >= 0; i--) { temp += (clients.get(i).getuser().getname() + "/" + clients .get(i).getuser().getip()) + "@"; } writer.println("userlist@" + clients.size() + "@" + temp); writer.flush(); } // 向所有在线用户发送该用户上线命令 for (int i = clients.size() - 1; i >= 0; i--) { clients.get(i).getwriter().println( "add@" + user.getname() + user.getip()); clients.get(i).getwriter().flush(); } } catch (ioexception e) { e.printstacktrace(); } } @suppresswarnings("deprecation") public void run() {// 不断接收客户端的消息,进行处理。 string message = null; while (true) { try { message = reader.readline();// 接收客户端消息 if (message.equals("close"))// 下线命令 { contentarea.append(this.getuser().getname() + this.getuser().getip() + "下线!\r\n"); // 断开连接释放资源 reader.close(); writer.close(); socket.close(); // 向所有在线用户发送该用户的下线命令 for (int i = clients.size() - 1; i >= 0; i--) { clients.get(i).getwriter().println( "delete@" + user.getname()); clients.get(i).getwriter().flush(); } listmodel.removeelement(user.getname());// 更新在线列表 // 删除此条客户端服务线程 for (int i = clients.size() - 1; i >= 0; i--) { if (clients.get(i).getuser() == user) { clientthread temp = clients.get(i); clients.remove(i);// 删除此用户的服务线程 temp.stop();// 停止这条服务线程 return; } } } else { dispatchermessage(message);// 转发消息 } } catch (ioexception e) { e.printstacktrace(); } } } // 转发消息 public void dispatchermessage(string message) { stringtokenizer stringtokenizer = new stringtokenizer(message, "@"); string source = stringtokenizer.nexttoken(); string owner = stringtokenizer.nexttoken(); string content = stringtokenizer.nexttoken(); message = source + "说:" + content; contentarea.append(message + "\r\n"); if (owner.equals("all")) {// 群发 for (int i = clients.size() - 1; i >= 0; i--) { clients.get(i).getwriter().println(message); clients.get(i).getwriter().flush(); } } } } }
运行截图
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。