JavaSE简单实现多线程聊天

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/429351.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

matlab将数据输出到excel中,matlab将数据保存为excel表格-怎样将MATLAB中的数据输出到excel中...

怎样将MATLAB中的数据输出到excel中&#xff1f;xlswrite()函数可以将matlab中数据保存到excel中&#xff0c;请面例子&#xff1a;>> data magic(5) % 示例数据data 17 24 1 8 1523 5 7 14 164 6 13 20 2210 12 19 …

一维抛物线的matlab求解,一维抛物线偏微分方程数值解法(附图及matlab程序)

精确解为&#xff1a;U(x,t)e^(xt);用紧差分格式&#xff1a;此种方法精度为o(h1^2h2^4),无条件差分稳定&#xff1b;一&#xff1a;用追赶法解线性方程组(还可以用迭代法解)Matlab程序为&#xff1a;function [u p e x t]JCHGS(h1,h2,m,n)%紧差分格式解一维抛物线型偏微分方程…

Windows系统环境下Solr之Java实战(三)使用solrJ管理索引库

https://www.cnblogs.com/zhuxiaojie/p/5764680.html https://www.cnblogs.com/xieyupeng/p/9317158.html转载于:https://www.cnblogs.com/cnki/p/6783264.html

macos php无法访问,Mac上,Apache启动正常,却无法访问localhost和127.0.0.1

mac系统&#xff0c;之前一直好好的&#xff0c;今天突然localhost以及127就突然打不开了。显示拒绝访问。各种方法都试过了&#xff0c;不是端口占用&#xff0c; 不是日志文件缺失&#xff0c;任何情况都不是。想了想&#xff0c;之前有升级过PHP从5升级到了7&#xff0c;于是…

内部类(innerclasses)

一般情况下&#xff0c;我们把类定义成独立的单元。有些情况下&#xff0c;我们把一个类放在另一个类的内部定义为内部类。 内部类的作用&#xff1a; 1.内部类提供了更好的封装。只能让外部类直接访问&#xff0c;不允许同一个包中的其他类直接访问。 2.内部类可以直接访问外部…

c js php比较字符串,Php 比较字符串相像度

Php 比较字符串相似度除了利用cookies、IP限制等技术外&#xff0c;我们可以利用PHP自身带的similar_text函数来判断用户发帖内容的相似度。?????similar_text()?函数计算两个字符串的匹配字符的数目&#xff0c;也可以计算两个字符串的相似度(以百分比计)。????语法…

非线性时延系统matlab框图,非线性主-从时延系统的时滞相关有限时间同步控制方法与流程...

本发明属于涉及非线性主-从时延系统控制技术领域&#xff0c;具体涉及一种非线性主-从时延系统的时滞相关有限时间同步控制方法。背景技术&#xff1a;近年来融合了控制理论、计算机技术以及网络通信技术的主-从时延机器人系统吸引了大量研究学者的关注。目前&#xff0c;主-从…

python 爬虫002-http与urllib2

urllib2 GET https://www.oschina.net/home/login #!/usr/bin/env python # -*- coding: utf-8 -*- import urllib2 import sys type sys.getfilesystemencoding()if __name__ __main__:# 设置Request的url信息和头部信息url "https://www.oschina.net/home/login&q…

浅说 Rewrite规则简介

1.Rewirte主要的功能就是实现URL的跳转&#xff0c;它的正则表达式是基于Perl语言。可基于服务器级的(httpd.conf)和目录级的(.htaccess)两种方式。如果要想用到rewrite模块&#xff0c;必须先安装或加载rewrite模块。方法有两种一种是编译apache的时候就直接安装rewrite模块&a…

matlab 二进制乘法,xor(乘法英语单词)

For a 1 To 4 For b 1 To 4 For c 1 To 4 For d 1 To 4 If (a 1 Xor b 2) .xor 是异或运算两个整数进行XOR运算&#xff0c;是怎样的算法&#xff1f;XOR为异或运算&#xff0c;对于布尔型的运算&#xff0c;当2者都为ture或者false时&#xff0c;则返回false&#xff0c…

