⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 btsocket.java

📁 p2p仿真
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * @(#)BTSocket.java	ver 1.2  6/20/2005
 *
 * Copyright 2005 Weishuai Yang (wyang@cs.binghamton.edu). 
 * All rights reserved.
 * 
 */

package gps.protocol.BT;


import gps.Simulator;
import gps.event.SimEvent;
import gps.event.SimEventHandler;
import gps.event.SimEventScheduler;
import gps.gui.ProtocolPanel;
import gps.protocol.BT.param.BTPeerMessage;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.logging.Logger;


/**
 * BT socket deals with lower level connection issue
 *
 *
 * @author  Weishuai Yang
 * @version 1.2,  6/20/2005
 */
public class BTSocket  implements SimEventHandler {

	/**
	 * request timeout
	 */
	public static final int REQUEST_TIMEOUT = 5;
	/**
	 * connection timeout
	 */
	public static final int CONNECTION_TIMEOUT=60;
	/**
	 * keep alive time
	 */
	public static final int CONNECTION_KEEP_ALIVE=10;
	
	/**
	 * singleton reference to event scheduler
	 */
	private static SimEventScheduler mScheduler=SimEventScheduler.getInstance();
	
	/**
	 * singleton reference to debug log
	 */
	private static Logger mDebugLog = Logger.getLogger("Debug");
	/**
	 * singleton reference to trace log
	 */
	private static Logger mTraceLog = Logger.getLogger("Trace");

	//choked or not means whether this node allow the counterpart to download
	
	/**
	 * I chocked the other side
	 */
	public boolean mAmChoking=true;
	
	/**
	 * the other side chocked me
	 */
	public boolean mPeerChoking=true;
	
	//interested or not means whether this node is interested in the content at counterpart's host
	/**
	 * the other side is interested at my file
	 */
	public boolean mPeerInterested=false;
	
	/**
	 * I'm interested in their file
	 */
	public boolean mAmInterested=false;

	/**
	 * bit field of that peer
	 */
	public boolean mBitField[]=null;

	/**
	 * if closed, set up the mClosed flag, and remove from hashmap
	 */
	public boolean mClosed=false;
	
	/**
	 * reference back to the session to which this connection belongs
	 */
	public BTSession mSession=null;

	/**
	 * the connection at the other side 
	 */
	public BTSocket mCounterpart=null;
	
	/**
	 * uploading or not
	 */
	public boolean mUploading=false;

	/**
	 * the current uploading piece index
	 */
	public int mUploadingPieceIndex=-1;

	
	//following are paramaters recorded at the downloading side	
	
	/**
	 * downloading or not
	 */
	public boolean mDownloading=false;
	
	/**
	 * the piece that I'm interested, this variable is set when request is sent 
	 */
	public int mRequestingPieceIndex=-1;
	
	/**
	 * offset within a downloading piece
	 */
	public int mBegin=0;
	
	/**
	 * length of the current downloading block
	 */
	public int mLength=0;
	
	/**
	 * start time for this downloading bandwidth
	 */
	public double mStartTime=0;

	/**
	 * bytes left within this block
	 */
	public int mDownloadLeft=0;

	/**
	 * previous finished percent
	 */
	public float mPreviousPercent=0;

	/**
	 * connection time out event
	 */
	public BTEvent mTimeout=null;
	
	/**
	 * keep alive event
	 */
	public BTEvent mKeepAlive=null;
	
	/**
	 * the keep alive message to be sent
	 */
	public BTEvent mKeepAliveMsg=null;
	
	/**
	 * estimate finish event
	 */
	public BTEvent mEstimateFinish=null;
	
	/**
	 * request time out event
	 */
	public BTEvent mRequestTimeout=null;

	/**
	 * lower level connection
	 */
	public BTConnection mConnection=null;
	
	/**
	 * in bandwidth history
	 */
	public LinkedList mInBandwidthHistory=new LinkedList();

	/**
	 * out bandwidth history
	 */
	public LinkedList mOutBandwidthHistory=new LinkedList();

	/**
	 * constructs a new bt socket object
	 * @param s session this socket belongs to
	 */
	public BTSocket(BTSession s){
		mSession=s; 
	}
	
	/**
	 * process event sent to this connection
	 * @param e the event object with some parameters in it
	 * @return true if already handled
	 */
	public boolean handle(SimEvent e) {
		switch(e.getType()){
			//all the following events come from itself
			case BTEvent.CONNECTION_DOWNLOAD_BLOCK_FINISH: 
				handleBlockFinished((BTEvent)e);
				return true;
				
			case BTEvent.REQUEST_TIMEOUT: 
				handleRequestTimeout((BTEvent)e);
				return true;
				
			case BTEvent.CONNECTION_KEEP_ALIVE: 
				handleKeepAlive((BTEvent)e);
				return true;
		}
		return false;
	}	
	
	/**
	 * handles request timeout event
	 * @param e the event object
	 */
	public void handleRequestTimeout(BTEvent e){
	    BTPeer p=(BTPeer)e.getAddParam();
	    if(mSession.mRemoved) return;
	    if(!mSession.getConnections().containsKey(p))
	        return;
	    
		//mDebugLog.info(mScheduler.getCurrent()+": "+toString()+" request timeout!");
	    
	    //make the next request possible, otherwise the next request will never be sent
	    
	    if(mRequestingPieceIndex==-1)
			mDebugLog.warning(mScheduler.getCurrent()+": "+toString()+" mRequestingPieceIndex is not supposed to be -1 when request timeout!");
	    
	    if(!mSession.getDocument().inDownloadingSet(mRequestingPieceIndex))
	    	mDebugLog.warning(mScheduler.getCurrent()+": "+toString()+" mRequestingPieceIndex should be in downloading set when request timeout!");

	    mSession.getDocument().removePieceDownloading(mRequestingPieceIndex);
	    if(mSession.getDocument().inPartialList(mRequestingPieceIndex)){
		    if(0==mSession.getDocument().getPieceProgress(mRequestingPieceIndex)){
		    		mSession.getDocument().removePieceProgress(mRequestingPieceIndex);
		    }
		}

	    mRequestingPieceIndex=-1;
	    mRequestTimeout=null;

	    if(!mPeerChoking){
	    	mSession.sendRequestTo(p);
	    }
	 	
	}

	/**
	 * handles keep alive event
	 * @param e the event object
	 */
	public void handleKeepAlive(BTEvent e){
		//send out a keep alive peer message
		ArrayList morePieces=comparePieces();
		
		if(morePieces.size()>0)
		{	
			if(mCounterpart==null) {
				mDebugLog.warning(mScheduler.getCurrent()+": "+this+" in keep alive, return since counterpart is null");
				return;
			}
			
			if(mKeepAliveMsg==null){
				String key=mSession.getDocument().getKey();		
				BTPeerMessage btpm=new BTPeerMessage(BTPeerMessage.KEEP_ALIVE);
				btpm.mDocHashKey=key;
		    	
		    	double t=mScheduler.getCurrent()+BT.getInstance().getDelayAgent(mSession.getAgent(),mCounterpart.mSession.getAgent());
				BTEvent bte=new BTEvent(t, BTEvent.PEER_MESSAGE, (SimEventHandler)(mCounterpart.mSession), mSession);
				bte.setAddParam(btpm);
				mScheduler.enqueue(bte);
				mKeepAliveMsg=bte;
			}
			else{
				double t=mScheduler.getCurrent()+BT.getInstance().getDelayAgent(mSession.getAgent(),mCounterpart.mSession.getAgent());
				mKeepAliveMsg.setTimeStamp(t);
				mScheduler.enqueue(mKeepAliveMsg);
			}
			
			//enqueue next keep alive event
			double t=mScheduler.getCurrent()+BTSocket.CONNECTION_KEEP_ALIVE;
			mKeepAlive.setTimeStamp(t);
			mScheduler.enqueue(mKeepAlive);
			
			//extend connection timeout to keep alive
			if(mTimeout.getTimeStamp()<mScheduler.getCurrent()+BTSocket.CONNECTION_KEEP_ALIVE){
				mScheduler.cancel(mTimeout);
				mTimeout.setTimeStamp(mScheduler.getCurrent()+BTSocket.CONNECTION_KEEP_ALIVE);
				mScheduler.enqueue(mTimeout);
				//mDebugLog.info(mScheduler.getCurrent()+": "+mAgent+", received "+btpm+", connection timeout updated1 to " +(mScheduler.getCurrent()+BTSocket.CONNECTION_TIMEOUT)+" for connection to "+bts.getAgent());
			}
		}
	}


	/**
	 * compare piece between two peers at both end of the connection
	 * @return array of piece index that doesn't existing at local, but existing at remote
	 */
	public ArrayList comparePieces(){
		
		BTDocument btd=mSession.getDocument();
	 	
	 	//pieces this node already has
	 	boolean pieces[]=btd.getPieces();
	 	
	 	//pieces peer node has
	 	boolean peerPieces[]=mBitField;
	 	
	 	if(mBitField==null)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -