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