?? packethistory.java
字號:
/*
* LumaQQ - Java QQ Client
*
* Copyright (C) 2004 luma <stubma@163.com>
* notXX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package edu.tsinghua.lumaqq.qq.packets;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
/**
* 包監視器.
* 這個類使用一個hashtable和一個linked list來管理收到的包,其他人可以調用他的
* 方法來檢查一個包是否收到,比如重發線程通過它來檢查是否一個包的應答已經到達,
* 如果是,則不需要重發。還有接收線程,一旦收到一個包,就把這個包的hash值存入這
* 個類,還有包處理器,也要通過來檢查是否一個包是重復的。當然這種方法還不能完美
* 的避免任何不必要的重發,但是至少有點幫助,-_-!....
* 另外這個包監視器還要管理所有的請求,因為這些包的應答包里面沒有什么有用的信息,
* 信息都在請求包里,所以...
* <br>(edit by notxx)
* 改變成使用LinkedHashSet和HashMap來管理. 速度應該快一些.
* 不需要創建一個Integer對象作為key了, 直接使用Packet本身即可.
*
* @see notxx.lumaqq.qq.packet.Packet#hashCode()
* @see notxx.lumaqq.qq.packet.Packet#equals(Object)
*
* @author luma
* @author notXX
*/
public class PacketHistory {
/**
* 用于重復包檢測的鏈接哈希表
*/
private LinkedHashSet<Integer> hash;
/**
* 用于請求的哈希表
*/
private Map<OutPacket, OutPacket> sent;
/**
* 閾值,超過時清理hash中的數據
*/
private static final int THRESHOLD = 100;
/**
* 構造函數
*/
public PacketHistory() {
hash = new LinkedHashSet<Integer>();
sent = new Hashtable<OutPacket, OutPacket>();
}
/**
* 這個方法檢查包是否已收到,要注意的是檢查是針對這個包的hash值進行的,
* 并不是對packet這個對象,hash值的計算是在packet的hashCode中完成的,
* 如果兩個packet的序號或者命令有不同,則hash值肯定不同。
*
* @param packet
* 要檢查的包
* @param add
* 如果為true,則當這個包不存在時,添加這個包的hash,否則不添加
* @return
* true如果這個包已經收到,否則false
*
* @see Packet#hashCode()
* @see Packet#equals(Object);
*/
public boolean check(Packet packet, boolean add) {
// 檢查
return check(packet.hashCode(), add);
}
/**
* 檢查指定的hash值是否已經存在
*
* @param hashValue
* 哈希值
* @param add
* true表示如果不存在則添加這個哈希值
* @return
* true表示已經存在
*/
public boolean check(int hashValue, boolean add) {
// 檢查是否已經有了
if(hash.contains(hashValue))
return true;
else{
// 如果add標志為false,不添加
if(add)
hash.add(hashValue);
else
return false;
}
// 檢查是否超過了閾值
if(hash.size() >= THRESHOLD) {
// 清理掉一半
Iterator<Integer> it = hash.iterator();
for(int i = 0; i < (THRESHOLD / 2); i++) {
it.next();
it.remove();
}
}
return false;
}
/**
* 這個方法檢查包是否已收到,要注意的是檢查是針對這個包的hash值進行的,
* 并不是對packet這個對象,hash值的計算是在packet的hashCode中完成的,
* 如果兩個packet的序號或者命令有不同,則hash值肯定不同。
*
* @param packet
* 要檢查的包
* @param add
* 如果為true,則當這個包不存在時,添加這個包的hash,否則不添加
* @return
* true表示這個包已經收到,否則false
*/
public boolean check(Object packet, boolean add) {
return check((Packet)packet, add);
}
/**
* 把請求推入哈希表
*
* @param packet
* 請求包
*/
public void putSent(OutPacket packet) {
sent.put(packet, packet);
}
/**
* 返回這個回復包對應的請求包
*
* @param packet
* InPacket
* @return
* 你的請求包
*/
public OutPacket retrieveSent(InPacket packet) {
return sent.remove(packet);
}
/**
* 清空包監視緩沖區
*/
public void clear() {
hash.clear();
sent.clear();
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -