1.1 主程序入口

在主程序入口处,通过设置MyWindow的第一个参数,如果为true则为服务器,如果为false,则为客户端,当然也可以设置第二个参数,区分客户端和服务器的窗口标题。

public class JavaMain {public static void main(String[] args) {MyWindow w=new MyWindow(false,"QQ聊天");  //运行时将false改成true, 先启动服务端,然后再改成false启动客户端w.setNet("192.168.1.103", 12345);}
}

1.2 界面程序

界面程序根据主程序传来的参数不同而创建客户端和服务器窗口,根据界面的构造函数中第一个参数,isServer设置服务器窗体或者是客户端窗体。

public class MyWindow extends JFrame {private static final long serialVersionUID = 1L;// 定义一个成员变量Client myClient = null;Server myServer=null;JTextArea area=null;// 设置默认的IP地址和端口private String ipAddress="127.0.0.1";private int    nPort=50000;private boolean isServer=false;// 构造函数public MyWindow(boolean isServer,String title) {this.isServer=isServer;setTitle(title);setSize(300, 400);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setLayout(null);initComponents();setVisible(true);}// 为外界提供设置IP地址和端口的方法public void setNet(String ip,int port){ipAddress=ip;nPort=port;// 对通信接口初始化
        initCommication();}// 通过构造函数,将端口和文本显示区传递给myServer对象public void initCommication(){if (isServer) {myServer=new Server(nPort,area);}else{myClient=new Client(ipAddress,nPort,area);}}public void initComponents() {// 添加一个文本区area = new JTextArea();area.setBounds(10, 20, 260, 200);add(area);// 添加一个文本框final JTextField text = new JTextField();text.setBounds(10, 240, 260, 30);add(text);// 添加一个发送按钮JButton button = new JButton("发送");button.setBounds(10, 290, 80, 30);button.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {if (isServer) {myServer.sendServerMsg(text.getText());}else{myClient.sendMsg(text.getText());}}});add(button);}
}

1.3 服务器类

服务器类比较复杂,这里用到了内部类,内部类的好处就是能随时访问外部类的成员和方法,而无需通过传参数的方法达到目的。

// 监听主线程
public class Server extends Thread {// 服务器Socketprivate ServerSocket serverSocket = null;private ArrayList<ServerThread> clientList = null;// 显示区private JTextArea jTextArea = null;// 构造函数public Server(int port, JTextArea area) {jTextArea = area;try {// 开始绑定端口serverSocket = new ServerSocket(port);// 初始化客户端连接的列表clientList = new ArrayList<ServerThread>();} catch (IOException e) {System.err.println("服务器端口初始化失败!\n");}jTextArea.setText("服务器成功启动,等待客户连接!\n");start(); // 启动线程
    }public void sendServerMsg(String msg) {jTextArea.append(msg + "\n");for (int i = clientList.size() - 1; i >= 0; i--) {clientList.get(i).getWriter().println("服务器:" + msg);clientList.get(i).getWriter().flush();}}// 线程程序public void run() {while (true) {try {// 用阻塞的方式,等待用户连接请求Socket socket = serverSocket.accept();// 启动一条为客户端服务的线程ServerThread svthread = new ServerThread(socket);svthread.start();// 将该客户加入列表中
                clientList.add(svthread);} catch (IOException e) {e.printStackTrace();}}}// 服务线程(内部类),用于处理客户端的服务线程class ServerThread extends Thread {// 当前正在连接的SocketSocket socket = null;// 当前连接的Socket的输入和输出流(数据出入口)private PrintWriter writer = null;private BufferedReader reader = null;// 构造函数public ServerThread(Socket s) {socket = s;try {// 获取输入输出流reader = new BufferedReader(new InputStreamReader(s.getInputStream()));writer = new PrintWriter(s.getOutputStream());// 在此可以写接收用户端的信息,解析出来(IP地址)
} catch (Exception e) {e.printStackTrace();}}// 获得输入流,供外界调用public BufferedReader getReader() {return reader;}// 获得输出流,供外界调用public PrintWriter getWriter() {return writer;}// 获得socketpublic Socket getSocket() {return socket;}// 线程服务程序public void run() {// 创建一个变量,用于接收客户端发来的信息String message = null;while (true) {try {// 读取输入流message = reader.readLine();// 如果是下线命令if (message.equals("Bye")) {// 在客户端列表上删除该用户ServerThread temp = null;for (int i = clientList.size() - 1; i >= 0; i--) {temp = clientList.get(i);if (temp.getSocket().equals(socket)) {clientList.remove(i);}temp.stop();}// 断开连接释放资源
                        reader.close();writer.close();socket.close();return;} else {// 在文本区显示该消息jTextArea.append(message + "\n");// 将该消息广播给其他用户
                        broadcastMsg(message);}} catch (Exception e) {// TODO: handle exception
                }}}// 广播消息public void broadcastMsg(String msg) {for (int i = clientList.size() - 1; i >= 0; i--) {clientList.get(i).getWriter().println(msg);clientList.get(i).getWriter().flush();}}}
}

1.4 客户端类

客户端类比较简单,只要创建一个线程,与服务器连接即可。

