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

📄 filesenderpacketprocessor.java

📁 用java实现的
💻 JAVA
字号:
/*
* LumaQQ - Java QQ Client
*
* Copyright (C) 2004 luma <stubma@163.com>
*
* 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.filetrans;

import java.io.IOException;
import java.nio.ByteBuffer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import edu.tsinghua.lumaqq.qq.QQ;

/**
 * <pre>
 * 文件发送者的包处理器
 * </pre>
 * 
 * @author 马若劼
 */
public class FileSenderPacketProcessor {
    // Log对象
    static Log log = LogFactory.getLog(FileSenderPacketProcessor.class);
    // FileSenderPacketProcessor从属的FileSender对象
    private FileSender sender;
    
    /**
     * 构造函数
     * @param sender
     */
    public FileSenderPacketProcessor(FileSender sender) {
        this.sender = sender;
    }

    /**
     * @param sk
     * @throws BadQQPacketException
     */
    public void processSelectedKeys(ByteBuffer buffer) throws Exception {   
		buffer.flip();
		if(buffer.get() == QQ.QQ_FILE_DATA_PACKET_TAG) {
		    buffer.rewind();
		    sender.fdp.parseContent(buffer);
		    processFileDataPacket(sender.fdp);
		} else {
		    buffer.rewind();
		    sender.fcp.parseContent(buffer);
		    processFileControlPacket(sender.fcp);
		}
    }
    
	// 处理文件数据信息包
	private void processFileDataPacket(FileDataPacket fdp) throws Exception {
		switch(fdp.getCommand()) {
		    case QQ.QQ_FILE_CMD_HEART_BEAT:
		        log.debug("收到Heart Beat 序号: " + (int)fdp.getHeartBeatSequence());
		        // 返回heart beat的确认包
		    	fdp.setCommand(QQ.QQ_FILE_CMD_HEART_BEAT_ACK);
		    	fdp.setHeartBeatSequence(fdp.getHeartBeatSequence());
		    	fdp.initContent(sender.buffer);
		    	sender.buffer.flip();
		    	sender.send();
		        break;
		    case QQ.QQ_FILE_CMD_HEART_BEAT_ACK:
		        log.debug("收到Heart Beat回复,序号: " + (int)fdp.getHeartBeatSequence());
		    	sender.hbThread.setMaxReply(fdp.getHeartBeatSequence());
		        break;
		    case QQ.QQ_FILE_CMD_TRANSFER_FINISHED:
		        // 返回回复包
		    	fdp.setCommand(QQ.QQ_FILE_CMD_TRANSFER_FINISHED);
		    	fdp.initContent(sender.buffer);
		    	sender.buffer.flip();
		    	sender.send();
		    	if(!sender.monitor.checkDuplicate(fdp)) {
			    	// 检查是否已经收到了全部分片,如果不是,表明对方取消了文件传送
			    	if(sender.window.isFinished()) {
			    	    log.debug("文件传输正常结束");
			    	    sender.finish();		    	    
			    	} else {
				        log.debug("文件传输取消");
			    	    sender.abort();
			    	}
		    	}
		        break;
		    case QQ.QQ_FILE_CMD_FILE_OP_ACK:
		    	processFileOpAck(fdp);
		        break;
		}
	}
    
	// 处理文件操作的回复包
    private void processFileOpAck(FileDataPacket fdp) {
        switch(fdp.getInfoType()) {
            case QQ.QQ_FILE_BASIC_INFO:
                processFileBasicInfoAck(fdp);
                break;
            case QQ.QQ_FILE_DATA_INFO:
                processFileDataInfoAck(fdp);
                break;
            case QQ.QQ_FILE_EOF:
                processFileEOFAck(fdp);
                break;
        }
    }

    // 处理文件EOF信息回复包
    private void processFileEOFAck(FileDataPacket fdp) {
        log.debug("收到文件EOF信息回复");
        if(!sender.monitor.checkDuplicate(fdp)) {
            sender.sendFinish(fdp, sender.buffer);
        }
    }

    // 处理文件数据信息回复包
    private void processFileDataInfoAck(FileDataPacket fdp) {
        // 首先检查是否重复
        if(!sender.monitor.checkDuplicate(fdp)) {
            // 然后检查序号是否在预期的范围内,因为heart beat线程也可能访问滑窗对象,所以要同步
            synchronized(sender.window) {                
	            if(sender.window.put(fdp.getFragmentIndex())) {
	                log.debug("收到分片" + fdp.getFragmentIndex() + "的确认");
	                // 如果put成功,相应的调整分片缓冲
	                sender.fb.release(sender.window.getIncrement());
	                // 触发事件
	                sender.fireFileInProgressEvent();
	                // 如果所有的分片都发送完了,调整当然状态,并发送EOF信息
	                //    如果否,发送后面的分片
	                if(sender.window.isFinished()) {
	                    sender.fileTransferStatus = FileWatcher.FT_SENDING_EOF;
	                    sender.sendEOF(fdp, sender.buffer);
	                } else
	                    sender.sendFragment(fdp, sender.buffer);
	            }                
            }
        }
    }

    // 处理文件基本信息回复包
    private void processFileBasicInfoAck(FileDataPacket fdp) {
        log.debug("收到文件基本信息回复");
        if(!sender.monitor.checkDuplicate(fdp)) {
	        sender.fileTransferStatus = FileWatcher.FT_SENDING;
	    	sender.sendFragment(fdp, sender.buffer);            
        }
    }

    // 处理文件控制信息包
	private void processFileControlPacket(FileControlPacket fcp) throws IOException {    
		switch(fcp.getCommand()) {
			case QQ.QQ_FILE_CMD_SENDER_SAY_HELLO:
			    log.debug("收到Sender Hello, HelloByte: " + fcp.getHelloByte());
				break;
			case QQ.QQ_FILE_CMD_SENDER_SAY_HELLO_ACK:
			    log.debug("收到Sender Hello Ack, HelloByte: " + fcp.getHelloByte());
			    break;
			case QQ.QQ_FILE_CMD_RECEIVER_SAY_HELLO:
			    log.debug("收到Receiver Hello, HelloByte: " + fcp.getHelloByte());
				processReceiverSayHello(fcp);
			    break;
			case QQ.QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK:
			    log.debug("收到Reciver Hello Ack, HelloByte: " + fcp.getHelloByte());
			    break;
		}
	}

    /**
     * @param fcp
     */
    private void processReceiverSayHello(FileControlPacket fcp) {
        // 发送回复
        fcp.setCommand(QQ.QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK);
        fcp.setHelloByte(fcp.getHelloByte());
        fcp.initContent(sender.buffer);
        sender.buffer.flip();
        sender.send();
        // 如果这个包已经收到过,不处理
        if(!sender.monitor.checkDuplicate(fcp)) {
	        // 标记状态为传送中
            sender.fileTransferStatus = FileWatcher.FT_SENDING_BASIC;
        }
    }
}

⌨️ 快捷键说明

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