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

📄 qqclient.java

📁 lumaQQ的源文件
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
			GetFriendListPacket packet = new GetFriendListPacket(user);
    		pool.send(MAIN.name, packet, false);			        
	    }
	}
	
	/**
	 * 请求取得好友名单,position指定了名单开始的偏移,建议初级用户不要使用此API
	 * @param position
	 */
	public void getFriendList(char position) {
	    if(pool.hasConnection(MAIN.name)) {
			// 请求取得好友名单
			GetFriendListPacket packet = new GetFriendListPacket(user);
			packet.setStartPosition(position);
    		pool.send(MAIN.name, packet, false);		        
	    }
	}
	
    /**
     * 请求取得当前在线好友列表
     */
    public void getFriendOnline() {
    	if(pool.hasConnection(MAIN.name)) {
	        GetOnlineOpPacket packet = new GetOnlineOpPacket(user);
    		pool.send(MAIN.name, packet, false);		
    	}
    }
    
    /**
     * 请求取得当前在线好友列表
     */
    public void getFriendOnline(int startPosition) {
    	if(pool.hasConnection(MAIN.name)) {
	        GetOnlineOpPacket packet = new GetOnlineOpPacket(user);
	        packet.setStartPosition(startPosition);
    		pool.send(MAIN.name, packet, false);			
    	}
    }
    
    /**
     * 得到用户属性
     * 
     * @param startPosition
     */
    public void getUserProperty(char startPosition) {
    	if(pool.hasConnection(MAIN.name)) {
    		UserPropertyOpPacket packet = new UserPropertyOpPacket(user);
    		packet.setStartPosition(startPosition);
    		packet.setSubCommand(QQ.QQ_SUB_CMD_GET_USER_PROPERTY);
    		pool.send(MAIN.name, packet, false);
    	}
    }
    
    /**
     * 使我的状态改变成在线
     */
    public void makeMeOnline() {
    	if(user.isLoggedIn() && pool.hasConnection(MAIN.name)) {
	        user.setStatus(QQ.QQ_STATUS_ONLINE);
	    	ChangeStatusPacket packet = new ChangeStatusPacket(user);
	    	packet.setShowFakeCam(user.isShowFakeCam());
    		pool.send(MAIN.name, packet, false);	    
    	}
    }
    
    /**
     * 使我的状态改变成离开
     */
    public void makeMeAway() {
    	if(user.isLoggedIn() && pool.hasConnection(MAIN.name)) {
	        user.setStatus(QQ.QQ_STATUS_AWAY);
	    	ChangeStatusPacket packet = new ChangeStatusPacket(user);
	    	packet.setShowFakeCam(user.isShowFakeCam());
    		pool.send(MAIN.name, packet, false);		        
    	}
    }
    
    /**
     * 使我的状态改变为隐身
     */
    public void makeMeHidden() {
    	if(user.isLoggedIn() && pool.hasConnection(MAIN.name)) {
	        user.setStatus(QQ.QQ_STATUS_HIDDEN);
	    	ChangeStatusPacket packet = new ChangeStatusPacket(user);
	    	packet.setShowFakeCam(user.isShowFakeCam());
    		pool.send(MAIN.name, packet, false);	    	        
    	}
    }
    
    /**
     * 请求密钥
     * @param request
     */
    public void requestKey(byte request) {
        if(pool != null && user.isLoggedIn() && pool.hasConnection(MAIN.name)) {
			RequestKeyPacket packet = new RequestKeyPacket(user);
			packet.setRequest(request);
    		pool.send(MAIN.name, packet, true);
        }
    }
    
    /**
     * 请求得到多人对话列表
     */
    public void getDialogList() {
    	if(user.isLoggedIn()) {
    		ClusterSubClusterOpPacket packet = new ClusterSubClusterOpPacket(user);
    		packet.setOpByte(QQ.QQ_CLUSTER_SUB_CMD_GET_DIALOG_LIST);
    		pool.send(MAIN.name, packet, false);
    	}
    }
    
    /**
     * 请求得到讨论组列表
     * 
     * @param clusterId
     * 		群id
     */
    public void getSubjectList(int clusterId) {
    	if(user.isLoggedIn()) {
    		ClusterSubClusterOpPacket packet = new ClusterSubClusterOpPacket(user);
    		packet.setOpByte(QQ.QQ_CLUSTER_SUB_CMD_GET_SUBJECT_LIST);
    		packet.setClusterId(clusterId);
    		pool.send(MAIN.name, packet, false);
    	}
    }
    
    /**
     * 通用方法,发送一个packet
     * 这个方法用在一些包构造比较复杂的情况下,比如上传分组信息这种包,
     * 包中数据的来源是无法知道的也不是用几个参数就能概括的,可能也和实现有关。
     * 
     * @param packet OutPacket子类
     */
    public void sendPacket(OutPacket packet) {
    	if(user.isLoggedIn())
    		pool.send(MAIN.name, packet, true);
    }
    
    /**
     * 通过指定port发送一个包
     * 
     * @param packet
     * @param port
     */
    public void sendPacket(OutPacket packet, String port) {
        sendPacket(packet, port, true);
    }
    
    /**
     * 通过指定port发送一个包
     * 
     * @param packet
     * 		输出包对象
     * @param port
     * 		port名称 
     * @param monitor
     * 		true表示加入到包监视缓冲
     */
    public void sendPacket(OutPacket packet, String port, boolean monitor) {
        if(user.isLoggedIn())
            pool.send(port, packet, monitor);
    }
    
    /**
     * 不管有没有登录,都把包发出去
     * 
     * @param packet
     * @param port
     */
    public void sendPacketAnyway(OutPacket packet, String port) {
        pool.send(port, packet, true);
    }

    /**
     * @return 登陆服务器IP
     */
    public String getLoginServer() {
        return loginServer;
    }
    
    /**
     * @return Returns the user.
     */
    public QQUser getUser() {
        return user;
    }
        
    /**
     * 添加一个QQ事件监听器
     * 
     * @param listener
     * 		QQListener
     */
    public void addQQListener(IQQListener listener) {
    	if(!qqListeners.contains(listener)) {
	    	qqListeners.add(listener);
	    	setListenerChanged(true);    		
    	}
    }
    
    /**
     * 移去一个QQ事件监听器
     * @param listener QQListener
     */
    public void removeQQListener(IQQListener listener) {
    	if(qqListeners.contains(listener)) {
	    	qqListeners.remove(listener);
	    	setListenerChanged(true);    		
    	}
    }
    
    /**
     * 设置listener changed标志
     * 
     * @param b
     */
    private synchronized void setListenerChanged(boolean b) {
    	listenerChanged = b;
    }
    
    /**
     * 得到listener changed标志
     * 
     * @return
     * 		true表示有新的listener添加了进来
     */
    private synchronized boolean isListenerChanged() {
    	return listenerChanged;
    }
    
    /**
     * 检查监听器是否已经改变,如果是则更新监听器
     */
    private synchronized void checkListenerChange() {
    	if(isListenerChanged()) {
    		qqListenersBackup.clear();
    		qqListenersBackup.addAll(qqListeners);
    		setListenerChanged(false);
    	}
    }
    
    /**
     * 触发QQ事件
     * @param e QQEvent
     */
    public void fireQQEvent(QQEvent e) {
    	checkListenerChange();
		int size = qqListenersBackup.size();
		for(int i = 0; i < size; i++)
			qqListenersBackup.get(i).qqEvent(e);
    }
    
    /**
     * 登陆,使用缺省端口
     * 
     * @throws Exception
     * 				如果登录出错
     */
    public void login() throws Exception {    	
        if (user != null && !logging && loginServer != null) {
	        // 登陆
            if(user.isUdp())
                login(loginServer, QQ.QQ_PORT_UDP);
            else
                login(loginServer, tcpLoginPort);
       } 
    }
    
    /**
     * 用指定的服务器和端口登录
     * 
     * @param server 登陆服务器
     * @param p 登陆端口
     * @throws Exception
     * 				如果登录出错
     */
    protected void login(String server, int p) throws Exception {
        // 检查是否设置了用户名和密码
        if (user != null && poolFactory != null) {
        	// 停止以前的线程,如果有的话
        	logout();
        	// 设置状态为正在登陆
        	logging = true;    
            // 检查是什么登陆模式,udp还是tcp
            try {
                IConnection con = MAIN.create(this, new InetSocketAddress(server, p), proxyAddress, proxyUsername, proxyPassword, false);                
                // 如果登录令牌还是空,就构造请求登录令牌包,如果不是,直接登录
                OutPacket packet = null;
                if(user.getLoginToken() == null)
                    packet = new RequestLoginTokenPacket(user);
                else
                    packet = new LoginPacket(user);
                // 启动连接池
                pool.start();
                // 启动端口
            	con.start();
                // 发送请求包              
                pool.send(MAIN.name, packet, false);
            } catch (Exception e) {
			    throw e;
			}
        }
    }
    
    /**
     * 退出QQ会话
     */
    public void logout() {
        // 得到当前登录状态
        boolean isLoggedIn = user.isLoggedIn();
	    // 设置用户状态
    	if(!loginRedirect)
	    	user.setLoginToken(null);    
    	user.setLoggedIn(false);    	
    	// 设置正在登录标志为false
    	logging = false;
    	loginRedirect = false;

    	// 清空发送队列
    	if(pool != null) {
    		IConnection con = pool.getConnection(MAIN.name);
    		if(con != null) {
    			con.clearSendQueue();
    			// 如果已经登录了,则发送logout包
    			if(isLoggedIn) {
    				LogoutPacket packet = new LogoutPacket(user);
    				pool.send(MAIN.name, packet, false);
    			}
    		}    		
    		pool.dispose();
    	}
    	pool = poolFactory.newPool();
    	
    	// 执行清理工作
    	if(keepAliveFuture != null) {
    		keepAliveFuture.cancel(false);
    		keepAliveFuture = null;
    	}
    	resendTrigger.clear();
    }
    
    /**
     * 释放这个QQClient,如果不继续使用QQClient,则必须释放此客户端以便
     * SingleExecutor释放资源
     */
    public void release() {
    	executor.decreaseClient();
    }

    /**
     * 处理Keep Alive成功信息,对Keep Alive Success,QQClient不作什么
     * 进一步的分析,只是顺便刷新一下好友状态
     * 
     * @param e
     */
    private void processKeepAliveSuccess(QQEvent e) {
        GetOnlineOpPacket packet = new GetOnlineOpPacket(user);
        sendPacket(packet);
    }

	/**
	 * 处理登陆成功事件
	 */
	private void processLoginSuccess() {
	    if(!user.isLoggedIn()) {
			user.setLoggedIn(true);
			this.logging = false;
			// 请求密钥
			requestKey(QQ.QQ_SUB_CMD_REQUEST_UNKNOWN03_KEY);
			requestKey(QQ.QQ_SUB_CMD_REQUEST_FILE_AGENT_KEY);
			requestKey(QQ.QQ_SUB_CMD_REQUEST_UNKNOWN06_KEY);
			requestKey(QQ.QQ_SUB_CMD_REQUEST_UNKNOWN07_KEY);
			requestKey(QQ.QQ_SUB_CMD_REQUEST_UNKNOWN08_KEY);
			// 得到我的信息
			GetUserInfoPacket guiPacket = new GetUserInfoPacket(user);
	        sendPacket(guiPacket);
			// 手动更改我的在线状态,虽然服务器可能也会给我发送这样的信息
			ChangeStatusPacket csPacket = new ChangeStatusPacket(user);
			csPacket.setShowFakeCam(user.isShowFakeCam());
	        sendPacket(csPacket);	   
	        // 调度keep alive动作
	        keepAliveFuture = executor.scheduleWithFixedDelay(keepAliveTrigger, QQ.QQ_INTERVAL_KEEP_ALIVE, QQ.QQ_INTERVAL_KEEP_ALIVE, TimeUnit.MILLISECONDS);
	    }
	}

    /**
     * 处理普通消息事件,只是发一个确认而已
     * 
     * @param e
     */
    private void processReceiveIM(QQEvent e) {
        // 得到包
        ReceiveIMPacket packet = (ReceiveIMPacket)e.getSource();
        
        // 生成确认包
        ReceiveIMReplyPacket reply = new ReceiveIMReplyPacket(packet.reply, user);
        reply.setSequence(packet.getSequence());
		pool.send(MAIN.name, reply, false);	
    }

	/* (non-Javadoc)
	 * @see edu.tsinghua.lumaqq.QQListener#qqEvent(edu.tsinghua.lumaqq.QQEvent)
	 */
	public void qqEvent(QQEvent e) {

⌨️ 快捷键说明

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