bt分析之bt种子发布---做种(2)

先来一张图:

bt分析之bt种子发布---做种(2)_第1张图片

在此之前,了解下bt客户端与tracker的交互

http://my.oschina.net/blackylin/blog/113513

1.解析种子,放到SharedTorrent对象中

/**1.解析torrent文件到SharedTorrent对象中,并分片段*/
			BtClient_ShareTorrent=SharedTorrent.fromFile(
					new File(torrentPath),
					new File(sourceFileParentPath));

        /**发布种子文件
	 * @param torrentPath 	         torrent文件存放位置
	 * @param sourceFileParentPath   共享文件的父路径,如:/share1/share2/file.pdf 
	 *                                  则取/share1/share2  
	 * @return  Client
	 * */
public Client shareTorrentFile(String torrentPath, String sourceFileParentPath) {
		//注:这里sourceFileParentPath 如果是自己做种时,这个路径一定得是源文件所在的目录
		//如果是添加torrentFile而下载时,为下载文件目录
		this.saveDownloadPath=sourceFileParentPath;
		this.torrentPath=torrentPath;
		
		try {
			/**1.解析torrent文件到SharedTorrent对象中,并分片段*/
			BtClient_ShareTorrent=SharedTorrent.fromFile(
					new File(torrentPath),
					new File(sourceFileParentPath));
			
			/**2.初始化客户端,并注册监听*/
    		BtClient_Client = new Client(Client.getIPv4Address("eth0"),BtClient_ShareTorrent);

			/**3.连接tracker服务器做种或下载*/
    		BtClient_Client.share();
			if (ClientState.ERROR.equals(BtClient_Client.getState())) {
				System.exit(1);
			}
		} catch (Exception e) {
			Log.e(TAG, "Fatal error: "+ e.getMessage(), e);
			System.exit(2);
		}
		return BtClient_Client;
	}

2.在第2步,初始化客户端时,首先注册一个ConnectionHandler连接通道,等待其他peers来连接,这样就相当于自己变成一个服务端(故此既是客户端也是服务端)

		/**提供其他peers连接交互的通道*/
		this.service = new ConnectionHandler(this.torrent, id, address);
		this.service.register(this);

再注册announce的通道负责去请求Tracker服务器

this.announce = new Announce(this.torrent, this.self);
		this.announce.register(this);

/**
	 * Initialize the BitTorrent client.
	 *
	 * @param address The address to bind to.
	 * @param torrent The torrent to download and share.
	 */
	public Client(InetAddress address, SharedTorrent torrent)
		throws UnknownHostException, IOException {
		this.torrent = torrent;
		this.state = ClientState.WAITING;

		String id = Client.BITTORRENT_ID_PREFIX + UUID.randomUUID()
			.toString().split("-")[4];

		// Initialize the incoming connection handler and register ourselves to
		// it.
		
		/**提供其他peers连接交互的通道*/
		this.service = new ConnectionHandler(this.torrent, id, address);
		this.service.register(this);

		this.self = new Peer(
			this.service.getSocketAddress()
				.getAddress().getHostAddress(),
			(short)this.service.getSocketAddress().getPort(),
			ByteBuffer.wrap(id.getBytes(Torrent.BYTE_ENCODING)));
		// Initialize the announce request thread, and register ourselves to it
		// as well.
		this.announce = new Announce(this.torrent, this.self);
		this.announce.register(this);

		logger.info("BitTorrent client [{}] for {} started and " +
			"listening at {}:{}...",
			new Object[] {
				this.self.getShortHexPeerId(),
				this.torrent.getName(),
				this.self.getIp(),
				this.self.getPort()
			});

		//
		this.peers = new ConcurrentHashMap<String, SharingPeer>();
		this.connected = new ConcurrentHashMap<String, SharingPeer>();
		this.random = new Random(System.currentTimeMillis());
	}

客户端初始化完成后,调用share()启动Client线程服务,在线程run()方法中,继续启动刚注册的几个线程


	/**3.连接tracker服务器做种或下载*/
    		BtClient_Client.share();


具体代码请看到Client.java里的run()方法

3.第三步,得到tracker服务器的响应,在代码com.turn.ttorrent.announce.HTTPTrackerClient.java中line:106行

		HttpURLConnection conn = null;
		InputStream in = null;
		try {
			//连接tracker服务器,成功返回200状态码
			conn = (HttpURLConnection)target.openConnection();
			in = conn.getInputStream();
			
		} catch (IOException ioe) {
			if (conn != null) {
				in = conn.getErrorStream();
			}
		}

		// At this point if the input stream is null it means we have neither a
		// response body nor an error stream from the server. No point in going
		// any further.
		if (in == null) {
			throw new AnnounceException("No response or unreachable tracker!");
		}

		try {
			//从流中得到tracker返回的消息
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			baos.write(in);
			// Parse and handle the response
			HTTPTrackerMessage message =
				HTTPTrackerMessage.parse(ByteBuffer.wrap(baos.toByteArray()));
			this.handleTrackerAnnounceResponse(message, inhibitEvents);
		} catch (IOException ioe) {
			throw new AnnounceException("Error reading tracker response!", ioe);
		} catch (MessageValidationException mve) {
			throw new AnnounceException("Tracker message violates expected " +
				"protocol (" + mve.getMessage() + ")", mve);
		} finally {
			// Make sure we close everything down at the end to avoid resource
			// leaks.
			try {
				in.close();
			} catch (IOException ioe) {
				logger.warn("Problem ensuring error stream closed!", ioe);
			}

			// This means trying to close the error stream as well.
			InputStream err = conn.getErrorStream();
			if (err != null) {
				try {
					err.close();
				} catch (IOException ioe) {
					logger.warn("Problem ensuring error stream closed!", ioe);
				}
			}
		}

这个http的请求格式如:

192.168.21.154是android机子的ip,也就是做种者的ip,tracker服务器我是在192.168.21.91上搭的,也就是我电脑的ip,上面图片就是tracker回显出的请求信息
在info_hash后的参数全部都是封装在这个target对象中

conn = (HttpURLConnection)target.openConnection();

之后再管道流中得到一个tracker响应的被bencoding编码过的数据,再解析出peers列表

//从流中得到tracker返回的消息
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			baos.write(in);
			// Parse and handle the response
			HTTPTrackerMessage message =
				HTTPTrackerMessage.parse(ByteBuffer.wrap(baos.toByteArray()));
			this.handleTrackerAnnounceResponse(message, inhibitEvents);


此时是做种,所有tracker上的信息之后seeder的信息,即做种者的信息

4、5、6:之后,就是peers连接tracker得到peers列表,里面包含peers自己和seeder的信息,与seeder建立对等连接,交换数据

下面是对等连接的分析:

待续。。。O(∩_∩)O~


你可能感兴趣的:(android,BT,torrent做种,种子发布)