java自己写的简单聊天工具SimpleQQ感悟
Demo如下:
客户端:
/*
* 一个简单的QQ
* 2013-8-1
* @李志杰
*/
package SimpleQQ_Client;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.net.*; public class DemoQQ_Client
{
public static void main(String[] args)
{
// TODO Auto-generated method stub
DemoQQ_Client demoQQ_Server_1 = new DemoQQ_Client();
}
public DemoQQ_Client()
{ //初始化界面,开始界面的多线程
MyPanel mp;
mp = new MyPanel(); Thread t1 = new Thread(mp);
t1.start(); //服务器getter
MyClient mServer = new MyClient();
Thread t2 = new Thread(mServer);
t2.start(); //服务器sender
MyClient_writer myClient_writer = new MyClient_writer();
Thread t3 = new Thread(myClient_writer);
t3.start(); /*
//测试线程
Mytest mytest = new Mytest();
Thread t4 = new Thread(mytest);
t4.start();
*/
}
} //共享参数类
class MyBaseClient
{
//定义参数,务必让发送信息和接收信息的参数共享
static Socket s;
static String send_ino,get_ino; } class MyClient_writer extends MyBaseClient implements Runnable //QQ写者
{ @Override
public void run()
{
// TODO Auto-generated method stub
while(true)
{
try
{
Thread.sleep(500);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
sendIno();
send_ino = null;
}
}
//发送信息
public void sendIno()
{
if(send_ino == null)
{
return;
}
try
{
//发送数据
PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
//获取发送内容
pw.println(send_ino);
send_ino = "Client :" + send_ino +"\n"; }
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} class MyClient extends MyBaseClient implements Runnable
{
public MyClient()
{
//下面是主要功能
try
{
s = new Socket("127.0.0.1", 9999);
get_ino = "欢迎使用星尘QQ简易版\n";
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
} //传递返回信息
public void getIno()
{
try
{
//读数据
InputStreamReader inr = new InputStreamReader(s.getInputStream());
BufferedReader bf = new BufferedReader(inr);
get_ino = "Server :"+bf.readLine()+"\n";
}
catch (IOException e)
{
System.out.println("Error!");
return;
}
} @Override
public void run()
{
// TODO Auto-generated method stub
while(true)
{
try
{
Thread.sleep(500);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} getIno(); }
}
} //专门的界面类,以后要用这种方式去画界面,不要用视频教程里面的
class MyPanel extends JFrame implements Runnable,ActionListener
{ //定义参数
String sender,getter;
MyBaseClient mbc = new MyBaseClient();
//定义组件
JPanel jp;
JTextArea jta;
JButton jb;
JTextField jt;
JScrollPane jsp; public MyPanel()
{ //创建组件
jp = new JPanel();
jta = new JTextArea();
jb = new JButton("发送");
jt = new JTextField();
jsp = new JScrollPane(jta); jt.setCaretColor(Color.GREEN);//jt绿色光标
jt.setForeground(Color.GREEN);//jt绿色字体 //信息区只能读
jta.setEditable(false);
//添加监听
jb.setActionCommand("send");
//注册监听
jb.addActionListener(this); //添加组件
jp.setLayout(new GridLayout(2,1)); jp.add(jt);
jp.add(jb); this.setLayout(new GridLayout(2,1));
this.add(jsp);
this.add(jp); this.setSize(400,400);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("QQ_Client"); }
public void paint(Graphics g)
{
super.paint(g);
}
@Override
public void run()
{
while(true)
{
try
{
Thread.sleep(500); }
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
sender = this.jt.getText();
getter = mbc.get_ino;
//更新面板
if(getter == null) //信息为空,跳过更新
{
continue;
}
if(mbc.get_ino != null)
{
String s_board = this.jta.getText() + getter; //通过面板来获取记录
this.jta.setText(s_board);
mbc.get_ino = null;
}
this.repaint();
}
}
@Override
public void actionPerformed(ActionEvent e)
{
if(e.getActionCommand() == "send")
{
//发送信息
mbc.send_ino = sender; //更新消息缓存
String s_board = this.jta.getText() + "Client :" +sender +"\n"; //通过面板来获取记录
this.jta.setText(s_board);
jt.setText(null);//清空内容
this.repaint();
}
}
} //测试类
class Mytest extends MyBaseClient implements Runnable
{ int times = 0;
public void run()
{
// TODO Auto-generated method stub
try
{
while(true)
{
times++;
Thread.sleep(100);
System.out.println("Time :"+ times + " " + get_ino);
}
}
catch (Exception e)
{
// TODO: handle exception
}
} }
服务器端的:
/*
* 一个简单的QQ
* 2013-8-1
* @李志杰
*/
package SimpleQQ_Server;
import java.awt.*;
import java.awt.event.*; import javax.swing.*; import java.io.*;
import java.net.*; public class DemoQQ_Server
{
public static void main(String[] args)
{
// TODO Auto-generated method stub
DemoQQ_Server demoQQ_Server = new DemoQQ_Server();
}
public DemoQQ_Server()
{ //初始化界面,开始界面的多线程
MyPanel mp;
mp = new MyPanel(); Thread t1 = new Thread(mp);
t1.start(); //服务器getter
MyServer mServer = new MyServer();
Thread t2 = new Thread(mServer);
t2.start(); //服务器sender
MyServer_writer myClient_writer = new MyServer_writer();
Thread t3 = new Thread(myClient_writer);
t3.start(); }
} //共享参数类
class MyBaseServer
{
//定义参数,务必让发送信息和接收信息的参数共享
static Socket s;
static ServerSocket ss;
static String send_ino,get_ino;
} class MyServer_writer extends MyBaseServer implements Runnable //QQ写者
{ @Override
public void run()
{
// TODO Auto-generated method stub
while(true)
{
try
{
Thread.sleep(500);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
sendIno();
send_ino = null;
//get_ino = null;
}
}
//发送信息
public void sendIno()
{
if(send_ino == null)
{
return;
}
try
{
//发送数据
PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
//获取发送内容
pw.println(send_ino);
send_ino = "Client :" + send_ino +"\n";
}
catch (IOException e)
{
e.printStackTrace();
}
}
} class MyServer extends MyBaseServer implements Runnable
{
public MyServer()
{
//下面是主要功能
try
{
get_ino = "欢迎使用星尘QQ简易版\n";
ss = new ServerSocket(9999);
s = ss.accept();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
} //传递返回信息
public void getIno()
{
//要拥有一个判断去跳出这个读取,否则一旦进入try块,如果没有信息进来,读者会一直占用cpu而不会进入到写者,除非写者也开多线程
/*
if(get_ino == null)
{
return;
}
*/
try
{
//读数据
InputStreamReader inr = new InputStreamReader(s.getInputStream());
BufferedReader bf = new BufferedReader(inr);
get_ino = "Server :"+bf.readLine()+"\n";
}
catch (IOException e)
{
return;
}
} @Override
public void run()
{
// TODO Auto-generated method stub
while(true)
{
try
{
Thread.sleep(500);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
getIno();
//sendIno();
// send_ino = null;
//get_ino = null;
}
}
} //专门的界面类,以后要用这种方式去画界面,不要用视频教程里面的
class MyPanel extends JFrame implements Runnable,ActionListener
{ //定义参数
String sender,getter;
MyBaseServer mbs = new MyBaseServer();
//定义组件
JPanel jp;
JTextArea jta;
JButton jb;
JTextField jt;
JScrollPane jsp; public MyPanel()
{ //创建组件
jp = new JPanel();
jta = new JTextArea();
jb = new JButton("发送");
jt = new JTextField();
jsp = new JScrollPane(jta); jt.setCaretColor(Color.RED);//jt红色光标
jt.setForeground(Color.RED);//jt红色字体 //信息区只能读
jta.setEditable(false);
//添加监听
jb.setActionCommand("send"); //注册监听
jb.addActionListener(this); //添加组件
jp.setLayout(new GridLayout(2,1)); jp.add(jt);
jp.add(jb); this.setLayout(new GridLayout(2,1));
this.add(jsp);
this.add(jp); this.setSize(400,400);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("QQ_Server"); }
public void paint(Graphics g)
{
super.paint(g);
}
@Override
public void run()
{
while(true)
{
try
{
Thread.sleep(500); }
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
sender = this.jt.getText();
getter = mbs.get_ino;
//更新面板
//更新面板
if(getter == null) //信息为空,跳过更新
{
continue;
}
if(mbs.get_ino != null)
{
String s_board = this.jta.getText() + getter; //通过面板来获取记录
this.jta.setText(s_board);
mbs.get_ino = null;
}
this.repaint();
}
}
@Override
public void actionPerformed(ActionEvent e)
{
if(e.getActionCommand() == "send")
{
//发送信息
mbs.send_ino = sender; //更新消息缓存
String s_board = this.jta.getText() + "Client :" +sender +"\n"; //通过面板来获取记录
this.jta.setText(s_board);
jt.setText(null);//清空内容
this.repaint();
}
}
}
总结:
先说一下这个简单项目的设计思路:
1、本着模块独立化的思路,将整个项目的两个模块(界面+通讯)独立成三个类,其中界面类为MyPanel,通讯(这里以客户端为例)为MyClient(接收消息)和MyClient_writer(发送消息)。
2、除了以上三个类外,还设计了一个共享信息的类,即MyBaseClient,通讯的两个类直接继承这个类,界面类通过将这个类实例化来共享这个类的变量信息;
3、此项目还有一个特色的地方是,使用了三个线程,一个是界面线程用以定时绘图和监听按钮,另一个是接收消息的类,用以定时接收消息。除了这两个外,还有一个用以发送消息。之所以要这样设计,首先是要让界面与后台逻辑分离,即界面与通讯分离,其次是要让后台中的读写分离,实现同步和实时。
这是我今天的技术收获,记此。
java自己写的简单聊天工具SimpleQQ感悟的更多相关文章
- [更新Github地址]python学习,自己写了个简单聊天工具mychat
最近在学习python,自己写了个最最简单的聊天工具mychatv0.1. 第一版,完成基本的聊天功能. GUI用的是自带的TKinter,用到的模块主要就是socket(网络编程), thread( ...
- Java continue break 制作简单聊天室程序,屏蔽不文明语言,显示每句话聊天时间 for(;;) SimpleDateFormat("yyyy-MM-dd hh:mm:ss") equalsIgnoreCase
package com.swift; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Scanne ...
- Python使用Socket写一个简单聊天程序
b2b模式的聊天工具 服务端: # 链接 while True: print('等待连接...') sock,adr = server_socket.accept() while True: try: ...
- ASP.NET 使用application和session对象写的简单聊天室程序
ASP.Net中有两个重要的对象,一个是application对象,一个是session对象. Application:记录应用程序参数的对象,该对象用于共享应用程序级信息. Session:记录浏览 ...
- 关于Socket编写简单聊天工具的总结(原创)
这段时间再看socket编程,虽然现在是刚刚接触,但是还是忍不住想写一篇总结,来激励自己努力学习,写的不好的地方,还请大家指教啊! 下面针对一个简单的发送消息和文件的程序说说吧. 首先是服务器需要 ...
- c# UDP/TCP协议简单实现(简单聊天工具)
长时间没有摸这两个协议,写个代码温习下 下面是界面 [服务器界面] [登陆界面] [好友列表界面(我登陆了2个)] [聊天界面] 下面大致讲解下用到的内容 1.用户登陆于服务器通信用到的tcp协议,服 ...
- 用java代码写一个简单的网上购物车程序
需求:1.写一个商品类,有商品编号.商品名称.商品分类.商品单价属性.2.写一个商品条目信息类,有商品和数量两个属性,有商品总价格方法. 3.写一个购物车类,有添加商品方法.查看订单信息,删除商品,修 ...
- 基于Android的简单聊天工具-服务器端
1.数据库用的mysql,一共有3张表,一张用户表user.一张朋友列表friend和一张消息表message. 1 User table 用户表 uid 主键自动生成 userName 昵称 use ...
- 聊天工具mychat
python学习,自己写了个简单聊天工具mychat 最近在学习python,自己写了个最最简单的聊天工具mychatv0.1. 第一版,完成基本的聊天功能. GUI用的是自带的TKinter,用到的 ...
随机推荐
- 51nod 1406 位运算/dp
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1406 1406 与查询 题目来源: CodeForces 基准时间限制: ...
- python基础之多线程与多进程(二)
上课笔记整理: 守护线程的作用,起到监听的作用 一个函数连接数据库 一个做守护线程,监听日志 两个线程同时取一个数据 线程---->线程安全---->线程同时进行操作数据. IO操作--- ...
- python基础之模块一
一 time模块 时间表示形式 在Python中,通常有这三种方式来表示时间:时间戳.元组(struct_time).格式化的时间字符串:(1)时间戳(timestamp) :通常来说,时间戳表示的是 ...
- 热烈祝贺博主LZUGIS博客访问量突破
截止发文时间,博主"LZUGIS"CSDN博客文章总访问量突破50W,值此特殊的时刻,特发此文,以表纪念与督促. 博客详情 博客专栏 公众号 常言道:不积跬步,无以至千里:不积小流 ...
- 重读tcp-ip详解三卷:1
应用层 Http.Telnet.FTP和e-mail等 负责把数据传输到传输层或接收从传输层返回的数据传输层 TCP和UDP 主要为两台主机上的应用程序提供端到端的通信,TCP为两台主机提供高可靠性的 ...
- netcat 瑞士军刀
netcat被誉为网络安全界的‘瑞士军刀’,一个简单而有用的工具,透过使用TCP或UDP协议的网络连接去读写数据.它被设计成一个稳定的后门工具,能够直接由其它程序和脚本轻松驱动.同时,它也是一个功能强 ...
- C# 浅拷贝与深拷贝(复制)
在有些时候,我们需要从数据库读取数据填充对象或从硬盘读取文件填充对象,但是这样做相对耗时.这时候我们就想到了对象的拷贝.本文即以实例形式解析了C#浅拷贝和深拷贝的用法. C#中有两种类型变量,一种 是 ...
- SCARA——OpenGL入门学习四(颜色)
OpenGL入门学习[四] 本次学习的是颜色的选择.终于要走出黑白的世界了~~ OpenGL支持两种颜色模式:一种是RGBA,一种是颜色索引模式. 无论哪种颜色模式,计算机都必须为每一个像素保存一些数 ...
- MongoDB:MapReduce基础及实例
背景 MapReduce是个非常灵活和强大的数据聚合工具.它的好处是可以把一个聚合任务分解为多个小的任务,分配到多服务器上并行处理. MongoDB也提供了MapReduce,当然查询语肯定是Java ...
- LA3263 That Nice Euler Circuits
题意 PDF 分析 欧拉定理:设平面内顶点数.边数.面数分别为\(V,E,F\),则\(V+F-E=2\). 枚举每对线段求交点,注意去重. 另外注意第n个端点和第一个端点重合. 时间复杂度\(o(T ...