IT十八掌作業_java基礎第十七天_QQ案例

感謝大家對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 ;

}

}





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章