diff --git a/btpd/net.c b/btpd/net.c
index 081cdc4..2b89de4 100644
--- a/btpd/net.c
+++ b/btpd/net.c
@@ -129,6 +129,7 @@ net_write(struct peer *p, unsigned long wmax)
     while (bcount > 0) {
 	unsigned long bufdelta = nl->nb->len - p->outq_off;
 	if (bcount >= bufdelta) {
+	    peer_sent(p, nl->nb);
 	    if (nl->nb->type == NB_TORRENTDATA) {
 		p->tp->uploaded += bufdelta;
 		p->rate_from_me[btpd.seconds % RATEHISTORY] += bufdelta;
diff --git a/btpd/peer.c b/btpd/peer.c
index 6f1eb3d..3eb53c9 100644
--- a/btpd/peer.c
+++ b/btpd/peer.c
@@ -86,6 +86,10 @@ peer_unsend(struct peer *p, struct nb_link *nl)
 {
     if (!(nl == BTPDQ_FIRST(&p->outq) && p->outq_off > 0)) {
 	BTPDQ_REMOVE(&p->outq, nl, entry);
+	if (nl->nb->type == NB_TORRENTDATA) {
+	    assert(p->npiece_msgs > 0);
+	    p->npiece_msgs--;
+	}
 	nb_drop(nl->nb);
 	free(nl);
 	if (BTPDQ_EMPTY(&p->outq)) {
@@ -100,6 +104,21 @@ peer_unsend(struct peer *p, struct nb_link *nl)
 	return 0;
 }
 
+void
+peer_sent(struct peer *p, struct net_buf *nb)
+{
+    switch (nb->type) {
+    case NB_TORRENTDATA:
+	assert(p->npiece_msgs > 0);
+	p->npiece_msgs--;
+	break;
+    case NB_UNCHOKE:
+	assert(p->npiece_msgs == 0);
+	p->flags &= ~PF_NO_REQUESTS;
+	break;
+    }
+}
+
 void
 peer_request(struct peer *p, uint32_t index, uint32_t begin, uint32_t len)
 {
@@ -345,10 +364,18 @@ void
 peer_on_request(struct peer *p, uint32_t index, uint32_t begin,
     uint32_t length)
 {
-    off_t cbegin = index * p->tp->meta.piece_length + begin;
-    char * content = torrent_get_bytes(p->tp, cbegin, length);
-    peer_send(p, nb_create_piece(index, begin, length));
-    peer_send(p, nb_create_torrentdata(content, length));
+    if ((p->flags & PF_NO_REQUESTS) == 0) {
+	off_t cbegin = index * p->tp->meta.piece_length + begin;
+	char * content = torrent_get_bytes(p->tp, cbegin, length);
+	peer_send(p, nb_create_piece(index, begin, length));
+	peer_send(p, nb_create_torrentdata(content, length));
+	p->npiece_msgs++;
+	if (p->npiece_msgs >= MAXPIECEMSGS) {
+	    peer_send(p, btpd.choke_msg);
+	    peer_send(p, btpd.unchoke_msg);
+	    p->flags |= PF_NO_REQUESTS;
+	}
+    }
 }
 
 void
diff --git a/btpd/peer.h b/btpd/peer.h
index dd9db0f..675c9a8 100644
--- a/btpd/peer.h
+++ b/btpd/peer.h
@@ -1,22 +1,23 @@
 #ifndef BTPD_PEER_H
 #define BTPD_PEER_H
 
-#define PF_I_WANT	0x01	/* We want to download from the peer */
-#define PF_I_CHOKE	0x02	/* We choke the peer */
-#define	PF_P_WANT	0x04	/* The peer wants to download from us */
-#define	PF_P_CHOKE	0x08	/* The peer is choking us */
-#define PF_ON_READQ	0x10
-#define PF_ON_WRITEQ	0x20
-#define PF_ATTACHED	0x40
-#define PF_WRITE_CLOSE	0x80	/* Close connection after writing all data */
+#define PF_I_WANT	  0x1	/* We want to download from the peer */
+#define PF_I_CHOKE	  0x2	/* We choke the peer */
+#define PF_P_WANT	  0x4	/* The peer wants to download from us */
+#define PF_P_CHOKE	  0x8	/* The peer is choking us */
+#define PF_ON_READQ	 0x10
+#define PF_ON_WRITEQ	 0x20
+#define PF_ATTACHED	 0x40
+#define PF_WRITE_CLOSE	 0x80	/* Close connection after writing all data */
+#define PF_NO_REQUESTS	0x100
 
 #define RATEHISTORY 20
-
+#define MAXPIECEMSGS 128
 #define MAXPIPEDREQUESTS 10
 
 struct peer {
     int sd;
-    uint8_t flags;
+    uint16_t flags;
     uint8_t *piece_field;
     uint32_t npieces;
     uint32_t nwant;
@@ -28,6 +29,7 @@ struct peer {
     struct nb_tq my_reqs;
 
     unsigned nreqs_out;
+    unsigned npiece_msgs;
 
     size_t outq_off;
     struct nb_tq outq;
@@ -50,6 +52,7 @@ BTPDQ_HEAD(peer_tq, peer);
 
 void peer_send(struct peer *p, struct net_buf *nb);
 int peer_unsend(struct peer *p, struct nb_link *nl);
+void peer_sent(struct peer *p, struct net_buf *nb);
 
 void peer_unchoke(struct peer *p);
 void peer_choke(struct peer *p);