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感悟的更多相关文章

  1. [更新Github地址]python学习,自己写了个简单聊天工具mychat

    最近在学习python,自己写了个最最简单的聊天工具mychatv0.1. 第一版,完成基本的聊天功能. GUI用的是自带的TKinter,用到的模块主要就是socket(网络编程), thread( ...

  2. 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 ...

  3. Python使用Socket写一个简单聊天程序

    b2b模式的聊天工具 服务端: # 链接 while True: print('等待连接...') sock,adr = server_socket.accept() while True: try: ...

  4. ASP.NET 使用application和session对象写的简单聊天室程序

    ASP.Net中有两个重要的对象,一个是application对象,一个是session对象. Application:记录应用程序参数的对象,该对象用于共享应用程序级信息. Session:记录浏览 ...

  5. 关于Socket编写简单聊天工具的总结(原创)

    这段时间再看socket编程,虽然现在是刚刚接触,但是还是忍不住想写一篇总结,来激励自己努力学习,写的不好的地方,还请大家指教啊! 下面针对一个简单的发送消息和文件的程序说说吧.   首先是服务器需要 ...

  6. c# UDP/TCP协议简单实现(简单聊天工具)

    长时间没有摸这两个协议,写个代码温习下 下面是界面 [服务器界面] [登陆界面] [好友列表界面(我登陆了2个)] [聊天界面] 下面大致讲解下用到的内容 1.用户登陆于服务器通信用到的tcp协议,服 ...

  7. 用java代码写一个简单的网上购物车程序

    需求:1.写一个商品类,有商品编号.商品名称.商品分类.商品单价属性.2.写一个商品条目信息类,有商品和数量两个属性,有商品总价格方法. 3.写一个购物车类,有添加商品方法.查看订单信息,删除商品,修 ...

  8. 基于Android的简单聊天工具-服务器端

    1.数据库用的mysql,一共有3张表,一张用户表user.一张朋友列表friend和一张消息表message. 1 User table 用户表 uid 主键自动生成 userName 昵称 use ...

  9. 聊天工具mychat

    python学习,自己写了个简单聊天工具mychat 最近在学习python,自己写了个最最简单的聊天工具mychatv0.1. 第一版,完成基本的聊天功能. GUI用的是自带的TKinter,用到的 ...

随机推荐

  1. Easyui 行编辑

    之前没用过,突然用了的时候手忙脚乱的感觉  找了官方文档也好 百度了一大堆东西   表示个人脑袋跟不上思路 直接铺上简化的  以后自己 找起来也方便  以下代码已经执行 应该不会再错了 <tab ...

  2. New Concept English three (39)

    26w/m 70errors The rough across the plain soon became so bad that we tried to get Bruce to drive bac ...

  3. Linux中查看各文件夹大小命令:du -h --max-depth=1

    Linux中查看各文件夹大小命令:du -h --max-depth=1 du [-abcDhHklmsSx] [-L <符号连接>][-X <文件>][--block-siz ...

  4. 你必须知道的495个C语言问题,学习体会一

    C语言作为一门古老的语言,其灵活性和容易出错都让人 又爱又恨,书籍<你必须知道的495个C语言问题>,使用问答的形式,告诉读者 C语言使用的各个方面的知识,包括一些冷知识等.以下,我要摘录 ...

  5. linux中的vim编辑器的使用

    vim的三种模式: 常规模式(命令模式)也是默认模式,从其它模式进行命令模式按esc i 在光标前插入文本 o 命令是指在当前行下方插入新行 dd 是删除光标所在的整个一行 yy 是在光标所在整个放入 ...

  6. 【转】斜率优化DP和四边形不等式优化DP整理

    (自己的理解:首先考虑单调队列,不行时考虑斜率,再不行就考虑不等式什么的东西) 当dp的状态转移方程dp[i]的状态i需要从前面(0~i-1)个状态找出最优子决策做转移时 我们常常需要双重循环 (一重 ...

  7. 【抽时间 试验】hibernate集合映射inverse和cascade详解

    http://www.cnblogs.com/amboyna/archive/2008/02/18/1072260.html

  8. web应用程序安全攻防---sql注入和xss跨站脚本攻击

    kali视频学习请看 http://www.cnblogs.com/lidong20179210/p/8909569.html 博文主要内容包括两种常见的web攻击 sql注入 XSS跨站脚本攻击 代 ...

  9. 什么是 DDoS 攻击?

    欢迎访问网易云社区,了解更多网易技术产品运营经验. 全称Distributed Denial of Service,中文意思为“分布式拒绝服务”,就是利用大量合法的分布式服务器对目标发送请求,从而导致 ...

  10. Intent详解以及实例

    Android中统一用Intent来封装程序的“调用意图“.不管程序想启动一个Activity,一个Servicer,还是一个BroadcastReceiver.使用Intent提供了一个统一的编程模 ...