您的位置:首页 > 编程语言 > Java开发

IT十八掌作业_java基础第十七天_QQ案例

2016-03-22 17:54 405 查看
感谢大家对IT十八掌大数据的支持,今天的作业如下:

按照老师讲的,自己练习项目

--------------------------------------------------------------------------------------------------------
项目源码:

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());
}
}

package com.it18zhang.server;

import java.io.IOException;
import java.net.Socket;

import com.it18zhang.common.Message;
import com.it18zhang.util.SocketUtil;

/**
* 服务器消息推送器
*/
public class MessagePusher {

/**
* 推送消息
*/
public static void push(final Message msg){
//遍历所有socket
for(final Socket s : MessageServer.allSockets){
new Thread(){
public void run() {
try {
SocketUtil.writeMessage(s.getOutputStream(), msg);
}
catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
}
}

package com.it18zhang.server;

import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import com.it18zhang.util.SocketUtil;

/**
*
*/
public class MessageServer {
//客户端集合
public static List<String> friends = new ArrayList<String>();

//存放所有socket
public static List<Socket> allSockets = new ArrayList<Socket>();

//启动
public void start(int port){
try {
ServerSocket ss = new ServerSocket(port);
System.out.println("服务器启动了!!");
while(true){
Socket sock = ss.accept();
//添加好友
friends.add(SocketUtil.getAddr(sock));

//维护socket集合
allSockets.add(sock);
MessagePusher.push(new LatestFriendsServerMessage(friends));
//分配线程,单独处理
new ServerReceiverThread(sock).start();
}
}
catch (Exception e) {
}
}
}

package com.it18zhang.server;

import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;

import com.it18zhang.common.Message;
import com.it18zhang.common.MessageFactory;
import com.it18zhang.util.SocketUtil;

import sun.awt.windows.ThemeReader;

/**
* 服务器接收线程.
*/
public class ServerReceiverThread extends Thread {

private Socket sock ;
private InputStream is ;

public ServerReceiverThread(Socket sock) {
try {
this.sock = sock ;
this.is = sock.getInputStream() ;
}
catch (Exception e) {
e.printStackTrace();
}
}

public void run() {
while(true){
//
try {
//转成服务器消息
Message msg = MessageFactory.tranformPack(is);
//
int type = msg.getType();
switch(type){
case Message.MESSAGE_TYPE_SERVER_TALK :
MessagePusher.push(msg);
break ;
case Message.MESSAGE_TYPE_SERVER_REFRESHFRIENDS:
MessagePusher.push(msg);
break ;
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}

package com.it18zhang.server;

public class StartServer {

public static void main(String[] args) {
//消息服务器
MessageServer server = new MessageServer();
//启动消息服务器
server.start(1234);
}

}

package com.it18zhang.server;

import com.it18zhang.common.Message;

/**
* 服务器端推送给客户端的talk消息
*/
public class TalkServerMessage extends Message {

public TalkServerMessage(String text){
//处理消息
this.setType(Message.MESSAGE_TYPE_SERVER_TALK) ;
byte[] bytes = text.getBytes() ;
this.setContent(bytes);
}

/**
* 直接通过原生报文构造消息对象
*/
public TalkServerMessage(byte[] pack){
this.setPack(pack);
pack[0] = Message.MESSAGE_TYPE_SERVER_TALK ;
}
/**
* 直接通过原生报文构造消息对象
*/
public TalkServerMessage(int length,byte[] content){
this.setType(Message.MESSAGE_TYPE_SERVER_TALK) ;
this.setContent(content);
}

public byte[] genMessagePack() {
if(getPack() != null){
return getPack();
}
else{
return super.genMessagePack();
}
}

public Object getData() {
return new String(getContent());
}
}

package com.it18zhang.util;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.util.List;

import com.it18zhang.common.Message;

/**
* 工具类
*/
public class SocketUtil {
/**
* 返回地址串
*/
public static String getAddr(Socket sock){
String ip = sock.getInetAddress().getHostName() ;
String ip0 = ip.substring(ip.lastIndexOf(".") + 1);
return ip0 + ":" + sock.getPort() ;
}

/**
* 从输入流is的当前读取byte,处理成消息类型.
* 0-好友列表 1-文本内容
*/
public static int readMsgType(InputStream is){
try {
return is.read() ;
}
catch (IOException e) {
e.printStackTrace();
}
return -1 ;
}

/**
* 读取消息的长度
*/
public static int readMsglength(InputStream is){
try {
byte[] buf = new byte[4];
is.read(buf);
//最高位
int s3 = buf[0] << 24 ;
//次高位
int s2 = (buf[1] & 0xFF) << 16 ;
//次低位
int s1 = (buf[2] & 0xFF) << 8 ;
//最低位
int s0 = buf[3] & 0xFF ;
return s3 | s2 | s1 | s0 ;
}
catch (Exception e) {
e.printStackTrace();
}
return -1 ;
}

/**
* 读取指定消息长度的内容
*/
public static byte[] readMessage(InputStream is,int len){
try {
byte[] bytes = new byte[len];
is.read(bytes);
return bytes ;
}
catch (IOException e) {
e.printStackTrace();
}
return null ;
}

/**
* 反序列化字节数组成好友列表
*/
public static List<String> deserializeFriends(byte[] bytes){
try {
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
List<String> list= (List<String>)ois.readObject();
ois.close();
return list ;
}
catch (Exception e) {
e.printStackTrace();
}
return null ;
}

/**
* 读取字符串
*/
public static String readString(byte[] bytes){
return new String(bytes);
}

/**
* 使用指定的字符集读取字符串
*/
public static String readString(byte[] bytes,String charset){
try {
return new String(bytes,charset);
}
catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null ;
}

/**
* 发送消息到os中
*/
public static void writeMessage(OutputStream os , String txt){
try {
byte[] bytes = txt.getBytes();
//先写入字节数组的长度
os.write(int2ByteArr(bytes.length));
//再写入字节
os.write(bytes);
}
catch (Exception e) {
e.printStackTrace();
}
}

/**
* 发送Message的原始报文到os中
*/
public static void writeMessage(OutputStream os , Message msg){
try {
os.write(msg.genMessagePack());
os.flush();
}
catch (Exception e) {
e.printStackTrace();
}
}

/**
* 整型转换成字节数组
*/
public static byte[] int2ByteArr(int i){
byte[] bytes = new byte[4] ;
bytes[0] = (byte)(i >> 24) ;
bytes[1] = (byte)(i >> 16) ;
bytes[2] = (byte)(i >> 8) ;
bytes[3] = (byte)(i >> 0) ;
return bytes ;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java IT 十八掌