A simple BitTorrent client implementation (VI): Peer Manager and peer implementation

Source: Internet
Author: User
Tags readable
Peer Manager and peer

Peer is the most complex part of the whole BT communication, which is mainly the sending of various messages and some choke and unchoke strategies, piece selection strategy and so on. Peer manager is used to manage peer, which maintains multiple peer for remote communication. Peer Implementation

The peer in this program is implemented by the Cpeerlink class. Some important members of the Cpeerlink class are described below:
M_bamchoking: Do I block peer,true to say choke, otherwise unchoke.
M_baminterested: I am interested in peer, true means interested, otherwise not interested.
Whether M_bpeerchoking:peer block me, true means choke, otherwise unchoke.
Whether M_bpeerinterested:peer is interested in me, true means interested, otherwise not interested.
M_clpiecerequest: Saved some piece details I requested from peer.
M_lstpeerpiecerequest: Save the piece details peer asked me for.
The entire peer communication process is as follows:
(1) A descriptor that joins the peer and adds its sockets to the monitoring of the synchronization event separator is set up for its monitoring.

void Cpeerlink::connect (const char *ipaddr, int nport)
{
    csocket::createtcpsocket ();
    Csocket::setreactor (M_ppeermanager->gettorrenttask ()->getsocketreactor ());

    M_stripaddr = ipaddr;
    M_nport = Nport;

    Csocket::sethandlemask (write_mask);
    Csocket::connect (ipaddr, nport);
    M_npeerstate = ps_connecting;

    M_nconntimeoutid = Getreactor ()->addtimer (this, 10000, true);
}

(2) Synchronous event separator constant polling descriptor set.

nret = Select (M_nmaxsocketfd + 1, &m_rset, &m_wset, NULL, &tmval);

(3) The synchronization event separator detects that the socket is writable, indicating that the connection peer succeeded. Invokes and sets the socket to be readable, which is to add the socket to the read descriptor set.

 if (Fd_isset (*it)->gethandle (), &m_wset)) {int n
                Res = (*it)->handlewrite ();
                    if (nres = = 1) {(*it)->handleclose ();
                    (*it)->setreactor (NULL);
                    (*it)->close ();
                Continue }
            }
int cpeerlink::handlewrite () {if (m_npeerstate = = ps_connecting) {m_npeerstate
        = ps_established;

        Removehandlemask (Write_mask);

        OnConnect ();
    return 0;
    } M_bcanwrite = true;
return 0;

    } void Cpeerlink::onconnect () {sethandlemask (read_mask);
    M_strsendbuffer.clear ();
    M_strrecvbuffer.clear ();

    m_bhandshaked = false;

    M_clpiecerequest.createpiecerequestlist (-1, 0, 0);
    M_bamchoking = true;
    m_baminterested = false;
    M_bpeerchoking = true;

    m_bpeerinterested = false;
    M_ndownloadcount = 0;
    M_nuploadcount = 0;
    M_nlastdownloadcount = 0;
    M_nlastuploadcount = 0;
    M_nlastuploadcount = 0;
    m_ndownloadspeed = 0;

    m_nuploadspeed = 0;

    M_lllastcountspeedtime = GetTickCount ();
    M_bcanread = false;

    M_bcanwrite = true;

    M_ppeermanager->gettorrenttask ()->getratemeasure ()->addclient (this);
Sendhandshake (); }

(4) Send handshake message.

void Cpeerlink::sendhandshake ()
{
    char szbuff[68];
    memset (szbuff, 0, sizeof (szbuff));

    Szbuff[0] =;
    strncpy (Szbuff + 1, "BitTorrent Protocol");
    strncpy (Szbuff +,
            (const char *) M_ppeermanager->gettorrenttask ()->gettorrentfile ()->getinfohash (),
            );
    strncpy (Szbuff + +,
            (const char *) M_ppeermanager->gettorrenttask ()->getpeerid (). C_STR ()
            ;

    SendData (Szbuff, sizeof (Szbuff));
}

(5) The synchronous event separator monitors the sockets to be readable, handles various messages, such as handshake, choke, unchoke, piece, and so on.

 if (Fd_isset (*it)->gethandle (), &m_rset)) {int NR
               Es = (*it)->handleread ();
                   if (nres = = 1) {(*it)->handleclose ();
                   (*it)->setreactor (NULL);
                   (*it)->close ();
               Continue }
            }
