标签:java 基础 qq项目
QQ案例
-----------------------------------------------------
项目源码:
package com.it18zhang.client;
import java.net.Socket;
/**
* 通信类,单例类
*/
public class Comm {
private String ip = "192.168.12.2";
private int port = 1234 ;
private static Comm instance ;
private Socket sock ;
private ReceiverThread receiver ;
private SenderThread sender ;
public Socket getSock() {
return sock;
}
public void setSock(Socket sock) {
this.sock = sock;
}
/**
* 返回单例对象
*/
public static Comm getInstance(MyWindow window){
if(instance == null){
instance = new Comm(window);
}
return instance ;
}
private Comm(MyWindow window) {
try {
sock = new Socket(ip, port);
//启动后台接收线程
receiver = new ReceiverThread(sock, window);
receiver.start();
//启动后台发送线程
sender = new SenderThread(sock);
sender.start();
}
catch (Exception e) {
}
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
/**
* 发送消息
*/
public void sendText(String txt) {
sender.setTxt(txt);
}
}
package com.it18zhang.client;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
/**
* 窗体
*/
public class MyWindow extends JFrame {
private static final long serialVersionUID = -6944831795769317874L;
// 历史记录
private JTextArea taHistory;
//滚动面板
private JScrollPane spHistory ;
// 内容
private JTextArea taContent;
// 发送按钮
private JButton btnSend;
// 联系人列表
private JList listContacts;
private JTable table;
public MyWindow() {
ini();
}
// 初始化
private void ini() {
//
this.setSize(600, 400);
this.setLocation(200, 200);
// 绝对布局
this.setLayout(null);
//联系人表格
table = new JTable();
table.setBounds(500, 0, 100, 400);
this.add(table);
//聊天记录区
taHistory = new JTextArea();
taHistory.setEditable(false);
taHistory.setBounds(0, 0, 480, 300);
//
spHistory = new JScrollPane(taHistory);
spHistory.setBounds(0, 0, 480, 300);
this.add(spHistory);
//输入区
taContent = new JTextArea();
taContent.setBounds(0, 310,450, 90);
this.add(taContent);
//发送按钮
btnSend = new JButton("发送");
btnSend.setBounds(460,350 , 50, 50);
btnSend.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
//发送消息
String txt = taContent.getText();
Comm comm = Comm.getInstance(MyWindow.this);
comm.sendText(txt);
//清空输入区
taContent.setText("");
}
});
this.add(btnSend);
this.setVisible(true);
// 事件
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(-1);
}
});
}
/**
* 刷新联系人
*/
public void refreshFriendsUI(final List<String> friends) {
//去重
Set<String> set = new HashSet<String>(friends);
//
final List<String> newclients = new ArrayList<String>(set);
//
TableModel dataModel = new AbstractTableModel() {
public int getColumnCount() {
return 1;
}
public int getRowCount() {
return newclients.size();
}
public Object getValueAt(int row, int col) {
return newclients.get(row);
}
};
table.setModel(dataModel);
}
/**
* 更新聊天记录
*/
public void updateHistory(String addr, String line) {
//原文
String old = taHistory.getText();
StringBuilder builder = new StringBuilder();
builder.append(old);
builder.append("\r\n");
builder.append(addr);
builder.append("\r\n");
builder.append(line);
builder.append("\r\n");
//更新聊天区域
taHistory.setText(builder.toString());
}
/**
* 追加内容到聊天区域
*/
public void appendCont2History(String cont) {
String old = taHistory.getText() ;
StringBuilder builder = new StringBuilder();
builder.append(old);
builder.append("\r\n");
builder.append(cont);
String newCont = builder.toString();
taHistory.setText(newCont);
}
}
package com.it18zhang.client;
public class QQ {
public static void main(String[] args) {
MyWindow window = new MyWindow();
Comm comm = Comm.getInstance(window);
}
}
package com.it18zhang.client;
import java.io.InputStream;
import java.net.Socket;
import java.util.List;
import com.it18zhang.common.Message;
import com.it18zhang.common.MessageFactory;
import com.it18zhang.server.LatestFriendsServerMessage;
import com.it18zhang.server.TalkServerMessage;
import com.it18zhang.util.SocketUtil;
/**
* 接收者线程
*/
public class ReceiverThread extends Thread {
//客户端UI
private MyWindow window ;
//sock
private Socket sock ;
//输入流,读取服务器回传的信息
private InputStream is ;
public ReceiverThread(Socket sock,MyWindow window){
try {
this.sock = sock ;
this.window = window ;
is = sock.getInputStream() ;
}
catch (Exception e) {
e.printStackTrace();
}
}
public void run() {
try {
//读取消息类型
//读取文件长度
//读取消息内容
while(true){
processMessage();
}
}
catch (Exception e) {
}
}
/**
* 处理消息
*/
private void processMessage() {
Message msg = MessageFactory.parsePack(is);
int type = msg.getType();
switch(type){
//刷新列表
case Message.MESSAGE_TYPE_SERVER_REFRESHFRIENDS:
List<String> list = (List<String>)((LatestFriendsServerMessage)msg).getData();
window.refreshFriendsUI(list);
break ;
//服务器对话
case Message.MESSAGE_TYPE_SERVER_TALK:
String str = (String) ((TalkServerMessage)msg).getData();
window.appendCont2History(str);
break ;
}
}
}
package com.it18zhang.client;
import com.it18zhang.common.Message;
/**
* 客户端请求刷新好友列表消息
*/
public class RequestFriendsClientMessage extends Message {
public RequestFriendsClientMessage() {
this.setType(Message.MESSAGE_TYPE_CLIENT_REQUESTFRIENDS);
}
/**
* 重写该方法,该消息没有消息长度和消息内容。
*/
public byte[] genMessagePack() {
byte[] bytes = new byte[1];
bytes[0] = (byte)this.getType();
return bytes ;
}
/**
* 无需实现
*/
public Object getData() {
return null;
}
}
package com.it18zhang.client;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import com.it18zhang.util.SocketUtil;
/**
* 发送者线程
*/
public class SenderThread extends Thread {
private String txt ;
private OutputStream os ;
public SenderThread(Socket sock){
try {
this.os = sock.getOutputStream() ;
}
catch (IOException e) {
e.printStackTrace();
}
}
public String getTxt() {
return txt;
}
public void setTxt(String txt) {
this.txt = txt;
}
public void run() {
while(true){
if(txt != null){
//发送
SocketUtil.writeMessage(os, txt);
txt = null ;
}
}
}
}
package com.it18zhang.client;
import com.it18zhang.common.Message;
/**
* 客户端输入的话语消息
*/
public class TalkClientMessage extends Message {
public TalkClientMessage(String text) {
//处理消息
this.setType(Message.MESSAGE_TYPE_CLIENT_TALK) ;
byte[] bytes = text.getBytes() ;
this.setContent(bytes);
}
/**
* 无需实现
*/
public Object getData() {
return null;
}
}
package com.it18zhang.common;
import com.it18zhang.util.SocketUtil;
/**
* 消息
*/
public abstract class Message {
//客户端发送talk
public static final int MESSAGE_TYPE_CLIENT_TALK = 0 ;
//客户端请求好友列表(手动刷新)
public static final int MESSAGE_TYPE_CLIENT_REQUESTFRIENDS = 1 ;
//服务端推送刷新好友列表
public static final int MESSAGE_TYPE_SERVER_REFRESHFRIENDS = 2 ;
//推送某个客户端的说的话
public static final int MESSAGE_TYPE_SERVER_TALK = 3 ;
//消息类型
private int type ;
//消息长度
private int length ;
//消息内容
private byte[] content ;
//原生报文
private byte[] pack ;
public Message(){
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public byte[] getContent() {
return content;
}
public void setContent(byte[] content) {
this.content = content;
this.length = content.length ;
}
public byte[] getPack() {
return pack;
}
public void setPack(byte[] pack) {
this.pack = pack;
}
/**
* 生成整个报文,含有头信息 + 消息本身
*/
public byte[] genMessagePack(){
pack = new byte[1 + 4 + length];
//类型
pack[0] = (byte)type ;
//数组复制
byte[] lenArr = SocketUtil.int2ByteArr(length);
System.arraycopy(lenArr, 0, pack, 1, 4);
//内容复制
System.arraycopy(content, 0, pack, 5, length);
return pack ;
}
public abstract Object getData() ;
}
package com.it18zhang.common;
import java.io.InputStream;
import com.it18zhang.server.LatestFriendsServerMessage;
import com.it18zhang.server.MessageServer;
import com.it18zhang.server.TalkServerMessage;
import com.it18zhang.util.SocketUtil;
/**
* 消息工厂
*/
public class MessageFactory {
/**
* 转换报文,返回服务器端的消息对象,该方法只给服务器使用
*/
public static Message tranformPack(InputStream is){
Message msg = null ;
try {
//消息类型
int type = is.read();
int length = 0 ;
byte[] cont = null ;
switch(type){
//客户端talk消息
case Message.MESSAGE_TYPE_CLIENT_TALK:
//消息长度
length = SocketUtil.readMsglength(is);
cont = SocketUtil.readMessage(is, length);
//转换成服务器talk
msg = new TalkServerMessage(length,cont);
break ;
//客户端刷新好友
case Message.MESSAGE_TYPE_CLIENT_REQUESTFRIENDS:
msg = new LatestFriendsServerMessage(MessageServer.friends);
break ;
}
//返回消息
return msg ;
}
catch (Exception e) {
}
return null ;
}
/**
* 解析报文,提取消息内容,只给客户端使用
*/
public static Message parsePack(InputStream is){
Message msg = null;
try {
//消息类型
int type = is.read();
int length = 0 ;
byte[] cont = null ;
//消息长度
length = SocketUtil.readMsglength(is);
cont = SocketUtil.readMessage(is, length);
switch(type){
//客户端talk消息
case Message.MESSAGE_TYPE_SERVER_TALK:
msg = new TalkServerMessage(length, cont);
break ;
//客户端刷新好友
case Message.MESSAGE_TYPE_SERVER_REFRESHFRIENDS:
msg = new LatestFriendsServerMessage(cont);
break ;
}
//返回消息
return msg ;
}
catch (Exception e) {
}
return null ;
}
}
package com.it18zhang.server;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.util.List;
import com.it18zhang.common.Message;
import com.it18zhang.util.SocketUtil;
/**
* 服务器端消息,最新的好友列表
*/
public class LatestFriendsServerMessage extends Message {
public LatestFriendsServerMessage(List<String> list){
this.setType(MESSAGE_TYPE_SERVER_REFRESHFRIENDS);
this.setContent(serialFriends(list));
}
public LatestFriendsServerMessage(byte[] content){
this.setType(MESSAGE_TYPE_SERVER_REFRESHFRIENDS);
this.setContent(content);
}
/**
* 串行好友列表
*/
private byte[] serialFriends(List<String> list){
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(list);
oos.close();
baos.close();
return baos.toByteArray();
}
catch (Exception e) {
e.printStackTrace();
}
return null ;
}
/**
* 取得消息中的数据部分,反串行化。
*/
public Object getData() {
return SocketUtil.deserializeFriends(getContent());
}
}
本文出自 “作业” 博客,请务必保留此出处http://10718270.blog.51cto.com/10708270/1789789
标签:java 基础 qq项目
原文地址:http://10718270.blog.51cto.com/10708270/1789789