public class Client extends Thread {// 写该类的成员变量private Socket socket=null;private PrintWriter out=null;private BufferedReader in=null;private JTextArea area;// 写构造函数,完成初始化public Client(String ip,int nPort,JTextArea area){try {socket=new Socket(ip, nPort);} catch (UnknownHostException e) {System.err.println("初始化失败!");} catch (IOException e) {System.err.println("初始化失败!");}start();  // 启动线程,让线程开始工作this.area=area;this.area.setText("初始化成功,连接上服务器!\n");}// 发送消息public void sendMsg(String msg){if(socket.isConnected()==true){out.println("客户端:"+msg);out.flush();// 将消息推送给客户端
        }}public void run(){while(true){try {// 获取客户端的输入流InputStream is = socket.getInputStream();InputStreamReader isr = new InputStreamReader(is);in = new BufferedReader(isr);// 获取客户端的输出流out = new PrintWriter(socket.getOutputStream(), true);while(true){// 不停的读取从服务器发来的信息String info = in.readLine();area.append(info + "\n");}} catch (Exception e) {System.err.println("发生数据流读取错误,程序退出!");System.exit(1);}finally{try {// 结束,扫尾工作
                    out.close();in.close();socket.close();} catch (Exception e2) {}}}}
}

1.5 运行结果

运行结果如下所示:

转载于:https://www.cnblogs.com/StanLong/p/6781132.html

JavaSE简单实现多线程聊天相关推荐

  1. Windows网络编程-简单的多线程聊天室

    实验室系统:Windows10 实验室IDE:VS2012 一.创建MFC文件项目. 文件->新建->项目 然后根据图片进行操作 注意的地方: 1.取消union库 2.勾选上Window ...

  2. 【C++】基于socket的多线程聊天室(控制台版)

    以前学习socket网络编程和多线程编程的时候写的一个练手程序 聊天室基本功能: 1.用户管理:登录,注册,登出,修改用户名,修改密码 2.聊天室功能:群聊,私聊,获取在线用户列表,获取所有用户列表 ...

  3. Spring和WebSocket整合并建立简单的Web聊天室

    Spring和WebSocket整合并建立简单的Web聊天室 官方主页 Spring WebSocket 一.概述 WebSocket 是一种网络通信协议.RFC6455 定义了它的通信标准. Web ...

  4. Java网络编程学习——简单模拟在线聊天

    Java网络编程学习--简单模拟在线聊天 学了java网络,也是该做个小案例来巩固一下了. 本次案例将使用UDP和多线程模拟即时聊天,简单练练手. 1.前提知识 需要知道简单的IO流操作,以及简单的U ...

  5. html 简单机器人对话页面,简单的js聊天机器人框架BotUI

    Botui是一款简单的js聊天机器人框架.Botui基于Vue.js,通过简单配置,就可以制作出一个功能简单的聊天机器人,非常神奇. 使用方法 在页面中引入botui.min.css和botui-th ...

  6. Java Tread多线程(0)一个简单的多线程实例

    作者 : 卿笃军 原文地址:http://blog.csdn.net/qingdujun/article/details/39341887 本文演示,一个简单的多线程实例,并简单分析一下线程. 编程多 ...

  7. linux编写一个简单的端口扫描程序,小弟我在linux下写了个简单的多线程端口扫描程序,运行时出现有关问题,请问一下(2)...

    当前位置:我的异常网» Linux/Unix » 小弟我在linux下写了个简单的多线程端口扫描程序, 小弟我在linux下写了个简单的多线程端口扫描程序,运行时出现有关问题,请问一下(2) www. ...

  8. 基于PHP实现一个简单的在线聊天功能(轮询ajax )

    基于PHP实现一个简单的在线聊天功能(轮询ajax ) 一.总结 1.用的轮询ajax 二.基于PHP实现一个简单的在线聊天功能 一直很想试着做一做这个有意思的功能,感觉复杂的不是数据交互和表结构,麻 ...

  9. php 开发一个聊天系统,ajax+php 实现一个简单的在线聊天室功能(附带源码)

    通过ajax和setInterval()函数,配合php+mysql实现一个简单的在线聊天室的功能.附带详细源码案例.这个聊天室是一个简单的聊天室,通过javascript setInterval() ...

最新文章

  1. tcp、udp协议连接的建立和释放
  2. SAP托管在Github上的ABAP编程规范
  3. 关于使用indexedDB的本地存储(2)
  4. Bugfree实用心得_转
  5. Data-structures-and-algorithms-interview-questions-and-their-solutions
  6. python很有用吗_Python之父:为什么操作符很有用?
  7. ubuntu安装libjasper.so.1,libpng12.so.0
  8. Vue+Mui商城项目使用说明(首页仿淘宝)
  9. 电脑c盘格式化,如何恢复C盘文件?
  10. resultful规范使用
  11. Magento后台添加商品属性集属性集详细教程
  12. 微信公众号最佳实践 ( 9.6)地图导航
  13. 树莓派 11 bullseye镜像官方源和国内源
  14. kafka_2.11 简单使用
  15. 电商项目—会员体系、等级、折扣营销解析
  16. 如何查看centos系统cpu/内存使用情况
  17. 蓝桥杯国赛 C/C++ ABC组题解(第四届 ~ 第十二届)
  18. 通过命令(cli)配置华为AP的热点以及账号密码
  19. Android视频播放器架构接口的设计
  20. B2B、B2C和O2O商城开发

热门文章

  1. cmd oracle sys登录_oracle忘记sys/system/scott用户密码的解决方法
  2. tomcat 拦截指定url_一口气说出 过滤器 和 拦截器 6个区别,别再傻傻分不清了
  3. 鸿蒙内核是闭源吗_鸿蒙出世,中华有为!
  4. Java数组概述和定义
  5. ASP.NET Core 网站发布到Linux服务器
  6. hihocoder 1183 割点和割边
  7. 在云服务器搭建WordPress博客(六)发布和管理文章
  8. 亲和数 杭电2040
  9. 用Log4Net来记录系统的日志信息
  10. 微信新的用户信息接口wx.getUserProfile,返回信息解密失败