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,用到的 ...
随机推荐
- IE浏览器兼容 css之bug 问题
bug的几种常见原因: 1.盒模型bug 原因:没有正确声明doctype(如果没有声明doctype,各浏览器对代码的解析有不同的规范).解决方法:使用严格的doctype声明. 2.各浏 ...
- Android开发调试中遇到的Waiting for HOME解决方案
显示问题如图: 基本解决思路:在AVD里面单独启动运行一次模拟器,然后尝试运行程序,基本会解决这个问题.
- 前端之CSS续集
CSS:语法形式上由选择器+以及一条或多条声明组成:选择器查找到指定的html标签后,使用css属性设置html标签的样式: 一.css 语法形式: 二.使用步骤 1.引入css规则 2.使用cs ...
- react antd 动态表单
import React, { Component } from 'react'; import ReactDOM from 'react-dom'; import { Form, InputNumb ...
- windows7自动登录后锁定 & 其他VBS
首先设置自动登录(原已设置登录密码),在开始菜单搜索框输 入 “netplwiz” 按 回车,打开高级用户控制面板,然后取消对“要使用本机,用户需输入用户名和密码(E)”项的勾选,系统弹出窗口要求输入 ...
- Https与SSL介绍
参考资料: http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html http://www.ruanyifeng.com/blog/2014/09/ill ...
- Android 应用程序窗体显示状态操作(requestWindowFeature()的应用)
我们在开发程序是经常会需要软件全屏显示.自定义标题(使用按钮等控件)和其他的需求,今天这一讲就是如何控制Android应用程序的窗体显示. 首先介绍一个重要方法那就是requestWindowF ...
- [置顶]
【Android实战】----从Retrofit源码分析到Java网络编程以及HTTP权威指南想到的
一.简介 接上一篇[Android实战]----基于Retrofit实现多图片/文件.图文上传中曾说非常想搞明白为什么Retrofit那么屌.最近也看了一些其源码分析的文章以及亲自查看了源码,发现其对 ...
- 在CodeBlocks上配置OpenGL问题
问题:出现No such file or directory.之后重建了C++project 仍然出现这个error.嘿 奇了怪了! 原因:前几日写密码学作业,用到NTL库,将编译器路径设置为NTL库 ...
- 数据结构之最小生成树Prim算法
普里姆算法介绍 普里姆(Prim)算法,是用来求加权连通图的最小生成树算法 基本思想:对于图G而言,V是所有顶点的集合:现在,设置两个新的集合U和T,其中U用于存放G的最小生成树中的顶点,T存放G的最 ...