int Cpeerlink::D oread (Long long llcount) {int nreadcount = 0;

    Char *pbuff = new Char[recv_buffer_size];
    for (; nreadcount < llcount;)
        {int nreadsize = recv_buffer_size;
        if (Nreadsize > Llcount-nreadcount) {nreadsize = Llcount-nreadcount;
        int nret = recv (GetHandle (), Pbuff, nreadsize, 0);
            if (nret = = 0) {closelink ();
            Delete[] Pbuff;
        return nreadcount;
                } if (nret = = 1) {if (errno = = eagain) {M_bcanread = false;
            Break
            } if (errno = = eintr) {continue;
            } closelink ();
            Delete[] Pbuff;
        return nreadcount;
            } if (Nret > 0) {nreadcount + = Nret;
            M_ndownloadcount + = Nret; M_ppeermanager->gettorrenttask ()->adddOwnloadcount (Nret);
        M_strrecvbuffer.append (const char *) Pbuff, nret);

    }} delete[] Pbuff;

    Procrecvdata ();
        if (m_bcanread) {if (Gethandlemask () & Read_mask) {removehandlemask (read_mask); } else {if (!
        Gethandlemask () & Read_mask)) {sethandlemask (read_mask);
} return Nreadcount; }

For information processing, take the request message as an example:
Request:

int cpeerlink::P roccmdrequest (void *pdata, int ndatalen) {if (Ndatalen!= 12) {
    return-1;
    } if (m_bamchoking) {return 0;
    int nindex = * (int *) pData);
    nindex = Ntohl (nindex);
    int noffset = * ((int *) ((char *) PData + 4));
    Noffset = Ntohl (Noffset);
    int nlen = * ((int *) ((char *) PData + 8));

    Nlen = Ntohl (Nlen);
    List<peerpiecerequest>::iterator it = M_lstpeerpiecerequest.begin (); for (; it!= m_lstpeerpiecerequest.end (); ++it) {if (It->nindex = = nindex && It->noffset = = NOf
        Fset) {break;
        } if (it = = M_lstpeerpiecerequest.end ()) {peerpiecerequest strequst;
        Strequst.nindex = nindex;
        Strequst.noffset = Noffset;

        Strequst.nlen = Nlen;
    M_lstpeerpiecerequest.push_back (Strequst);

    } dopiecesend ();
return 0; }

Here you use M_lstpeerpiecerequest to save peer's requested piece and save it every time you receive the message. facilitates the subsequent sending of data. Remove the message if it has been sent or received a cancel message sent by peer. Peer Manager Implementation

Peer Manager is implemented by the Cpeermanager class, which mainly does the following two things:
(1) Add two timers at startup, one for checking peer connection status. Another for choke and Unchoke peer.

BOOL Cpeermanager::startup ()
{
    pthread_mutexattr_t attr;
    Pthread_mutexattr_init (&attr);
    Pthread_mutexattr_settype (&attr, pthread_mutex_recursive_np);
    Pthread_mutex_init (&m_mutexunusedpeer, &attr);
    Pthread_mutexattr_destroy (&attr);

    M_nconnecttimerid = M_ptorrenttask->getsocketreactor ()->addtimer (this, Watts,
            false);

    M_nchoketimerid = M_ptorrenttask->getsocketreactor ()->addtimer (this, 10000,
            false);

    return true;
}

(2) Add peer to the peer list.

void Cpeermanager::addpeerinfo (const char *pipaddr, int nport)
{
    string strpeerlinkid = Genpeerlinkid (pipaddr, Nport);
    if (peerexists (strpeerlinkid))
    {return
        ;
    }

    PeerInfo Stpeerinfo;
    Stpeerinfo.strlinkid = Strpeerlinkid;
    Stpeerinfo.stripaddr = pipaddr;
    Stpeerinfo.nport = Nport;
    Stpeerinfo.ppeerlink = NULL;

    Pthread_mutex_lock (&m_mutexunusedpeer);
    M_mapunusedpeer[strpeerlinkid] = Stpeerinfo;
    Pthread_mutex_unlock (&m_mutexunusedpeer);
}

Peer and peer manager's introduction to the end, you can go to see the code. Writing is simpler, and it's not complicated.
Program source code download address: http://download.csdn.net/detail/zxywd/9415711

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.