php聊天功能逻辑原理,@xxx提及用户,这种功能的实现原理是怎样的?

122014-12-13 22:05:54 08:00 1在牛客网 http://www.nowcoder.com 用户在我们网站提交的评论&#xff0c;我们会进行敏感词过滤&#xff0c;其算法是基于有限状态机DFA过滤的。 我觉得可以用敏感词过滤的方法来查找的用户ID。 (用户ID就是好多敏感词)&#xff0c; 具体的代码…

strcpy、memcpy和memset的区别

strcpy 原型&#xff1a;extern char *strcpy(char *dest,char *src); 用法&#xff1a;#include <string.h> 功能&#xff1a;把src所指由NULL结束的字符串复制到dest所指的数组中。 说明&#xff1a;src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的…

php cli和fastcgi,php的几种运行模式CLI、CGI、FastCGI、mod_php

1、CLI:就是命令行&#xff0c;例如可以在控制台或者是shell中键入命令:php -f index.php然后获取输出2、CGI:以下是不同的说法与理解公共网关接口”(Common Gateway Interface)&#xff0c;HTTP服务器 与你的或其它机器上的程序 进行 “交谈”的一种工具 &#xff0c;其程序 须…

自学前端,你要的学习资料到了~~~~~~

你要的学习资料到了~~~~~~ 你还在找一个纯技术交流的地方嘛?你还在找一个每天更新资料的群吗&#xff1f;现在加裙617986737&#xff0c;无论是小白还是大神&#xff0c;可以尽情的讨论。 加裙条件&#xff1a; 1&#xff1a;保证自己常在线&#xff0c;一直沉默潜水的人不许加…

html文档php 取mac地址_cpu序列号_硬盘序列号,用vbs脚本获取网卡MAC,CPUID,硬盘序列号的实现代码...

这里先给大家分享一个分配静态ip地址的代码 Assign a Static IP AddressstrComputer "."Set objWMIService GetObject("winmgmts:" _& "{impersonationLevelimpersonate}!\\" & strComputer & "\root\cimv2")Set colNet…

T7-Dropout 解决 overfitting 过拟合

Dropout 解决 overfitting 相对于过拟合&#xff08;overfitting&#xff0c;或称&#xff1a;过度学习&#xff09;是指&#xff0c;使用过多参数&#xff0c;以致太适应训练数据而非一般情况&#xff1b;另一种常见的现象是使用太少参数&#xff0c;以致于不适应当前的训练数…

PHP伪造来源HTTP,伪造来源采集http.php

伪造来源采集.php"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11","safari 5.1 – Windows">"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gec…

从零开始构建一个的asp.net Core 项目(一)

最近突发奇想&#xff0c;想从零开始构建一个Core的MVC项目&#xff0c;于是开始了构建过程。 首先我们添加一个空的CORE下的MVC项目&#xff0c;创建完成之后我们运行一下&#xff08;Ctrl F5&#xff09;。我们会在页面上看到“Hello World!”。 既然是从零开始构建的项目&am…

oracle sal01,oracle中 all any in的用法

Oracle的嵌套子查询可以使用Some,Any和All对子查询中返回的多行结果进行处理。Some表示满足其中一个的含义&#xff0c;是用or串起来的比较从句。例如&#xff1a;SELECT * FROM emp WHERE empno hmz OR dept 10Any也表示满足其中一个的含义&#xff0c;也是用or串起来的比较…

BZOJ 4884 [Lydsy2017年5月月赛]太空猫(单调DP)

【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id4884 【题目大意】 太空猫(SpaceCat)是一款画面精致、玩法有趣的休闲游戏&#xff0c;   你需要控制一只坐在迷你飞碟上的猫咪在太空里不断探索&#xff0c;让大家看看你能飞得多远。   游戏地图可以看成一个…