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. 控制语句1:真假与if 语句

    一.真假与运算符 1.1 真假的划分.查看 任何数据都可以分为两类:True 与 False False : 0,None,空的数据结构例如:[] ,{},str1 = '' True  :除了上面情 ...

  2. UI- UINavigationController UITabBarController 使用总结

    #pragma mark - UINavigationController UITabBarController  ====================================== 控制器 ...

  3. CSS: transitions

    CSS Transitions CSS transitions allows you to change property values smoothly (from one value to ano ...

  4. react-router-dom: 重定向默认路由

    <appLayout> <Switch> <Route path='/' exact render={()=> ( <Redirect to={this.ge ...

  5. hdu-5117 Fluorescent(状压dp)

    题目链接: Fluorescent Time Limit: 3000/3000 MS (Java/Others)     Memory Limit: 512000/512000 K (Java/Oth ...

  6. Compile For Cydia Submission Author: BigBoss Updated September 23, 2011

    Compile For Cydia Submission Author: BigBoss Updated September 23, 2011: In order to submit your app ...

  7. Wordpress在主题或者插件中自定义存储附件的方法

    1.前端使用form表单 //单文件上传,我的业务需求中限制了必须上传图片 <input type="file" name="singlename" ac ...

  8. fedora 安装新字体 courier new xxx

    fedora安装新字体 1.将windows字体拷贝到/usr/share/fonts/truetype下面,文件夹名字可以随便起 cp /media/c/WINDOWS/Fonts/* /usr/s ...

  9. C++将链表反转的实现

    有题目的需求是求将链表反转,例如1->2->3->4->5转变成5->4->3->2->1,经典的是可以有两种解决方法,递归方式和非递归方式,下面给出C ...

  10. Django之mysql表单操作

    在Django之ORM模型中总结过django下mysql表的创建操作,接下来总结mysql表记录操作,包括表记录的增.删.改.查. 1. 添加表记录 class UserInfo(models.Mo ...