<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Blog Khoa Học Máy Tính &#187; Mạng máy tính</title>
	<atom:link href="http://www.procul.org/blog/category/m%e1%ba%a1ng-may-tinh/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.procul.org/blog</link>
	<description>Tầm nhìn ta thật ngắn mà đã thấy bao thứ  để làm -- Alan Turing</description>
	<lastBuildDate>Wed, 08 Feb 2012 12:29:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Hercules chặt được hết đầu Hydra chăng?</title>
		<link>http://www.procul.org/blog/2010/12/08/hercules-ch%e1%ba%b7t-d%c6%b0%e1%bb%a3c-h%e1%ba%bft-d%e1%ba%a7u-hydra-chang/</link>
		<comments>http://www.procul.org/blog/2010/12/08/hercules-ch%e1%ba%b7t-d%c6%b0%e1%bb%a3c-h%e1%ba%bft-d%e1%ba%a7u-hydra-chang/#comments</comments>
		<pubDate>Wed, 08 Dec 2010 16:22:33 +0000</pubDate>
		<dc:creator>NQH</dc:creator>
				<category><![CDATA[Mạng máy tính]]></category>
		<category><![CDATA[Wikileaks]]></category>

		<guid isPermaLink="false">http://www.procul.org/blog/?p=2775</guid>
		<description><![CDATA[Nhiệm vụ thứ hai của Hercules là giết Hydra. Nhưng quái vật 9 đầu này mọc 2 đầu mới mỗi khi bị chặt một đầu. Wikileaks là quái vật nghìn đầu. Không có một tổ chức nào, kể cả Hercules hiện đại như chính phủ Mỹ, có thể chặt hết đầu chú Hydra này; trừ [...]]]></description>
			<content:encoded><![CDATA[<p>Nhiệm vụ thứ hai của Hercules là giết Hydra. Nhưng quái vật 9 đầu này mọc 2 đầu mới mỗi khi bị chặt một đầu. Wikileaks là quái vật <strong>nghìn</strong> đầu. Không có một tổ chức nào, kể cả Hercules hiện đại như chính phủ Mỹ, có thể chặt hết đầu chú Hydra này; trừ phi chặt luôn tay mình, nghĩa là cắt đứt Internet. Cú truy ép toàn cầu này của Hercules này còn hơn cả những gì <a href="http://www.stieglarsson.com/">Steig Larsson</a> tưởng tượng ra nhé. Nhưng Larsson vẫn thắng vì đồng chí Assange thì kém cool hơn nàng Lisbeth nhiều.</p>
<p>Bên Renesys có một <a href="http://www.renesys.com/blog/2010/12/wikileaks-moving-target.shtml">bài tóm tắt</a> rất hay. Trước khi thả rông mấy cái diplomatic cables, Wikileaks.org dùng 2 nhà cung cấp dịch vụ của Thụy Điển là <a href="http://en.wikipedia.org/wiki/Bahnhof">Bahnhof</a> và <a href="http://en.wikipedia.org/wiki/PRQ">PRQ</a>, và một ISP của Pháp là <a href="http://www.octopuce.fr/Cursys">Cursys</a>. Sau đó, cuối tháng 11, họ thêm vào Amazon <a href="http://en.wikipedia.org/wiki/Amazon_EC2">EC2 cloud</a> để mở rộng cửa đón khách. Nhà to cửa rộng, khách thì đông. Chú Hydra này có vài cái đầu tiếp khách, nhét vào Amazon một cái.</p>
<p>Doanh nhân bụng to Amazon bị Hercules dọa, đến hôm 1 tháng 12 <a href="http://aws.amazon.com/message/65348/">tống cổ một đầu</a> Hydra không chứa chấp nữa. Chú Hydra thêm vào cái đầu mới, nhét vào <a href="http://en.wikipedia.org/wiki/OVH">OVH</a> (ISP của Pháp). Thêm bọn doanh nhân bụng to đầu lắm tóc như <a href="http://www.npr.org/2010/12/05/131813224/paypal-cuts-off-wikileaks-account">Paypal</a>, Visa, Master card cũng <a href="http://www.csmonitor.com/Innovation/Horizons/2010/1207/WikiLeaks-ditched-by-MasterCard-Visa.-Who-s-next">phủi tay chạy mất</a> dép, giảm cash flow vào Wikileaks. Rồi đến chú EveryDNS cũng <a href="http://www.skepticgeek.com/miscellaneous/everydns-net-terminates-wikileaks-dns-services/">từ chối</a> không trả lời câu hỏi &#8220;IP của Wikileaks.org là gì?&#8221; luôn.</p>
<p><span id="more-2775"></span></p>
<p>Mà cái tên miền Wikileaks.org cũng rất tếu. Nếu bạn hỏi bọn root servers, bọ nó sẽ chỉ đến các authoritative name servers của EveryDNS, có nghĩa là <a href="http://www.dynadot.com/">chú registrar có trách nhiệm</a> với Wikileaks.org vẫn chưa phủi tay.</p>
<pre>[NQH] MFM:~$ dig @d0.org.afilias-nst.org ns wikileaks.org.

; &lt;&lt;&gt;&gt; DiG 9.6.0-APPLE-P2 &lt;&lt;&gt;&gt; @d0.org.afilias-nst.org ns wikileaks.org.
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 20170
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 4, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;wikileaks.org.			IN	NS

;; AUTHORITY SECTION:
wikileaks.org.		86400	IN	NS	ns1.everydns.net.
wikileaks.org.		86400	IN	NS	ns2.everydns.net.
wikileaks.org.		86400	IN	NS	ns3.everydns.net.
wikileaks.org.		86400	IN	NS	ns4.everydns.net.

;; Query time: 111 msec
;; SERVER: 199.19.57.1#53(199.19.57.1)
;; WHEN: Wed Dec  8 11:01:57 2010
;; MSG SIZE  rcvd: 115</pre>
<p>Thế nhưng các name servers của EveryDNS thì không trả lời câu hỏi về Wikileaks.org nữa.</p>
<p>Tên thì mất, nhưng mà IP address space thì vẫn sống nhăn răng. Ví dụ bạn có thể truy cập thẳng vào <code>178.21.20.8</code> thoải mái, dù có bị <a href="http://techcrunch.com/2010/11/28/wikileaks-ddos-attack/">DDoS oánh tơi tả</a>. Ngược lại cũng có một số nhóm hackers mũ &#8230; nồi, ủng hộ Wikileaks, và <a href="http://thelede.blogs.nytimes.com/2010/12/08/operation-payback-targets-mastercard-and-paypal-sites-to-avenge-wikileaks/?partner=rss&amp;emc=rss">tấn cống</a> các chú doanh nhân bụng to chân đất. MasterCard <a href="http://www.huffingtonpost.com/2010/12/08/mastercard-down-hacked-wikileaks-ddos_n_793625.html">bị oánh</a> sáng nay, chảy máu cam mất mấy tiếng.</p>
<p>Còn anh Hydra thì thêm tên: mọc ra Wikileaks.ch (Thụy Sĩ), wikileaks.de (Đức), wikileaks.eu (EU), wikileaks.fi (Phần Lan), wikileaks.nl (Hà Lan), wikileaks.pl (Ba Lan), wikileaks.se (Thụy Điển), wikileaks.to (Tonga), vân vân; Đám tên mới này trỏ vào khối địa chỉ <code>88.80.0.0/19</code> do Bahnhof chứa chấp. Một số tên trỏ vào một khối khác như <code>78.21.16.0/21</code> (của Serverius, Hà Lan), <code>46.59.0.0/17</code> (của Bahnhof, Thụy Điển), hay 213.251.128.0/18 (của OVH ở Pháp).</p>
<p>Ngoài ra, tìm một tên như wikileaks.ch chúng ta sẽ kiếm ra vài chục authoritative servers, trỏ đến các IPs khác nhau:</p>
<pre>[NQH] MFM:~$ dig @dns1.syshack.org a wikileaks.ch.

; <<>> DiG 9.6.0-APPLE-P2 <<>> @dns1.syshack.org a wikileaks.ch.
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5067
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 14, ADDITIONAL: 1

;; QUESTION SECTION:
;wikileaks.ch.			IN	A

;; ANSWER SECTION:
wikileaks.ch.		1800	IN	A	178.21.20.9
wikileaks.ch.		1800	IN	A	213.251.145.96
wikileaks.ch.		1800	IN	A	46.59.1.2
wikileaks.ch.		1800	IN	A	178.21.20.8

;; AUTHORITY SECTION:
wikileaks.ch.		1800	IN	NS	ns1.twisted4life.com.
wikileaks.ch.		1800	IN	NS	v217241437.yourvserver.net.
wikileaks.ch.		1800	IN	NS	ns1.buzzernet.net.
wikileaks.ch.		1800	IN	NS	ns1.pcdog.ch.
wikileaks.ch.		1800	IN	NS	lou.porcus.ch.
wikileaks.ch.		1800	IN	NS	dns2.syshack.org.
wikileaks.ch.		1800	IN	NS	dns.wikileaks.ch.
wikileaks.ch.		1800	IN	NS	s2.s3cr3t.de.
wikileaks.ch.		1800	IN	NS	elrido.no-ip.org.
wikileaks.ch.		1800	IN	NS	ns2.easydns.com.
wikileaks.ch.		1800	IN	NS	dns1.syshack.org.
wikileaks.ch.		1800	IN	NS	arjeplog.scnr.ch.
wikileaks.ch.		1800	IN	NS	marmotta.brabbel.ch.
wikileaks.ch.		1800	IN	NS	dns2.easydns.net.
</pre>
<p>Rồi nếu bạn vào một trong số các tên trên, bạn sẽ thấy một danh sách của hơn một nghìn các mirror sites, có cả IPv6. </p>
<p>Đó là chưa kể đám torrents nhãi nhép đông nhung nhúc không cách chi giết được. Như mấy sợi lông của Tề Thiên. </p>
<p>Hercules. Đừng hòng chặt đầu rắn.</p>
<p>Nhưng, có một điều Hercules có thể làm được. Thả ra nghìn vạn rắn ... giả. Chúng ta sẽ không còn biết rắn nào thật rắn nào giả nữa. Maximize entropy <img src='http://www.procul.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.procul.org/blog/2010/12/08/hercules-ch%e1%ba%b7t-d%c6%b0%e1%bb%a3c-h%e1%ba%bft-d%e1%ba%a7u-hydra-chang/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Tác động lớn của một byte</title>
		<link>http://www.procul.org/blog/2010/10/13/1-byte/</link>
		<comments>http://www.procul.org/blog/2010/10/13/1-byte/#comments</comments>
		<pubDate>Wed, 13 Oct 2010 20:58:00 +0000</pubDate>
		<dc:creator>NQH</dc:creator>
				<category><![CDATA[Mạng máy tính]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Mạng]]></category>
		<category><![CDATA[TCP]]></category>

		<guid isPermaLink="false">http://www.procul.org/blog/?p=2363</guid>
		<description><![CDATA[TCP là một trong những giao thức phổ dụng nhất của mạng máy tính. Mỗi lần ta click vào một trang web mới là có (ít nhất) một kết nối TCP được thiết lập từ trình duyệt đến máy chủ. Vì thế, hiệu suất hoạt động của TCP ảnh hưởng trực tiếp đến toàn bộ [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://en.wikipedia.org/wiki/Transmission_Control_Protocol">TCP</a> là một trong những giao thức phổ dụng nhất của mạng máy tính. Mỗi lần ta click vào một trang web mới là có (ít nhất) một kết nối TCP được thiết lập từ trình duyệt đến máy chủ. Vì thế, hiệu suất hoạt động của TCP ảnh hưởng trực tiếp đến toàn bộ mấy tỉ người dùng Internet. Thiết kế một giao thức phổ dụng như TCP quả thật rất khó, vì thế <a href="http://www.procul.org/blog/2005/08/26/bai-gi%e1%ba%a3ng-nhan-gi%e1%ba%a3i-turing-c%e1%bb%a7a-cerf-va-kahn/">Cerf và Kahn được giải thưởng Turing</a> rất xứng đáng.</p>
<p><span id="more-2363"></span></p>
<p>Dù có viễn kiến vĩ đại, Cerf và Kahn hiển nhiên không phải là những người duy nhất đóng góp vào TCP. Họ chỉ đặt một cái nền. Còn trong vòng 40 năm nay có biết bao nhiêu người đã đóng góp vào cải thiện nhiều mặt của TCP. Thật ra chỉ cần đến khoảng cuối những năm 80 là &#8220;diện mạo&#8221; của TCP đã rất khác so với hồi Cerf và Kahn thiết kết nó.</p>
<p>Xem qua <a href="http://tools.ietf.org/html/rfc4614">quá trình tiến hóa của TCP</a>, một điều hiển hiện là việc giữ cho một giao thức hoạt động đúng như ý mình muốn thật là nan giải. Có hai lý do chính, đều liên quan đến sự đa dạng. Thứ nhất là sự đa dạng của các loại mục tiêu khác nhau mà ta muốn giao thức đạt được: hiệu suất cao, tính bảo mật tốt, dùng ít tài nguyên mạng và tài nguyên tính toán, xử lý cực nhanh với tốc độ ánh sáng, giữ cho phiên bản mới của giao thức tương hợp với phiên bản cũ, vân vân. Thứ hai là sự đa dạng (và đa nguyên) của những nhóm nghiên cứu và các công ty đóng góp vào cải tiến về lý thuyết và lập trình giao thức trên thực tế. Làm thế nào để đảm bảo rằng TCP do Microsoft lập trình chạy tốt với TCP của Linux, của BSD, của SunOS, MacOSX, cùng với cơ man nào là các phiên bản khác nhau của chúng. Khó nữa là chúng ta không có một bộ khung lý thuyết nào khả thi để có thể xác minh xem một thiết kế giao thức cho trước là thiết kế &#8220;tốt&#8221;: các bộ phận hoạt động đồng bộ với nhau, các phiên bản hoạt động không ngáng giò nhau, vân vân.</p>
<p>Khó thế đấy. Vậy mà, khi ta click vào <a href="http://www.procul.org/blog">http://www.procul.org/blog</a> ta thấy ngay cái blog này. Bất kể ta chạy máy gì, hệ điều hành gì. Nó cho thấy sự tráng kiện (robustness) của giao thức TCP và của các giao thức mạng nói chung.</p>
<p>Thế nhưng, có khi các bộ phận của TCP thật sự không hoạt động đồng bộ với nhau, thậm chí chỉ vì một byte dữ liệu. Khi điều này xảy ra, nếu không hiểu rõ TCP và các ngóc ngách của nó thì không thể hiểu tại sao lại có những hiện tượng &#8220;ma quái&#8221; như vậy. Câu chuyện sau đây chỉ là một vị dụ.</p>
<p><a href="http://www.stuartcheshire.org/papers/NagleDelayedAck/">Chuyện</a> như sau. Một nhóm kỹ sư muốn thử nghiệm hiệu suất hoạt động của một hệ thống Wifi. Họ viết một chương trình nhỏ để gửi dữ liệu giữa hai máy dùng hệ thống Wifi nọ. Chương trình thiết lập một kết nối TCP giữa hai máy, xong rồi bên gửi gửi đi 100KB, bên nhận gửi lại một gói ký nhận nhỏ, rồi bên gửi lại gửi đi 100KB kế tiếp, vân vân. Mục tiêu là thực hiện gửi nhận như vậy liên tục một thời gian xem tốc độ truyền là bào nhiêu.</p>
<p>Kết quả: hệ thống Wifi này trên Windows XP đạt được tốc độ 3.5Mbps, còn trên MacOSX chỉ đạt được 2.7Mbps. Trong ngữ cảnh của họ thì 3.5Mbps là tốt. 2.7Mbps không tốt.</p>
<p>Vậy Windows XP có bộ TCP tốt hơn MacOSX? (Giả sử thẻ mạng và các thứ khác tương tự nhau.)</p>
<p>Không. Sau vài lần nghịch với các tham số. Họ giảm 100KB xuống còn 99,912 bytes (để gửi một đợt trước khi nhận gói xác minh). Về nguyên tắc, thay vì 100KB một vòng, ta thử 99KB một vòng thì tốc độ không nên có thay đổi gì dáng kể. Thế mà tốc độ của MacOSX tự nhiên tăng lên đến 5.2Mbps: hơn Windows và gần gấp đôi tốt độ cũ. Thú vị hơn nữa, nếu thay 99,912 bytes bằng 99,913 bytes một đợt thì tốc độ của MacOSX lại giảm xuống 2.7Mbps như xưa.</p>
<p><strong>1 byte mà có thể tăng tốc TCP của Mac gấp đôi? Chuyện gì xảy ra?</strong></p>
<p>Số là, trong mấy trăm cái mẹo cải thiện hiệu suất được đưa vào TCP trong 40 năm qua, có 4 cái mẹo tương tác với nhau rất độc đáo tạo ra hiện tượng trên.</p>
<p>Để mô tả 4 cái mẹo này, trước hết chúng ta lược qua xem TCP làm việc thế nào. Đại khái, TCP là một giao thức cung cấp dịnh vụ tin cậy cho &#8220;khách hàng&#8221; là các ứng dụng (như web browser, server, Media player, và rất nhiều các ứng dụng mạng khác). Để tạo ra dịch vụ tin cậy, TCP gửi dữ liệu giữa hai đầu gửi-nhận và bắt bên nhận gửi lại các mẩu xác minh là đã nhận (acknowledgements, viết tắt là ACK). Các mẩu dữ liệu của TCP tiếng Anh gọi là segments. Các mẩu dữ liệu được nhét vào các &#8220;gói dữ liệu&#8221;, như là các phong bì mà bên trong chứa dữ liệu còn bên ngoài chứa thông tin điều khiển và địa chỉ gửi nhận. Bao bì tốn khoảng 20 bytes, cộng thêm 20 bytes bao bì của mạng nữa là khoảng 40 bytes cho mỗi gói dữ liệu.</p>
<p><strong>Mẹo 1: kích thước từng mẩu dữ liệu</strong>. Một phong bì do TCP gửi không thể chứa nhiều dữ liệu quá. Tại vì các gói dữ liệu đi qua nhiều loại mạng khác nhau. Mỗi loại mạng có kích thước gói tối đa khác nhau. Ví dụ mang Ethernet có kích thước tối đa là 1500 bytes, mạng X25 có kích thước gói tối đa là 576 bytes, vân vân. Một trong các lý do mà các mạng giới hạn kích thước gói dữ liệu là vì nếu kích thước gói lớn quá thì mỗi lần đường truyền bị lỗi gì ta phải gửi lại toàn bộ gói. Gói càng lớn thì xác suất nó bị lỗi càng cao, mà gửi lại gói to thì tốn tài nguyên hơn gửi lại gói nhỏ. Thế cho nên, nếu TCP gửi một cái phong bì khổng lồ thì đến mạng có giới hạn kích thước phong bì nó sẽ bị băm nhỏ ra thành nhiều gói nhỏ. Mỗi gói nhỏ tốn một phong bì riêng. Và như thế thì rất tốn. Túm lại, TCP có một biến số gọi là MSS để lưu trữ kích thước mẩu lớn nhất (của một kết nối). Có <a href="http://tools.ietf.org/html/rfc1191">các thuật toán</a> để xác định MSS nên là bao nhiêu cho mỗi kết nối. Nếu không chạy thuật toán thì trị mặc định là 576 &#8211; 40 = 536, trong đó 576 là do X25, còn 40 là kích thước bao bì của TCP/IP như đã nói ở trên. Nếu chỉ truyền trên Ethernet thì MSS nên là 1500-40 = 1460.</p>
<p><strong>Mẹo 2: thuật toán Nagle</strong>. Thử tưởng tượng một khách hàng của TCP cứ thích đưa mỗi lần vài bytes cho TCP để gửi qua bên nhận. Các ứng dụng như <code>telnet, ssh, rlogin</code> lấy inputs từ chúng ta. Chúng ta gõ bàn phím rất chậm (tính theo tốc độ máy). Người gõ nhanh nhất thế giới cũng chỉ gõ được khoảng 150 từ một phút, vị chi là khoảng vài chục đến vài trăm mili-giây một ký tự. Do đó, hoàn toàn có khả năng là ứng dụng sẽ &#8220;đưa cho&#8221; TCP từng ký tự một, cứ khoảng 100-mili giây một ký tự.  Mỗi lần tải một mẩu dữ liệu 1 ký tự, TCP phải tốn ít nhất 40 bytes bao bì cho nội dung thư. Tỉ lệ phí hoài là 40/41, gần bằng tỉ lệ phí hoàn cho Vinashin. Rất tốn băng thông! Do đó, hồi 1984 John Nagle <a href="http://www.faqs.org/rfcs/rfc896.html">đề nghị</a> là TCP nên tích lũy một ít &#8220;hàng họ&#8221; (nghĩa là, ký tự) trước khi gửi. Ít nhất, nếu có một phong bì gửi trước đó mà chưa có hồi âm thì khoan hẵng gửi phong bì ít hàng hiện tại. Chờ hồi âm của phong bì trước, xong rồi hẵng gửi phong bì mới. Lý do là, trong thời gian chờ hồi âm, nhỡ đâu chú khách hàng lại tuồn thêm cho vài ký tự để đóng chung vào một gói thì đỡ tốn phí vận chuyển. Còn trong trường hợp phong bì đã đầy (MSS) thì gửi luôn không cần chờ.</p>
<p>(Mấy bác chuyên môn đánh áo phông bàn chải bên Đông Âu hồi xưa chắc chắn đã hiểu rõ bài toán đóng hàng này.)</p>
<p><strong>Mẹo 3: hồi âm muộn (Delayed ACK)</strong>. Ở phía bên nhận, để tiết kiệm phí vận chuyển thì TCP thường cố gắng đóng gói cả hồi âm lẫn dữ liệu chiều ngược (gọi là piggy-backing) gửi chung vào một gói. Ví dụ như sau khi nhận một thư từ browser, web-server đọc lên một file nào đó (index.html chẳng hạn) và gửi lại cho browser. Nếu TCP đừng hồi âm ngay, chờ một xíu cho chú server đọc đĩa, thì có luôn cả index.html mang cùng với hồi âm về. Do đó, chuẩn TCP có cái <a href="http://www.faqs.org/rfcs/rfc1122.html">mẹo hồi âm muộn</a>, bắt bên nhận chờ khoảng 200ms đến 500ms trước khi hồi âm một mẩu dữ liệu từ bên kia. Nhưng nếu trong thời gian chờ mà nhận thêm được một thư nữa thì hồi âm cả hai ngay. (Nếu không, bên kia tưởng thư mất gửi lại mất công lắm.) Đây là luật <em>hồi âm kép</em>.</p>
<p><strong>Mẹo 4: nhãn thời gian (timestamp option)</strong>. Để đảm bảo độ tin cậy, TCP cần biết xem thư gửi đi đã nhận được chưa. Nếu thư bị mất, hoặc hồi âm bị mất thì không nhận được hồi âm. Do đó, TCP cần có một cái đồng hồ báo mất. Khi đồng hồ reng leng keng thì gửi thư lại. Nếu thời khoảng gửi lại quá bé thì không tốt: tại vì có thể hồi âm đang trên đường về, chưa chi đã gửi lại. Nếu thời khoảng gửi lại quá dài thì cũng không tốt: thư đã mất mà không gửi lại luôn còn chờ gì nữa? Do đó, TCP cần một cơ chế để ước lượng thời gian khứ hồi là bao nhiêu, xong rồi đặt thời khoảng cho đồng hồ gửi lại cỡ chừng thời gian khứ hồi cộng với một khoảng đệm cho chắc. (<a href="http://www.faqs.org/rfcs/rfc2988.html">Thuật toán ước lượng thời khoảng khứ hồi</a> phức tạp hơn một chút, nhưng đại khái là thế.) Làm thế nào để đo thời gian khứ hồi? <em>Cách thứ nhất</em> là gửi thư, rồi khi nhận được hồi âm thì xem đó là thời gian khứ hồi. Nhưng mà nếu thư bị mất, phải gửi lại, rồi nhận được hồi âm, thì mình không biết là hồi âm cho thư cũ hay thư mới. Ngoài ra, nếu bên nhận lại dùng mẹo hồi âm muộn thì ước lượng thời gian khứ hồi của mình bị sai đi. Còn nữa, TCP thường gửi nhiều thư cùng một lúc, và nếu dùng một đồng hồ cho mỗi thư thì rất phức tạp và tốn tài nguyên. <em>Cách thứ hai</em> là mỗi lần gửi thư đi thì dán tem chứa thời điểm hiện tại vào đó. Bên nhận, trước khi hồi âm, lấy tem của thư bỏ vào hồi âm. Khi nhận được hồi âm thì bên gửi chỉ cần lấy thời điểm hiện tại trừ đi giá trị tem là biết thời khoảng khứ hồi. Cách đo thời khoảng khứ hồi dùng nhãn thời gian này tốt hơn, nhưng như thế thì ta lại tốn thêm 12 bytes để làm nhãn và vì thế trên Ethernet thì MSS chỉ còn tối đa là 1500 &#8211; 52 = 1448 bytes thay vì 1460 bytes như trước.</p>
<p><strong>Tương tác giữa 4 cái mẹo. </strong> Quay lại với câu chuyện thử hiệu xuất giữa Windows và MacOSX trên Ethernet. Khác biệt thứ nhất là Windows XP không dùng nhãn thời gian, cho nên MSS = 1460, còn MacOSX dùng nhãn thời gian cho nên MSS = 1448 (trong môi trường thử nghiệm). Do đó, 100000 bytes được</p>
<ul>
<li> TCP của Windows XP băm ra thành 68 mẩu, mỗi mẩu 1460 bytes, cộng với một mẩu 720 bytes.</li>
<li> TCP của Mac OSX băm ra thành 69 mẩu, mỗi mẩu 1448 bytes, cộng với một mẩu 88 bytes.</li>
</ul>
<p>Khi Windows XP truyền thì:</p>
<ul>
<li> Bên gửi gửi đi 68 mẩu (đầy MSS nên gửi ngay), và giữ lại mẩu cuối (720 bytes) chờ hồi âm của mẩu 68.</li>
<li> Bên nhận dùng luật hồi âm kép nên sẽ hồi âm cho các mẩu 2, 4, &#8230;, 68 ngay lập tức, và cuối cùng khi bên gửi nhận được hồi âm của mẩu 68 sẽ gửi ngay mẩu lẻ cuối cùng.</li>
</ul>
<p>Khi Mac OSX truyền thì:</p>
<ul>
<li> Bên gửi gửi đi 69 mẩu (đầy MSS nên gửi ngay), và giữ lại mẩu cuối (88 bytes) chờ hồi âm mẩu 69.</li>
<li> Bên nhận theo luật hồi âm kép, nên sẽ hồi âm cho các mẩu 2, 4, &#8230;, 68 ngay lập tức, nhưng giữ lại không hồi âm mẩu 69 ngay (trừ phi có thêm hàng họ của khách hàng gửi kèm hồi âm mang về)</li>
<li> Nhưng hàng họ chỉ có sau 100KB, mà bây giờ bên nhân mới nhận được 100000-88 bytes thôi nên chưa có hàng.</li>
<li> Bên gửi thì dùng thuật toán Nagle, giữ lại 88 bytes chờ khi mẩu 69 có hồi âm.</li>
<li> Kết quả là hai bên phải chờ thêm từ 200ms đến 500ms nữa, tùy theo người lập trình TCP chọn giá trị hồi âm muộn là bao nhiêu.</li>
<li> Kết quả cuối cùng là cứ 100KB thì MacOSX bị chậm lại 200ms!</li>
</ul>
<p>200ms là một thời khoảng rất lớn. Trên Gigabit Ethernet, với tốc độ 1Gbps thì trong 200ms ta truyền được 200Mb vị chi là 25MB.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.procul.org/blog/2010/10/13/1-byte/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>20 vạn dặm dưới đáy biển</title>
		<link>http://www.procul.org/blog/2010/08/31/20-v%e1%ba%a1n-d%e1%ba%b7m-d%c6%b0%e1%bb%9bi-day-bi%e1%bb%83n/</link>
		<comments>http://www.procul.org/blog/2010/08/31/20-v%e1%ba%a1n-d%e1%ba%b7m-d%c6%b0%e1%bb%9bi-day-bi%e1%bb%83n/#comments</comments>
		<pubDate>Tue, 31 Aug 2010 14:04:00 +0000</pubDate>
		<dc:creator>NQH</dc:creator>
				<category><![CDATA[Mạng máy tính]]></category>
		<category><![CDATA[Cáp quang]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Mạng]]></category>

		<guid isPermaLink="false">http://www.procul.org/blog/?p=2295</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p><center><object width="500" height="405"><param name="movie" value="http://www.youtube.com/v/v1JEuzBkOD8?fs=1&amp;hl=en_US&amp;border=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/v1JEuzBkOD8?fs=1&amp;hl=en_US&amp;border=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="500" height="405"></embed></object></center></p>
]]></content:encoded>
			<wfw:commentRss>http://www.procul.org/blog/2010/08/31/20-v%e1%ba%a1n-d%e1%ba%b7m-d%c6%b0%e1%bb%9bi-day-bi%e1%bb%83n/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Makefile tổng quát</title>
		<link>http://www.procul.org/blog/2010/08/22/makefile-t%e1%bb%95ng-quat/</link>
		<comments>http://www.procul.org/blog/2010/08/22/makefile-t%e1%bb%95ng-quat/#comments</comments>
		<pubDate>Sun, 22 Aug 2010 07:36:02 +0000</pubDate>
		<dc:creator>NQH</dc:creator>
				<category><![CDATA[Lập trình]]></category>
		<category><![CDATA[Mạng máy tính]]></category>

		<guid isPermaLink="false">http://www.procul.org/blog/?p=2219</guid>
		<description><![CDATA[Hôm qua lọ mọ viết một Makefile cho sinh viên cho các bài tập lập trình học kỳ tới. Makefile này khá tổng quát cho các chương trình cỡ chục nghìn dòng lệnh đổ lại. Nó giả sử là mỗi .c đều có .h tương ứng. Dễ dàng sửa lại một chút để nó dịch [...]]]></description>
			<content:encoded><![CDATA[<p>Hôm qua lọ mọ viết một Makefile cho sinh viên cho các bài tập lập trình học kỳ tới. Makefile này khá tổng quát cho các chương trình cỡ chục nghìn dòng lệnh đổ lại. Nó giả sử là mỗi .c đều có .h tương ứng. Dễ dàng sửa lại một chút để nó dịch các chương trình C++. Ghi lại đây biết đâu lại có lợi cho ai đó.</p>
<p><span id="more-2219"></span></p>
<pre>#############################################################################
#   $ make           compile and link all C programs specified with PROGS
#   $ make clean     clean objects and the executable file
#   $ make distclean clean objects, the executable and dependencies
# I assume that each .c has a .h of the same name in directory INC_DIR
# You can compile multiple programs by redefining $(PROGS)
#===========================================================================

## Customizable Section: adapt those variables to suit your program.
##==========================================================================
# The pre-processor and compiler options.
MY_CFLAGS = -I./include -DBE_DEBUG -D_REENTRANT -Wall -D__EXTENSIONS__

# Libraries to link to, depending on OS
UNAME = $(shell uname)
ifeq ($(UNAME), SunOS)              # Sun OS
MY_LIBS = -lresolv -lsocket -lnsl
endif
ifeq ($(UNAME), Linux)              # Linux
MY_LIBS = -lresolv -lnsl
endif
ifeq ($(UNAME), Darwin)             # Mac OS
MY_LIBS =
endif

# Directory where your .h files are
INC_DIR := ./include

# The options used in linking as well as in any direct use of ld.
LDFLAGS +=

# The executable file names.
PROGS   = server client iom_client

## Implicit Section: change the following only when necessary.
##==========================================================================

CC := gcc
SRCS := $(wildcard *.c)

# objects other than those in PROGS
ALL_OBJS := ${SRCS:.c=.o}
ALL_NAMES := ${ALL_OBJS:.o=}

# all object files other than those named $(PROGS).o
COMMON_OBJS :=
define APPEND_CO
ifeq (,$(findstring $(1), $(PROGS)))
COMMON_OBJS += $(1).o
endif
endef
$(foreach name,$(ALL_NAMES),$(eval $(call APPEND_CO, $(name))))

.PHONY: all clean distclean

all: $(PROGS)

define PROG_RULE
$(1) : $(COMMON_OBJS) $(1).o
        ${CC} -I${INC_DIR} ${CFLAGS} ${MY_LIBS} ${COMMON_OBJS} $(1).c -o $(1)
endef

$(foreach program,$(PROGS),$(eval $(call PROG_RULE, $(program))))

## Objects are dependent on headers (and implicitly .c files)
##==========================================================================
define OBJ_RULE
$(1) : ${INC_DIR}/${1:.o=.h} ${1:.o=.c}
        ${CC} -I${INC_DIR} ${CFLAGS} -c ${1:.o=.c}
endef

$(foreach obj_file,$(ALL_OBJS),$(eval $(call OBJ_RULE,$(obj_file))))

## clean things up
##==========================================================================
clean:
        @- $(RM) $(PROGS)
        @- $(RM) $(ALL_OBJS)

distclean: clean
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.procul.org/blog/2010/08/22/makefile-t%e1%bb%95ng-quat/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Bài tập lập trình lớp mạng máy tính</title>
		<link>http://www.procul.org/blog/2009/11/12/bai-t%e1%ba%adp-l%e1%ba%adp-trinh-l%e1%bb%9bp-m%e1%ba%a1ng-may-tinh/</link>
		<comments>http://www.procul.org/blog/2009/11/12/bai-t%e1%ba%adp-l%e1%ba%adp-trinh-l%e1%bb%9bp-m%e1%ba%a1ng-may-tinh/#comments</comments>
		<pubDate>Thu, 12 Nov 2009 22:52:39 +0000</pubDate>
		<dc:creator>NQH</dc:creator>
				<category><![CDATA[Mạng máy tính]]></category>

		<guid isPermaLink="false">http://www.procul.org/blog/?p=1799</guid>
		<description><![CDATA[Thường là mỗi lần dạy lớp mạng máy tính tôi lại thiết kế một &#8220;bài tập lập trình mạng&#8221; khác nhau. Học kỳ này, bài tập là một phiên bản của BitTorrent protocol. Các sinh viên có 2 tháng để viết chương trình này. (Mấy lần trước thì là Gnutella và Kademlia, đều là các [...]]]></description>
			<content:encoded><![CDATA[<p>Thường là mỗi lần dạy lớp mạng máy tính tôi lại thiết kế một &#8220;bài tập lập trình mạng&#8221; khác nhau. Học kỳ này, bài tập là một phiên bản của BitTorrent protocol. Các sinh viên có 2 tháng để viết chương trình này. (Mấy lần trước thì là Gnutella và Kademlia, đều là các bài tập lập trình mạng tuyệt vời.)</p>
<h3>1. Purpose and basic requirements</h3>
<p align="left">Project 1 hopefully have familiarized you with basic socket programming. Please check out my implementation (source) of project 1. I hope you can build on it or learn something from it. Project 2 is no longer &#8220;toyish.&#8221; You will implement a basic subset of the BitTorrent protocol, which is one of the (two) most popular P2P file sharing protocols on the Internet. BitTorrent traffic constitutes a large fraction of modern Internet traffic. If you implement the protocol correctly, your &#8220;client&#8221; should be able to download files from other BitTorrent clients &#8220;in the wild,&#8221; and there are millions of those peers.</p>
<p align="left">The assignment is to be done in groups of size at most 2. You are responsible for finding your partner (if you need one), for finishing off the assignment in case your partner drops the class or backs out from completing the assignment for whatever reason. The program is to be written in C under a Unix platform such as Linux, SunOS, Solaris, or FreeBSD, or even Mac OS X. Under Windows, it is possible to develop your program with <a href="http://www.cygwin.com/"><code style="font-size: 1em; color: #008099;">cygwin</code></a> but you must make sure that:</p>
<ul>
<li>Your submission compiles and runs under both Linux and Solaris/SunOS. We will test your submission on both Linux and Solaris/SunOS machines.</li>
<li>Except for C++ (which is still not at all recommended), no other language is allowed. I have good pedagogical reasons for this requirement.</li>
</ul>
<p>For portability, please use the <code style="font-size: 1em; color: #008099;">Makefile</code> I provided in my Project 1 implementation, so that we can compile your program under these two platforms.</p>
<hr style="width: 1386px; height: 2px;" />
<h3>2. UBTorrent &#8212; overview of the protocol</h3>
<p>Let&#8217;s refer to the subset of the BitTorrent protocol that we (i.e. you and I) will implement the <span style="font-weight: bold; color: #cc66cc;">UBTorrent protocol</span>. It is BitTorrent with some advanced features stripped off. For simplicity, we will also name the program to be implemented <code style="font-size: 1em; color: #008099;">ubtorrent</code>, each instance of which is called a <span style="font-style: italic;">UBTorrent peer</span>, or just a <span style="font-style: italic; color: #cc33cc; font-weight: bold;">peer</span><span style="color: #cc33cc; font-weight: bold;"> </span>for short. For convenience, when we talk about the behavior of a particular peer, we will call it a (UBTorrent)<span style="font-style: italic; font-weight: bold; color: #cc33cc;">client</span>, to distinguish it from other peers.</p>
<p>The <a href="http://www.bittorrent.org/beps/bep_0003.html">&#8220;official&#8221; BitTorrent protocol specification</a> written by Bram Cohen is vague is some areas. Thus, I will copy materials from <a href="http://wiki.theory.org/BitTorrentSpecification">a more detailed specification of BitTorrent 1.0</a>. You do not need to read the official specifications, because UBTorrent is (hopefully) simpler.</p>
<p>Peers collaborate to download files. Let&#8217;s say some client has a file to be shared named &#8220;<a href="http://www.cse.buffalo.edu/~hungngo/classes/2009/Fall-589/projects/Simon%20And%20Garfunkel%20-%20Scarborough%20Fair.mp3"><span style="font-style: italic;">Simon and Garfunkel &#8211; Sound of Silence.mp3</span></a>&#8220;. Actually, let&#8217;s rename it &#8220;<span style="font-style: italic;">SS.mp3</span>&#8221; for short. The client first needs to create a <span style="font-style: italic; font-weight: bold; color: #cc33cc;">metainfo file</span> containing information about <span style="font-style: italic;">SS.mp3</span>. The metainfo file has the .<span style="font-style: italic;">torrent</span> extension, and is often referred to as the &#8220;dot torrent&#8221; file of <span style="font-style: italic;">SS.mp3</span>. The precise format of the metainfo file will be described below. Roughly, it contains the file name, keywords (if any), the URL of a program called a <span style="font-weight: bold; font-style: italic; color: #cc33cc;">tracker</span>, which is responsible for keeping track of all the peers who are collaborating in downloading <span style="font-style: italic;">SS.mp3</span>.</p>
<p><span id="more-1799"></span></p>
<p><span style="font-weight: bold;">2.1 Creating the metainfo file</span></p>
<p>In the wild, you will typically have to upload the metainfo file to some webserver, allowing others to search for it, and download it. But in Project 2, we will assume that every peer has the metainfo file already, bypassing the search step. (Feel free to implement a web search engine, in which case you should drop out of UB right about now.) In particular, we&#8217;ll just create the metainfo file for <span style="font-style: italic;">SS.mp3</span> and &#8220;give&#8221; it to each participating peer.</p>
<p>You can create the metainfo file using a command line utility that Bram Cohen wrote in Python a while back, named <code style="font-size: 1em; color: #008099;">btmakemetafile</code>. Here&#8217;s <a href="http://www.cse.buffalo.edu/~hungngo/classes/2009/Fall-589/projects/mmt.tar.gz">a directory</a> containing the utility (and supporting files). Download, gunzip and untar it, you will get a directory named <code style="font-size: 1em; color: #008099;">MMT</code> containing the utility. To create a metafile for <span style="font-style: italic;">SS.mp3</span>, you can type something like this:</p>
<pre style="font-size: 1.2em; color: black; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: #ddddee; background-position: initial initial; margin: 10px;">UBTorrent/MMT/btmakemetafile SS.mp3 http://127.0.0.1:6969/announce</pre>
<p>The first argument is the file name (or path to file name if you&#8217;re not running the utility in the directory where the file resides). The second argument<code style="font-size: 1em; color: #008099;">http://127.0.0.1:6969/announce</code> is called the <span style="color: #cc33cc; font-weight: bold; font-style: italic;">URL of the tracker</span>, which basically consists of the IP address and the port number that the tracker is running and listening on. Note that the tracker will run the HTTP protocol, and hence there&#8217;s the <code style="font-size: 1em; color: #008099;">http://</code> in the beginning.</p>
<p><span style="color: red;">Important note</span>: you might need to edit the first line of <code style="font-size: 1em; color: #008099;">btmakemetainfo</code> to point to the right path of <code style="font-size: 1em; color: #008099;">python</code> for <code style="font-size: 1em; color: #008099;">btmakemetainfo</code> to work. Type<code style="font-size: 1em; color: #008099;">which python</code> to get the path.</p>
<p><span style="font-weight: bold;">2.2. The tracker</span></p>
<p>It would be nice if we wrote your own tracker, but that would be too easy to do in 2 months. So, let&#8217;s not do that. We will use probably the most well-known tracker out there: <a href="http://erdgeist.org/arts/software/opentracker/">the opentracker written by Dirk Engling</a>. It is (was?) used by PirateBay.com and even <a href="http://nrkbeta.no/2009/03/08/norwegian-broadcasting-corporation-sets-up-its-own-bittorrent-tracker/">a Norwegian state TV broadcaster</a>.</p>
<p>To download and compile opentracker, download <a href="http://www.cse.buffalo.edu/~hungngo/classes/2009/Fall-589/projects/opentracker.tar.gz">these</a> <a href="http://www.cse.buffalo.edu/~hungngo/classes/2009/Fall-589/projects/libowfat.tar.gz">files</a>, unzip and untar them, you&#8217;ll get two directories named <code style="font-size: 1em; color: #008099;">libowfat</code> and <code style="font-size: 1em; color: #008099;">opentracker</code>. You <strong>MUST</strong> put the two directories under the same parent directory for the compilation to work. Then, <code style="font-size: 1em; color: #008099;">cd</code> into <code style="font-size: 1em; color: #008099;">libowfat</code> and type <code style="font-size: 1em; color: #008099;">make</code>, and <code style="font-size: 1em; color: #008099;">cd</code> into<code style="font-size: 1em; color: #008099;">opentracker</code> and type <code style="font-size: 1em; color: #008099;">make</code>. Alternatively, you can just follow Dirk Engling direction on his opentracker website:</p>
<pre style="font-size: 1.2em; color: black; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: #ddddee; background-position: initial initial; margin: 10px;">cvs -d :pserver:cvs@cvs.fefe.de:/cvs -z9 co
libowfat
cd libowfat
make
cd ..
cvs -d:pserver:anoncvs@cvs.erdgeist.org:/home/cvsroot co opentracker
cd opentracker
make</pre>
<p>There are two versions, <code style="font-size: 1em; color: #008099;">opentracker</code> and <code style="font-size: 1em; color: #008099;">opentracker.debug</code>, and you can run either of them. For instance,</p>
<pre style="font-size: 1.2em; color: black; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: #ddddee; background-position: initial initial; margin: 10px;">hungngo@MYMACHINE:~/UBTorrent/opentracker$ ./opentracker.debug -i 127.0.0.1
Binding socket type TCP to address [127.0.0.1]:6969... success.
Binding socket type UDP to address [127.0.0.1]:6969... success.</pre>
<p>will tell it to listen to port <code style="font-size: 1em; color: #008099;">6969</code> (default port) on the local interface.</p>
<p><span style="color: #ff0000;">Note</span>: if <code style="font-size: 1em; color: #008099;">make</code> reports some error, please try <code style="font-size: 1em; color: #008099;">gmake</code>.</p>
<p><span style="font-weight: bold;">2.3. The protocols</span></p>
<p>Once the tracker is running (on the URL specified in the metainfo file for <span style="font-style: italic;">SS.mp3</span>), peers can start collaborating on downloading this file. To get to know other peers, a client talks to the tracker using the <span style="font-weight: bold; color: #cc33cc; font-style: italic;">Tracker HTTP Protocol</span>, which is simply a tiny subset of the HTTP protocol. The tracker maintains and updates information about the torrent or the <span style="color: #cc33cc; font-weight: bold; font-style: italic;">swarm</span>, which is the set of participating peers. Every shared file corresponds to a swarm. A new peer can join the swarm by informing and querying the tracker.</p>
<p>Once knowing each other, peers can talk directly to each other using the <span style="font-style: italic; color: #cc33cc; font-weight: bold;">Peer Wire Protocol</span> over TCP to exchange <span style="color: #cc33cc; font-style: italic; font-weight: bold;">pieces</span> of <span style="font-style: italic;">SS.mp3</span>. A swarm can be large, containing any where from tens to thousands of peers. Thus, a client only connects to a subset of those. The original client which had the file <span style="font-style: italic;">SS.mp3</span> to share is called a <span style="color: #cc33cc; font-weight: bold; font-style: italic;">seeder</span>. Peers who do not have the entire file yet are called <span style="color: #cc33cc; font-weight: bold; font-style: italic;">leechers</span>. There might be multiple seeders for the same file, because once a leecher has downloaded the entire file, it will become a seeder. Peers can leave a swarm at any time, on their own terms.</p>
<p>While the Tracker HTTP Protocol is very simple both conceptually and practically, the Peer Wire Protocol (PWP) is only conceptually simple: a client requests pieces of the file from other peers until it got the entire file. If everyone was as enlightened as Buddha, PWP would have been extremely simple and there would be no Nobel prize in economics. Unfortunately, in the wild PWP has to solve the <a href="http://en.wikipedia.org/wiki/Free_rider_problem">free rider problem</a> while keeping the download efficient.</p>
<p>For efficiency, PWP uses a simple strategy called <span style="color: #cc33cc; font-weight: bold; font-style: italic;">rarest first</span> in which, given the current list of missing pieces, the client requests a rarest one first (i.e. a piece which fewest &#8212; but non-zero &#8212; of its neighboring peers have). Typically, there are many pieces which are equally rare. In this case it is also important to randomly pick one of them to download. This way, the availability of pieces are spread out and thus even when all seeders go to heaven, chances are better that no piece goes extinct.</p>
<p>To solve the free rider problem, PWP uses something called <span style="color: #cc33cc; font-weight: bold; font-style: italic;">choke algorithms</span>. A client gives pieces to good guys and &#8220;chokes&#8221; guys who haven&#8217;t given the client much. This is also called a tit-for-tat strategy. However, to avoid peers choking each other to death, especially in the beginning, a client also randomly unchokes some (potentially) bad guy too. This is called <span style="color: #cc33cc; font-weight: bold; font-style: italic;">optimistic unchoking</span>.</p>
<p><a href="http://www.imconf.net/imc-2006/papers/p20-legout.pdf">Recent studies</a> have shown that rarest first and choke algorithms are pretty good at solving both the free rider problem and the download efficiency problem. However, these mechanisms are far from perfect and there are a lot of potentials for further research and new protocol design. I hope some of you will get interested in this problem and start experimenting with new ideas. You could be the next Bram Cohen! (I&#8217;ll gladly accept a small stake in the new company.)</p>
<hr style="width: 1386px; height: 2px;" />
<h3>3. The ugly details</h3>
<p>A large part of this section is copied (selectively) from <a href="http://wiki.theory.org/BitTorrentSpecification">the BitTorrent protocol specification</a>. However, I have also stripped off many requirements. When in doubt, ask me (via the blog), don&#8217;t consult the official BitTorrent protocol specification. After all, we are implementing UBTorrent, not BitTorrent.</p>
<p><span style="font-weight: bold;">3.1 Bencoding</span></p>
<p>Bencoding is a way to specify and organize data in a terse format. It supports the following types: <span style="font-style: italic;">byte strings</span>, <span style="font-style: italic;">integers</span>, <span style="font-style: italic;">lists</span>, and <span style="font-style: italic;">dictionaries</span>.</p>
<p><span style="font-style: italic; font-weight: bold; color: #000000;"><span>3.1.1 Byte strings</span></span></p>
<p>Byte strings are encoded as follows: <em style="color: #009900;">&lt;string length encoded in base ten ASCII&gt;<strong>:</strong>&lt;string data&gt;</em><br />
Note that there is no constant beginning delimiter, and no ending delimiter.</p>
<dl>
<dd><strong>Example</strong>: <em>4<strong>:</strong>spam</em> represents the string &#8220;spam&#8221;</dd>
</dl>
<p><span style="font-weight: bold; font-style: italic; color: #000000;">3.1.2 Integers</span></p>
<p>Integers are encoded as follows: <em style="color: #009900;"><strong>i</strong>&lt;integer encoded in base ten ASCII&gt;<strong>e</strong></em><br />
The initial <strong>i</strong> and trailing <strong>e</strong> are beginning and ending delimiters. You can have negative numbers such as <em><strong>i</strong>-3<strong>e</strong></em>. You cannot prefix the number with a zero such as <em><strong>i</strong>04<strong>e</strong></em>. However, <em><strong>i</strong>0<strong>e</strong></em> is valid.</p>
<dl>
<dd><strong>Example</strong>: <em><strong>i</strong>3<strong>e</strong></em> represents the integer &#8220;3&#8243;</dd>
</dl>
<p><span style="font-weight: bold; font-style: italic; color: #000000;">3.1.3 Lists</span></p>
<p>Lists are encoded as follows: <em style="color: #009900;"><strong>l</strong>&lt;bencoded values&gt;<strong>e</strong></em><br />
The initial <strong>l</strong> and trailing <strong>e</strong> are beginning and ending delimiters. Lists may contain any bencoded type, including integers, strings, dictionaries, and other lists.</p>
<dl>
<dd><strong>Example:</strong> <em><strong>l</strong>4:spam4:eggs<strong>e</strong></em> represents the list of two strings: [ "spam", "eggs" ]</dd>
</dl>
<p><span style="font-weight: bold; font-style: italic; color: #000000;"><span>3.1.4 Dictionaries</span></span></p>
<p>Dictionaries are encoded as follows: <em style="color: #009900;"><strong>d</strong>&lt;bencoded string&gt;&lt;bencoded element&gt;<strong>e</strong></em><span style="color: #009900;"> </span><br />
The initial <strong>d</strong> and trailing <strong>e</strong> are the beginning and ending delimiters. Note that the keys must be bencoded strings. The values may be any bencoded type, including integers, strings, lists, and other dictionaries. Keys must be strings and appear in sorted order (sorted as raw strings, not alphanumerics). The strings should be compared using a binary comparison, not a culture-specific &#8220;natural&#8221; comparison.</p>
<dl>
<dd><strong>Example</strong>: <em><strong>d</strong>3:cow3:moo4:spam4:eggs<strong>e</strong></em> represents the dictionary { &#8220;cow&#8221; =&gt; &#8220;moo&#8221;, &#8220;spam&#8221; =&gt; &#8220;eggs&#8221; }
</dd>
<dd><strong>Example</strong>: <em><strong>d</strong>4:spaml1:a1:be<strong>e</strong></em> represents the dictionary { &#8220;spam&#8221; =&gt; [ "a", "b" ] }
</dd>
<dd><strong>Example</strong>: <em><strong>d</strong>9:publisher3:bob17:publisher-webpage15:www.example.com18:publisher.location4:home<strong>e</strong></em> represents { &#8220;publisher&#8221; =&gt; &#8220;bob&#8221;, &#8220;publisher-webpage&#8221; =&gt; &#8220;www.example.com&#8221;, &#8220;publisher.location&#8221; =&gt; &#8220;home&#8221; }</dd>
</dl>
<p><span style="font-weight: bold; font-style: italic;">3.1.5 You don&#8217;t have to implement a bendecoder</span></p>
<p>You can use a <a href="http://funzix.svn.sourceforge.net/viewvc/funzix/trunk/bencode/">bendecoder written in C by Mike Frysinger here</a>. Feel free to write your own. After downloading the entire directory, you can test the bendecoder by <code style="font-size: 1em; color: #008099;">make</code> and then try</p>
<pre style="font-size: 1.2em; color: black; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: #ddddee; background-position: initial initial; margin: 10px;">hungngo@MYMACHINE:~/tmp/bencode$ ./test i1234e
DECODING: i1234e
int = 1234
hungngo@MYMACHINE:~/tmp/bencode$ ./test l4:spam4:eggse
DECODING: l4:spam4:eggse
list [
    str = spam (len = 4)
    str = eggs (len = 4)
]
hungngo@MYMACHINE:~/tmp/bencode$ ./test d3:cow3:moo4:spam4:eggse
DECODING: d3:cow3:moo4:spam4:eggse
dict {
    cow =&gt; str = moo (len = 3)
    spam =&gt; str = eggs (len = 4)
}</pre>
<p>Obviously, you should look into the code to see how to use the functions. But the decoder is there, no coding needed. This decoder is the bulk of the <code style="font-size: 1em; color: #008099;">metainfo</code> command that you&#8217;re supposed to implement.</p>
<p><span style="font-weight: bold;">3.2. Metainfo file structure</span></p>
<p>All data in a metainfo file is bencoded. The content of a metainfo file (the file ending in &#8220;.torrent&#8221;) is a bencoded dictionary, containing the keys listed below. All character string values are UTF-8 encoded.</p>
<ul>
<li><strong>announce</strong>: The announce URL of the tracker (string)</li>
<li><strong>info</strong>: a dictionary that describes the file(s) of the torrent. There are two possible forms: one for the case of a &#8216;single-file&#8217; torrent with no directory structure, and one for the case of a &#8216;multi-file&#8217; torrent (see below for details)</li>
<li>a few other optional keys such as<strong>, creation date, comment, created by</strong>, and<strong> encoding</strong>. When you read the metainfo file, ignore these keys.</li>
</ul>
<p>The info dictionary contains the following fields:</p>
<ul>
<li><strong>length</strong>: length of the file in bytes (integer)</li>
<li><strong>name</strong>: the filename. This is purely advisory. (string)</li>
<li><strong>piece length</strong>: number of bytes in each piece (integer)</li>
<li><strong>pieces</strong>: string consisting of the concatenation of all 20-byte <span style="font-weight: bold; font-style: italic; color: #cc33cc;">SHA1 hash</span> values, one per piece (byte string, i.e. not urlencoded)</li>
</ul>
<p><span style="color: #ff0000;">Notes:</span></p>
<ul>
<li>The <strong>piece length</strong> specifies the nominal piece size, with default value 256KB = 2<sup>18</sup> bytes = 262144 bytes. In practice, the piece length is typically chosen based on the total amount of file data in the torrent, and is constrained by the fact that too-large piece sizes cause inefficiency, and too-small piece sizes cause large .torrent metainfo file. Historically, piece size was chosen to result in a .torrent file no greater than approx. 50 &#8211; 75 kB (presumably to ease the load on the server hosting the torrent files).
<ul>
<li>Current best-practice is to <em>keep the piece size to 512KB or less,</em> for torrents around 8-10GB, even if that results in a larger .torrent file. This results in a more efficient swarm for sharing files. The most common sizes are 256 kB, 512 kB, and 1 MB.</li>
<li>Every piece is of equal length except for the final piece, which is irregular. The number of pieces is thus determined by &#8216;ceil( total length / piece size )&#8217;.</li>
</ul>
</li>
<li>Each piece has a corresponding SHA1 hash of the data contained within that piece. These hashes are concatenated to form the <em>pieces values in the above<strong> </strong></em><strong>info</strong> dictionary. Note that this is <strong>not</strong> a list but rather a single string. The length of the string must thus be a multiple of 20.</li>
<li>Look carefully at my implementation of Project 1 for how to compute SHA1 hashes. (After a piece is downloaded, you will need to compute its SHA1 hash to verify its integrity!)</li>
</ul>
<p><span style="font-weight: bold;">3.3. Tracker HTTP Protocol</span></p>
<p>The tracker is an HTTP service which responds to HTTP GET requests. The requests include metrics from clients that help the tracker keep overall statistics about the torrent. The response includes a peer list that helps the client participate in the torrent. The base URL consists of the &#8220;announce URL&#8221; as defined in the metainfo (.torrent) file. The parameters are then added to this URL, using standard CGI methods (i.e. a &#8216;?&#8217; after the announce URL, followed by &#8216;param=value&#8217; sequences separated by &#8216;&amp;&#8217;).</p>
<p>Note that all binary data in the URL (particularly info_hash and peer_id) must be properly escaped. This means any byte not in the set 0-9, a-z, A-Z, &#8216;.&#8217;, &#8216;-&#8217;, &#8216;_&#8217; and &#8216;~&#8217;, must be encoded using the &#8220;%nn&#8221; format, where nn is the hexadecimal value of the byte. (See <a title="http://www.faqs.org/rfcs/rfc1738.html" rel="nofollow" href="http://www.faqs.org/rfcs/rfc1738.html">RFC1738</a> for details.) This is called the <span style="color: #cc33cc; font-weight: bold; font-style: italic;">urlencoding</span> of the data.</p>
<p>For a 20-byte hash of</p>
<p><code style="font-size: 1em; color: #008099;">\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a</code></p>
<p>the right encoded form is</p>
<p><code style="font-size: 1em; color: #008099;">%124Vx%9A%BC%DE%F1%23Eg%89%AB%CD%EF%124Vx%9A</code></p>
<p><span style="font-weight: bold; font-style: italic; color: #000000;">3.3.1 Tracker Request Parameters</span></p>
<p>The parameters used in the client-&gt;tracker GET request are as follows:</p>
<ul>
<li><strong>info_hash</strong>: urlencoded 20-byte SHA1 hash of the <em>value</em> of the <em>info</em> key from the metainfo file. Note that the <em>value</em> will be a bencoded dictionary, given the definition of the <em>info</em> key above.</li>
<li><strong>peer_id</strong>: urlencoded 20-byte string used as a unique ID for the client, generated by the client at startup. This is allowed to be any value, and may be binary data.</li>
<li><strong>port</strong>: The port number that the client is listening on.</li>
<li><strong>uploaded</strong>: The total number of bytes uploaded (since the client sent the &#8216;started&#8217; event to the tracker) in base ten ASCII.</li>
<li><strong>downloaded</strong>: The total number of bytes downloaded (since the client sent the &#8216;started&#8217; event to the tracker) in base ten ASCII.</li>
<li><strong>left</strong>: The number of bytes this client still has to download, encoded in base ten ASCII.</li>
<li><strong>compact</strong>: Setting this to 1 indicates that the client accepts a compact response. The peers list is replaced by a peers string with 6 bytes per peer. The first four bytes are the host (in network byte order), the last two bytes are the port (again in network byte order). It should be noted that some trackers only support compact responses (for saving bandwidth) and either refuse requests without &#8220;compact=1&#8243; or simply send a compact response unless the request contains &#8220;compact=0&#8243; (in which case they will refuse the request.)</li>
<li><strong>event</strong>: If specified, must be one of <em>started</em>, <em>completed</em>, <em>stopped</em>, (or empty which is the same as not being specified). If not specified, then this request is one performed at regular intervals.
<ul>
<li><strong>started</strong>: The first request to the tracker <em>must</em> include the event key with this value.</li>
<li><strong>stopped</strong>: Must be sent to the tracker if the client is shutting down gracefully.</li>
<li><strong>completed</strong>: Must be sent to the tracker when the download completes. However, must not be sent if the download was already 100% complete when the client started. Presumably, this is to allow the tracker to increment the &#8220;completed downloads&#8221; metric based solely on this event.</li>
</ul>
</li>
</ul>
<p>A request from the (original) seeder looks something like this:</p>
<pre style="font-size: 1.2em; color: black; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: #ddddee; background-position: initial initial; margin: 10px;">GET /announce?info_hash=_tWL%26%BD%C4%BDsEn%FD%7E1%2CJ3%40s%1B&amp;peer_id=M3-4-2--5ffd511f4079&amp;port=6881&amp;key=585b8345&amp;uploaded=0&amp;downloaded=0&amp;left=0&amp;compact=1&amp;event=started HTTP/1.1</pre>
<p>A request from a leecher looks something like this:</p>
<pre style="font-size: 1.2em; color: black; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: #ddddee; background-position: initial initial; margin: 10px;">GET /announce?info_hash=_tWL%26%BD%C4%BDsEn%FD%7E1%2CJ3%40s%1B&amp;peer_id=M3-4-2--f8c7df8ee1b9&amp;port=6882&amp;key=a6fa9e7e&amp;uploaded=0&amp;downloaded=0&amp;left=90112&amp;compact=1&amp;event=started HTTP/1.1</pre>
<p><strong>Note</strong>: 90112 is the size of <em>SS.mp3</em>. A GET request typically consists of the GET request line (as shown above) and an empty line. The last two characters of an HTTP request line must be <code style="font-size: 1em; color: #008099;">\r\n</code>. The &#8220;empty&#8221; line must consist of two characters <code style="font-size: 1em; color: #008099;">\r\n</code>. Those are &#8220;carriage-return&#8221; and &#8220;line-feed&#8221; characters.</p>
<p><span style="font-weight: bold; font-style: italic; color: #33cc00;"><span style="color: #000000;">3.3.2 Tracker Response</span><br />
</span><br />
The tracker responds with &#8220;text/plain&#8221; document consisting of a bencoded dictionary with the following keys:</p>
<ul>
<li><strong>failure reason</strong>: If present, then no other keys may be present. The value is a human-readable error message as to why the request failed (string).</li>
<li><strong>warning message</strong>: (new, optional) Similar to failure reason, but the response still gets processed normally. The warning message is shown just like an error.</li>
<li><strong>interval</strong>: Interval in seconds that the client should wait between sending regular requests to the tracker</li>
<li><strong>min interval</strong>: (optional) Minimum announce interval. If present clients must not reannounce more frequently than this.</li>
<li><strong>tracker id</strong>: A string that the client should send back on its next announcements. If absent and a previous announce sent a tracker id, do not discard the old value; keep using it.</li>
<li><strong>complete</strong>: number of peers with the entire file, i.e. seeders (integer)</li>
<li><strong>incomplete</strong>: number of non-seeder peers, aka &#8220;leechers&#8221; (integer)</li>
<li><strong>peers</strong>: (dictionary model) The value is a list of dictionaries, each with the following keys:
<ul>
<li><strong>peer id</strong>: peer&#8217;s self-selected ID, as described above for the tracker request (string)</li>
<li><strong>ip</strong>: peer&#8217;s IP address either IPv6 (hexed) or IPv4 (dotted quad) or DNS name (string)</li>
<li><strong>port</strong>: peer&#8217;s port number (integer)</li>
</ul>
</li>
<li><strong>peers</strong>: (binary model) Instead of using the dictionary model described above, the <strong>peers</strong> value may be a string consisting of multiples of 6 bytes. First 4 bytes are the IP address and last 2 bytes are the port number. All in network (big endian) notation.</li>
</ul>
<p>The list of peers is length 50 by default. If there are fewer peers in the torrent, then the list will be smaller. Otherwise, the tracker randomly selects peers to include in the response. The tracker may choose to implement a more intelligent mechanism for peer selection when responding to a request. For instance, reporting seeds to other seeders could be avoided. Since we are not implementing the tracker, we just take whatever the tracker gives.</p>
<p>Clients may send a request to the tracker more often than the specified interval, if an event occurs (i.e. stopped or completed) or if the client needs to learn about more peers. However, it is considered bad practice to &#8220;hammer&#8221; on a tracker to get multiple peers.</p>
<p>A reply from the tracker may look something like this:</p>
<pre style="font-size: 1.2em; color: black; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: #ddddee; background-position: initial initial; margin: 10px;">HTTP/1.0 200 OK
Content-Length: 27
Content-Type: text/plain
Pragma: no-cache

d8:intervali1800e5:peers0:e</pre>
<p>In general, the reply from the tracker follows the format <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html">specified here</a>. You should print out the first line of the response. If the status code (e.g. the number 200 above) is anything other than 2xx, then something is wrong, don&#8217;t read and parse the content. The content of the reply is everything after the blank line. <strong>Note:</strong> if you didn&#8217;t do anything special (like having a persistent-connection request along with the GET line), the tracker <em>will close</em> the connection right after sending the reply. Don&#8217;t be surprise! You should try <code style="font-size: 1em; color: #008099;">telnet localhost 6969</code> after running <code style="font-size: 1em; color: #008099;">opentracker</code>, and then cut-and-paste a sample request shown in the previous section to see the tracker&#8217;s response. <strong>Important note:</strong> The <code style="font-size: 1em; color: #008099;">readline()</code> function provided in the sample codes can be used, but it has to be used with extreme care, because it can read past the EOL character (for efficiency). Please read the code before using it!</p>
<p><span style="font-weight: bold;">3.4. Peer Wire Protocol (over TCP)</span></p>
<p><span style="font-weight: bold; font-style: italic; color: #000000;">3.4.1 Overview</span></p>
<p>The peer protocol facilitates the exchange of pieces as described in the metainfo file. To request a piece, a client will actually send multiple requests for parts of the piece, called <span style="color: #cc33cc; font-weight: bold; font-style: italic;">blocks</span>.  A block size is typically divisible by the piece size. It is recommended to set the default block size to be 16KB =  2<sup>14</sup> = 16384 bytes. Feel free to set the default block size to be equal to the piece size if you want. However, since the last piece may not have full size, some block requests will inevitably have to be of small sizes.</p>
<p>A client must maintain state information for each connection that it has with a remote peer:</p>
<ul>
<li><strong>choked</strong>: Whether or not the remote peer has choked this client. When a peer chokes the client, it is a notification that no requests will be answered until the client is unchoked. The client should not attempt to send requests for blocks, and it should consider all pending (unanswered) requests to be discarded by the remote peer.</li>
<li><strong>interested</strong>: Whether or not the remote peer is interested in something this client has to offer. This is a notification that the remote peer will begin requesting blocks when the client unchokes them.</li>
</ul>
<p>Note that this also implies that the client will also need to keep track of whether or not it is interested in the remote peer, and if it has the remote peer choked or unchoked. So, the real list looks something like this:</p>
<ul>
<li><strong>am_choking</strong>: this client is choking the peer</li>
<li><strong>am_interested</strong>: this client is interested in the peer</li>
<li><strong>peer_choking</strong>: peer is choking this client</li>
<li><strong>peer_interested</strong>: peer is interested in this client</li>
</ul>
<p>Client connections start out as &#8220;choked&#8221; and &#8220;not interested&#8221;. In other words:</p>
<ul>
<li><strong>am_choking</strong> = 1</li>
<li><strong>am_interested</strong> = 0</li>
<li><strong>peer_choking</strong> = 1</li>
<li><strong>peer_interested</strong> = 0</li>
</ul>
<p>A block is downloaded by the client when the client is interested in a peer, and that peer is not choking the client. A block is uploaded by a client when the client is not choking a peer, and that peer is interested in the client. It is important for the client to keep its peers informed as to whether or not it is interested in them. This state information should be kept up-to-date with each peer even when the client is choked. This will allow peers to know if the client will begin downloading when it is unchoked (and vice-versa).</p>
<p><span style="font-weight: bold; font-style: italic; color: #000000;">3.4.2 Data type</span></p>
<p>Unless specified otherwise, all integers in the peer wire protocol are encoded as four byte big-endian values. This includes the length prefix on all messages that come after the handshake.</p>
<p><span style="font-weight: bold; font-style: italic; color: #000000;"><span>3.4.3 Message flow</span></span><br style="color: #33cc00;" /></p>
<p>The peer wire protocol consists of an initial 2-way handshake. After that, peers communicate via an exchange of length-prefixed messages. The length-prefix is an integer as described above.</p>
<p><span style="font-weight: bold; font-style: italic; color: #000000;"><span>3.4.4 Handshake</span></span></p>
<p>The handshake is a required message and must be the first message transmitted by the client. It is (49+len(pstr)) bytes long.</p>
<p style="color: #009900;"><em>handshake: &lt;pstrlen&gt;&lt;pstr&gt;&lt;reserved&gt;&lt;info_hash&gt;&lt;peer_id&gt;</em></p>
<ul>
<li><strong>pstrlen</strong>: string length of &lt;pstr&gt;, as a single raw byte</li>
<li><strong>pstr</strong>: string identifier of the protocol.
<ul>
<li>In the UBTorrent protocol, as in the BitTorrent protocol, pstrlen = 19, and pstr = &#8220;BitTorrent protocol&#8221;.</li>
</ul>
</li>
<li><strong>reserved</strong>: eight (8) reserved bytes. All current implementations use all zeros. Each bit in these bytes can be used to change the behavior of the protocol. <em>An email from Bram suggests that trailing bits should be used first, so that leading bits may be used to change the meaning of trailing bits.</em></li>
<li><strong>info_hash</strong>: 20-byte SHA1 hash of the info key in the metainfo file. This is the same info_hash that is transmitted in tracker requests.</li>
<li><strong>peer_id</strong>: 20-byte string used as a unique ID for the client</li>
</ul>
<p>The initiator of a connection is expected to transmit their handshake immediately. The recipient may wait for the initiator&#8217;s handshake, if it is capable of serving multiple torrents simultaneously (torrents are uniquely identified by their <em>info_hash). </em>However, the recipient must respond as soon as it sees the info_hash part of the handshake<em>.</em><span style="font-style: italic;"> </span>If a client receives a handshake with an info_hash that it is not currently serving, then the client must drop the connection.</p>
<p>If the initiator of the connection receives a handshake in which the peer_id does not match the expected peer_id<em>, then the initiator is expected to drop the connection. </em>Note that the initiator presumably received the peer information from the tracker, which includes the peer_id that was registered by the peer. The peer_id from the tracker and in the handshake are expected to match.</p>
<p><span style="font-weight: bold; font-style: italic; color: #000000;">3.4.5 Messages</span></p>
<p>All of the remaining messages in the protocol take the form of <span style="color: #009900;">&lt;length prefix&gt;&lt;message ID&gt;&lt;payload&gt;</span>. The length prefix is a four byte big-endian value. The message ID is a single decimal byte. The payload is message dependent.</p>
<h4><span>keep-alive: &lt;len=0000&gt;</span></h4>
<p>The <strong>keep-alive</strong> message is a message with zero bytes, specified with the length prefix set to zero. There is no message ID and no payload. Peers may close a connection if they receive no messages (<strong>keep-alive</strong> or any other message) for a certain period of time, so a keep-alive message must be sent to maintain the connection <em>alive</em> if no command have been sent for a given amount of time. This amount of time is generally two minutes.</p>
<h4><span>choke: &lt;len=0001&gt;&lt;id=0&gt;</span></h4>
<p>The <strong>choke</strong> message is fixed-length and has no payload.</p>
<h4><span>unchoke: &lt;len=0001&gt;&lt;id=1&gt;</span></h4>
<p>The <strong>unchoke</strong> message is fixed-length and has no payload.</p>
<h4><span>interested: &lt;len=0001&gt;&lt;id=2&gt;</span></h4>
<p>The <strong>interested</strong> message is fixed-length and has no payload.</p>
<h4><span>not interested: &lt;len=0001&gt;&lt;id=3&gt;</span></h4>
<p>The <strong>not interested</strong> message is fixed-length and has no payload.</p>
<h4><span>have: &lt;len=0005&gt;&lt;id=4&gt;&lt;piece index&gt;</span></h4>
<p>The <strong>have</strong> message is fixed length. The payload is the zero-based index of a piece that has just been <span style="font-weight: bold;">successfully downloaded and verified</span> via the SHA1 hash.</p>
<p><em>Implementer&#8217;s Note: That is the strict definition, in reality some games may be played. In particular because peers are extremely unlikely to download pieces that they already have, a peer may choose not to advertise having a piece to a peer that already has that piece. At a minimum &#8220;HAVE suppression&#8221; will result in a 50% reduction in the number of HAVE messages, this translates to around a 25-35% reduction in protocol overhead. At the same time, it may be worthwhile to send a HAVE message to a peer that has that piece already since it will be useful in determining which piece is rare.</em></p>
<p><em>A malicious peer might also choose to advertise having pieces that it knows the peer will never download. Due to this attempting to model peers using this information is a <strong>bad idea</strong></em>.</p>
<h4><span>bitfield: &lt;len=0001+X&gt;&lt;id=5&gt;&lt;bitfield&gt;</span></h4>
<p>The <strong>bitfield</strong> message may only be sent immediately after the handshaking sequence is completed, and before any other messages are sent. The bitfield needs not be sent if a client has no pieces.</p>
<p>The <strong>bitfield</strong> message is variable length, where X is the length of the bitfield. The payload is a bitfield representing the pieces that have been successfully downloaded. The high bit in the first byte corresponds to piece index 0. Bits that are cleared indicated a missing piece, and set bits indicate a valid and available piece. Spare bits at the end are set to zero.<em> A bitfield of the wrong length is considered an error. Clients should drop the connection if they receive bitfields that are not of the correct size, or if the bitfield has any of the spare bits set.</em></p>
<h4><span>request: &lt;len=0013&gt;&lt;id=6&gt;&lt;index&gt;&lt;begin&gt;&lt;length&gt;</span></h4>
<p>The <strong>request</strong> message is fixed length, and is used to request a block. The payload contains the following information:</p>
<ul>
<li><strong>index</strong>: integer specifying the zero-based piece index</li>
<li><strong>begin</strong>: integer specifying the zero-based byte offset within the piece</li>
<li><strong>length</strong>: integer specifying the requested length.</li>
</ul>
<h4><span>piece: &lt;len=0009+X&gt;&lt;id=7&gt;&lt;index&gt;&lt;begin&gt;&lt;block&gt;</span></h4>
<p>The <strong>piece</strong> message is variable length, where X is the length of the block. The payload contains the following information:</p>
<ul>
<li><strong>index</strong>: integer specifying the zero-based piece index</li>
<li><strong>begin</strong>: integer specifying the zero-based byte offset within the piece</li>
<li><strong>block</strong>: block of data, which is a subset of the piece specified by index.</li>
</ul>
<h4><span>cancel: &lt;len=0013&gt;&lt;id=8&gt;&lt;index&gt;&lt;begin&gt;&lt;length&gt;</span></h4>
<p>The <strong>cancel</strong> message is fixed length, and is used to cancel block requests. The payload is identical to that of the &#8220;request&#8221; message. It is typically used during &#8220;End Game&#8221; (see the Algorithms section below).</p>
<p style="font-weight: bold;">3.5 Algorithms</p>
<p><span><span style="font-weight: bold; font-style: italic; color: #000000;">3.5.1 Piece downloading strategy </span></p>
<p></span>Download pieces in rarest first order. The client can determine this by keeping the initial bitfield from each peer, and updating it with every <strong>have</strong>message. Then, the client can download the pieces that appear least frequently in these peer bitfields. Note that any Rarest First strategy should include randomization among at least several of the least common pieces, as having many clients all attempting to jump on the same &#8220;least common&#8221; piece would be counter productive.<br />
<span style="font-weight: bold; font-style: italic; color: #000000;"><br />
<span>3.5.2 Choking and Optimistic Unchoking</span></span></p>
<p>The choke algorithm was introduced to guarantee a reasonable level of upload and download reciprocation. As a consequence, free riders, i.e., peers that never upload, should be penalized. For the sake of clarity, we describe without loss of generality the choke algorithm from the point of view of the local peer. In this section, interested always means interested in the local peer, and choked always means choked by the local peer.</p>
<p>The choke algorithm difers in leecher and seed states. We describe first the choke algorithm in leecher state. At most 4 remote peers can be unchoked and interested at the same time. Peers are unchoked using the following policy.</p>
<ol>
<li>Every 10 seconds, the interested remote peers are ordered according to their download rate to the local peer and the 3 fastest peers are unchoked.</li>
<li>Every 30 seconds, one additional interested remote peer is unchoked at random. We call this random unchoke the optimistic unchoke.</li>
</ol>
<p>In the following, we call the three peers unchoked in step 1 the regular unchoked (RU) peers, and the peer unchoked in step 2 the optimistic unchoked (OU) peer. The optimistic unchoke peer selection has two purposes. It allows to evaluate the download capacity of new peers in the peer set, and it allows to bootstrap new peers that do not have any piece to share by giving them their first piece.</p>
<p>In seed state, the choke algorithm is the same as that in leecher state except that in seed state the ordering performed in step 1 is based on upload rates from the local peer.</p>
<hr style="width: 1386px; height: 2px;" />
<h3>4. What you are supposed to implement</h3>
<p>You&#8217;re probably overwhelmed by the above description. However, keep in mind that you can use existing codes for many important functionalities have been implemented already: the SHA1 hash, the bendecoder, the tracker, etc. I will simplify things further by requiring you to implement clients which support only one single .torrent file, given as an input to the program <code style="font-size: 1em; color: #008099;">ubtorrent</code>. It is not difficult to extend the implementation to support multiple torrents, and you are encourage to do so in your spare time after this course is over. In fact, run your implementation &#8220;in the wild&#8221; to see how it measures up to other professional ones. Your <code style="font-size: 1em; color: #008099;">ubtorrent</code> is supposed to implement all of the above requirements though. The sequence of tasks looks something like this:</p>
<ul>
<li>Download and compile the <code style="font-size: 1em; color: #008099;">opentracker</code> program. Run it.</li>
<li>Create the <em>.torrent</em> file for <em>SS.mp3</em> (or any reasonably sized file). We will test your program with files up to 20MB in size, but not more. When you implement <code style="font-size: 1em; color: #008099;">ubtorrent</code>, you probably should write pieces down to disk, don&#8217;t keep everything in memory.</li>
<li>Create several directories, perhaps name them <code style="font-size: 1em; color: #008099;">1, 2, 3, 4, 5</code> and so on. Then put <em>SS.mp3</em> in one of them. And, put a copy of <code style="font-size: 1em; color: #008099;">ubtorrent</code> in each of them. Thus, the copy of <code style="font-size: 1em; color: #008099;">ubtorrent</code> running inside directory <code style="font-size: 1em; color: #008099;">1</code> will be the original seeder. Other copies of <code style="font-size: 1em; color: #008099;">ubtorrent</code> can write temporary files inside that local directory. Clean up the temp files after the downloading is done, or if the user types <code style="font-size: 1em; color: #008099;">quit</code></li>
<li><code style="font-size: 1em; color: #008099;">ubtorrent</code> takes two parameters: the first argument is the <em>.torrent</em> file name, and the second argument is the port number that other peers can connect to. For example,
<pre style="font-size: 1.2em; color: black; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: #ddddee; background-position: initial initial; margin: 10px;">ubtorrent SS.mp3.torrent 6881</pre>
</li>
<li>Note that the tracker information is contained in the <em>metainfo</em> file. Upon starting, a client checks the local directory to see if the file is there already. (Check the file name and file size.) If the file is there, the client is running in the seeder state. Otherwise, it is running in the leecher state. The client then issues a GET request to the tracker rightaway. If the tracker is not running, the client reports an error and quit.</li>
<li>At this point, if the seeder was already started, or if other peers have downloaded some pieces, the current client can start requesting blocks and start downloading. It should fully implement the rarest first and choke algorithms. If you run only 5 peers in total, choke algorithms should not take effect, and thus the peers download blocks/pieces from each other until they are completed. The rarest first algorithm should still be in place though. I personally would recommend writing a function which tells you which piece(s) to request, given the current list of pieces that the peers have. Initially, the function would just return any missing piece (i.e. without the rarest first algorithm). Once this works, you can change the function to return a random rarest piece.</li>
</ul>
<p>What follows is the list of commands to be implemented: <code style="font-size: 1em; color: #008099;">ubtorrent</code> takes commands from users. I will be more precise on the output formats of these commands in the next few days.</p>
<p><span style="font-weight: bold; font-style: italic;">4.1. metainfo</span></p>
<p>This command asks the client to show the information about the metainfo file. The output format looks something like this:</p>
<pre style="font-size: 1.2em; color: black; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: #ddddee; background-position: initial initial; margin: 10px;">ubtorrent&gt; metainfo
  my IP/port    : 127.0.1.1/9999
  my ID         : bcd914c766d969a772823815fdc2737b2c8384bf
  metainfo file : Dan Hill &amp; Rique Franks - Sometimes When We Touch.mp3.torrent
  info hash     : 4a060f199e5dc28ff2c3294f34561e2da423bf0b
  file name     : Dan Hill &amp; Rique Franks - Sometimes When We Touch.mp3
  piece length  : 262144
  file size     : 1007616 (3 * [piece length] + 221184)
  announce URL  : http://test/abc
  pieces' hashes:
    0  064b493d90b6811f22e0457aa7f50e9c70b84285
    1  d17cb90e50ca06a651a84f88fde0ecfb22a90cca
    2  20e82d045341032645ebe27eed38103329281175
    3  568c8a0599a7c1e2b3c70d8b8c960134653d497a

ubtorrent&gt;</pre>
<p>Everything is in the metainfo file or available locally (IP/port), except for the <code style="font-size: 1em; color: #008099;">info hash</code> value which you have to compute. (This has to be computed anyhow in order to send tracker requests.) The value of <code style="font-size: 1em; color: #008099;">info hash</code> is the SHA1 hash of the <em>value</em> of the <em>info</em> key in the metainfo dictionary.</p>
<p>Like in Project 1, your program should handle errors graciously. If the input .torrent file does not exist or if there were some errors in reading the file, for example, please do not crash. You <strong>can</strong> assume that the metainfo file (that we will test) is not greater than 8KB = 8192 bytes. If the given metainfo file is larger than that, you can quit the program and complain (to the screen). In the wild, metainfo files are often kept small, not more than 50KB.</p>
<p>Now, sometimes for debugging purposes you might want to display the metainfo file to the screen. However, as there are hash values in it, many characters cannot be displayed, causing the terminal to behave in unpredictable manner (e.g., change to Korean or Chinese fonts or something). To be safe, you should use <code style="font-size: 1em; color: #008099;">hexdump</code> to display a metainfo file:</p>
<pre style="font-size: 1.2em; color: black; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: #ddddee; background-position: initial initial; margin: 10px;">hungngo@MYMACHINE:~/tmp$ hexdump test.torrent -c
0000000   d   8   :   a   n   n   o   u   n   c   e   1   5   :   h   t
0000010   t   p   :   /   /   t   e   s   t   /   a   b   c   1   3   :
...</pre>
<p>I cut the rest of the output. You may find the functions <code style="font-size: 1em; color: #008099;">strtol()</code> helpful when trying to get the <em>value</em> of the <em>info</em> key out.</p>
<p><span style="font-weight: bold; font-style: italic;">4.2. announce</span></p>
<p>This command asks the client to send a GET request to the tracker. When the response comes back, update the information to be used later. It also prints out the status line of the response (the first line which looks something like <code style="font-size: 1em; color: #008099;">HTTP1.0 200 OK</code>). The output may look like this:</p>
<pre style="font-size: 1.2em; color: black; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: #ddddee; background-position: initial initial; margin: 10px;">ubtorrent&gt; announce
++++ Tracker responded: HTTP/1.0 200 OK
 complete | downloaded | incomplete | interval | min interval |
---------------------------------------------------------------
 1        | 0          | 0          | 1686     | 843          |
---------------------------------------------------------------
++++ Peer List :
 IP               | Port
-------------------------------
 127.0.0.1        | 9999
   ... Tracker closed connection</pre>
<p>(I suggest you store the dictionary in some <code style="font-size: 1em; color: #008099;">be_node</code>. Remember to <code style="font-size: 1em; color: #008099;">be_free</code> the node the next time an <code style="font-size: 1em; color: #008099;">announce</code> is called. The <code style="font-size: 1em; color: #008099;">be_node</code> is used in processing the command <code style="font-size: 1em; color: #008099;">trackerinfo</code>.)</p>
<p><span style="font-weight: bold; font-style: italic;">4.3. trackerinfo</span></p>
<p>Prints the information contained in the latest tracker response. This is a subroutine which should have been called when <code style="font-size: 1em; color: #008099;">announce</code> is typed. So, the output is just part of the (last sucessful) <code style="font-size: 1em; color: #008099;">announce</code> output, without the status line:</p>
<pre style="font-size: 1.2em; color: black; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: #ddddee; background-position: initial initial; margin: 10px;">ubtorrent&gt;trackerinfo
 complete | downloaded | incomplete | interval | min interval |
---------------------------------------------------------------
 1        | 0          | 0          | 1686     | 843          |
---------------------------------------------------------------
++++ Peer List (self included):
 IP               | Port
-------------------------------
 127.0.0.1        | 9999
 127.0.0.1        | 9998
 127.0.0.1        | 9997</pre>
<p><span style="font-weight: bold; font-style: italic;">4.4. show</span></p>
<p>Prints the status of all current peer connections, including the choked/interested states and upload/download rates. The format looks something like this:</p>
<pre style="font-size: 1.2em; color: black; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: #ddddee; background-position: initial initial; margin: 10px;">ubtorrent&gt; show
ID | IP address | Status | Bitfield         | Down/s   | Up/s     |
--------------------------------------------------------------------
 0 | 127.0.0.1  | 0101   | 1111111111111111 | 0        |  59271
 1 | 127.0.0.1  | 0101   | 1111111111111111 | 0        |  59271</pre>
<p><code style="font-size: 1em; color: #008099;">Down/s</code> is the number of bytes downloaded per second on that connection. The <code style="font-size: 1em; color: #008099;">status</code> field has 4 bits, corresponding to the status of that connection: <code style="font-size: 1em; color: #008099;">iam_choking</code> (peer), <code style="font-size: 1em; color: #008099;">iam_interested</code> (in peer), <code style="font-size: 1em; color: #008099;">peer_choking</code> (me), <code style="font-size: 1em; color: #008099;">peer_interested</code> (in me).</p>
<p><span style="font-weight: bold; font-style: italic;">4.5. status</span></p>
<p>Prints the status of the current  download: which pieces have been downloaded, which pieces are missing, the number of downloaded, uploaded, and remaining bytes. The format is something like this:</p>
<pre style="font-size: 1.2em; color: black; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: #ddddee; background-position: initial initial; margin: 10px;"> ubtorrent&gt; status
 Downloaded | Uploaded | Left | My bit field
------------------------------------------------
 1007616    | 0        | 0    | 1111111111111111</pre>
<p>or</p>
<pre style="font-size: 1.2em; color: black; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: #ddddee; background-position: initial initial; margin: 10px;">ubtorrent&gt; status
 Downloaded | Uploaded | Left    | My bit field
---------------------------------------------------
 0          | 0        | 1007616 | 0000000000000000</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.procul.org/blog/2009/11/12/bai-t%e1%ba%adp-l%e1%ba%adp-trinh-l%e1%bb%9bp-m%e1%ba%a1ng-may-tinh/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Một bài tập lớp mạng máy tính</title>
		<link>http://www.procul.org/blog/2009/10/21/m%e1%bb%99t-bai-t%e1%ba%adp-l%e1%bb%9bp-m%e1%ba%a1ng-may-tinh/</link>
		<comments>http://www.procul.org/blog/2009/10/21/m%e1%bb%99t-bai-t%e1%ba%adp-l%e1%bb%9bp-m%e1%ba%a1ng-may-tinh/#comments</comments>
		<pubDate>Wed, 21 Oct 2009 14:32:25 +0000</pubDate>
		<dc:creator>NQH</dc:creator>
				<category><![CDATA[Mạng máy tính]]></category>
		<category><![CDATA[Thuật Toán]]></category>

		<guid isPermaLink="false">http://www.procul.org/blog/?p=1789</guid>
		<description><![CDATA[Học kỳ này tôi dạy lớp mạng máy tính. Tôi thiết kế một bài tập mà cá nhân tôi rất thích vì nó chứa các thành tố của cả mạng lẫn thuật toán (quy hoạch động). Ý tưởng của bài tập này đến từ một bài báo mà anh Hà Trần Đức và tôi viết [...]]]></description>
			<content:encoded><![CDATA[<p>Học kỳ này tôi dạy lớp mạng máy tính. Tôi thiết kế một bài tập mà cá nhân tôi rất thích vì nó chứa các thành tố của cả mạng lẫn thuật toán (quy hoạch động). Ý tưởng của bài tập này đến từ <a href="http://www.cse.buffalo.edu/~hungngo/papers/worm07.pdf">một bài báo</a> mà anh Hà Trần Đức và tôi viết mấy năm trước. Chia sẻ bài tập này với các bạn ở đây cho vui. Do cut-and-paste, đoạn sau đây viết bằng tiếng Anh.</p>
<p><strong>Problem 1</strong>. In this question, we explore how potentially a P2P design is more efficient than a central sever design for file distribution. However, to make it juicier, we will explore this issue from a computer worm propagation context.</p>
<p>The Slammer worm was a very famous computer worm, very destructive, infected 75000 victims within 10 minutes in January of 2003. Each instance of the worm has size 404 bytes. We will simplify the problem for the worm writer a little. Let’s assume that once an infected computer A transmitted the worm (404 bytes) to computer B, computer B is infected and thus can propagate the worm further on its own. If you were a worm writer wanting to design an infection strategy for your worm, you’ll have to do some back-of-the-envelop computation similar to this problem.</p>
<p>Suppose the worm writer wants to infect 1 million home computers, each of which has an ADSL connection whose upload speed is 400Kbps and whose download speed is 1.4Mbps. This population of 1 million computers is called the vulnerable population. Also suppose that the propagation delay from any machine to another machine on the Internet is 50ms.</p>
<p>Consider the following two scenarios:</p>
<ul>
<li> Suppose initially a really fast server is infected. The server’s up-link (i.e. the link to send data to the Internet) is an OC12 link, whose speed is roughly 622 Mbps. Let the server infect each of the vulnerable hosts one by one. How long does it take until all vulnerable hosts are infected?
<li> Now, suppose initially a computer with an ADSL connection as above is infected. The worm writer decides to use a P2P-type of strategy for infection. The infection strategy can be visualized as a tree, whose root is the originally infected host. A parent node, upon infected, will infect each of its children one-by-one in some order. This tree has a million and one nodes. Let <img src='http://s.wordpress.com/latex.php?latex=T%28n%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='T(n)' title='T(n)' class='latex' /> denote the minimum infection time of a tree with n nodes whose root is infected. We are interested in computing <img src='http://s.wordpress.com/latex.php?latex=T%281000001%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='T(1000001)' title='T(1000001)' class='latex' />.
<p>– Write a recursive formula for computing <img src='http://s.wordpress.com/latex.php?latex=T%28n%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='T(n)' title='T(n)' class='latex' />.</p>
<p>– What is <img src='http://s.wordpress.com/latex.php?latex=T%281000001%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='T(1000001)' title='T(1000001)' class='latex' />, according to your recursive formula? (You may need to write a very short piece of code to compute this. If the code is recursive, it might never terminate. Think of a way [very simple] to write an iterative one, with a for loop.)
</ul>
<p><strong>Problem 2</strong>. Repeat the above question with a 4 GB file instead of the 404 worm bytes.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.procul.org/blog/2009/10/21/m%e1%bb%99t-bai-t%e1%ba%adp-l%e1%bb%9bp-m%e1%ba%a1ng-may-tinh/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Giao trứng cho ác</title>
		<link>http://www.procul.org/blog/2009/05/18/giao-tr%e1%bb%a9ng-cho-ac/</link>
		<comments>http://www.procul.org/blog/2009/05/18/giao-tr%e1%bb%a9ng-cho-ac/#comments</comments>
		<pubDate>Mon, 18 May 2009 14:52:57 +0000</pubDate>
		<dc:creator>NQH</dc:creator>
				<category><![CDATA[Ảnh hưởng của CNTT]]></category>
		<category><![CDATA[Mạng máy tính]]></category>
		<category><![CDATA[Tin tức đó đây]]></category>

		<guid isPermaLink="false">http://www.procul.org/blog/?p=1182</guid>
		<description><![CDATA[Cập nhật 18 tháng 5: Cuối cùng thì có vẻ như các tin tức về chủ quyền trên server đã được/bị hủy bỏ. Ví dụ như http://211.88.5.96/cvweb/vcc/info/Article.jsp?a_no=180804&#038;col_no=550 không còn chứa các tuyên bố chủ quyền này nọ nữa. Chắc là domain name www.vietnamchina.gov.vn sẽ được hồi phục nay mai. Còn thiếu mỗi việc &#8230; quy [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Cập nhật 18 tháng 5</strong>:</p>
<p>Cuối cùng thì có vẻ như các tin tức về chủ quyền trên server đã được/bị hủy bỏ. Ví dụ như</p>
<p><a href="http://211.88.5.96/cvweb/vcc/info/Article.jsp?a_no=180804&#038;col_no=550">http://211.88.5.96/cvweb/vcc/info/Article.jsp?a_no=180804&#038;col_no=550</a></p>
<p>không còn chứa các tuyên bố chủ quyền này nọ nữa.</p>
<p>Chắc là domain name www.vietnamchina.gov.vn sẽ được hồi phục nay mai. Còn thiếu mỗi việc &#8230; quy trách nhiệm là đóng sổ vụ này.</p>
<p><strong>Cập nhật 15 tháng 5</strong>:</p>
<p>Có vẻ như giải pháp bỏ DNS entry đã được thực hiện.</p>
<pre> &gt; server vdc-hn01.vnn.vn
Default Server:  vdc-hn01.vnn.vn
Address:  203.162.0.11

&gt; www.vietnamchina.gov.vn.
Server:  vdc-hn01.vnn.vn
Address:  203.162.0.11

*** vdc-hn01.vnn.vn can't find www.vietnamchina.gov.vn.: Non-existent host/domain
</pre>
<p>Nếu vào thẳng IP thì có vẻ như các công văn yêu cầu đội bạn bỏ tài liệu không có tác dụng:</p>
<p><a href="http://211.88.5.96/cvweb/vcc/index.jsp">http://211.88.5.96/cvweb/vcc/index.jsp</a></p>
<p><a href="http://211.88.5.96/cvweb/vcc/info/Article.jsp?a_no=180804&#038;col_no=550">http://211.88.5.96/cvweb/vcc/info/Article.jsp?a_no=180804&#038;col_no=550</a></p>
<p>Cũng đáng chú  ý là <a href="http://www.blogosin.org/?p=898#comments">một bình luận</a> (số 113) của bác Trương Thái Du bên blog Osin:</p>
<blockquote><p>
Tôi tò mò vào trang web nói trên. Bất ngờ với cách dùng hai hình ảnh tượng trưng cho VN (khuê văn các) và TQ (thiên đàn). Chắc chắn người TQ đã chọn ảnh. Ý tưởng rất rõ ràng THIÊN TRIỀU và HỌC TRÒ. Chơi với TQ mà lơ tơ mơ về lịch sử và văn hóa thì hậu quả tự đồng hóa luôn nhãn tiền.
</p></blockquote>
<p><strong>14 tháng 5</strong><br />
Bác Lê Tuấn Huy có công rất lớn với đất nước, <a href="http://blog.360.yahoo.com/blog-bfvqsbM9frIQmHcPB6d2QS4LkA--?cq=1&#038;p=895">phát hiên</a> ra vụ &#8220;nằm vùng&#8221; của vietnamchina.gov.vn. Nhiều blogs khác cũng đã đăng lại tin này (<a href="http://www.blogosin.org/?p=894">Ô Sin</a>, <a href="http://everywhereland.blogspot.com/2009/05/vietnamchinagovvn.html">Linh</a>, <a href="http://nguyenvanphu.blogspot.com/2009/05/su-yeu-kem-cua-bo-may.html">NVP</a>, v.v.), cùng với <a href="http://www.bbc.co.uk/vietnamese/vietnam/2009/05/090514_vnwebsite_chinapolicies.shtml">một bài</a> trên BBC Việt Ngữ.</p>
<p>Là dân kỹ thuật, có cái cần thử ngay:</p>
<pre>[NQH] MFM:~$ nslookup
&gt; set type=a
&gt; www.vietnamchina.gov.vn
...
Non-authoritative answer:
Name:   www.vietnamchina.gov.vn
Address: 211.88.5.96
&gt; set type=ns
&gt; gov.vn.
Server:         24.92.226.40
Address:        24.92.226.40#53

Non-authoritative answer:
gov.vn  nameserver = d.dns-servers.vn.
gov.vn  nameserver = a.dns-servers.vn.
gov.vn  nameserver = f.dns-servers.vn.
...
&gt; server d.dns-servers.vn
Default server: d.dns-servers.vn
Address: 203.119.44.105#53
&gt; vietnamchina.gov.vn.
Server:         d.dns-servers.vn
Address:        203.119.44.105#53

Non-authoritative answer:
*** Can't find vietnamchina.gov.vn.: No answer

Authoritative answers can be found from:
<strong>vietnamchina.gov.vn     nameserver = hcm-server1.vnn.vn.
vietnamchina.gov.vn     nameserver = vdc-hn01.vnn.vn.
</strong>
&gt; set type=a
&gt; server vdc-hn01.vnn.vn
Default server: vdc-hn01.vnn.vn
Address: 203.162.0.11#53
&gt; www.vietnamchina.gov.vn.
Server:         vdc-hn01.vnn.vn
Address:        203.162.0.11#53

Name:   www.vietnamchina.gov.vn
Address: <strong>211.88.5.96</strong>
</pre>
<p>Theo http://www.ip2location.com/free.asp thì 211.88.5.96 nằm ở Bắc Kinh. Như vậy là web server nằm ở Bắc Kinh, còn nameservers là của bọ (dĩ nhiên rồi! tên miền .vn mà). </p>
<p>Nếu chúng đã &#8220;muốn làm gì thì làm&#8221; với webserver thì bọ cũng phải được &#8220;muốn làm gì thì làm&#8221; với nameserver của bọ chứ: đừng trả lời DNS query cho www.vietnamchina.gov.vn là xong. Dĩ nhiên vấn đề phức tạp hơn như thế. Chẳng biết hai bên ký kết cái gì khi thành lập website này. Nhỡ khi ký rằng: &#8220;<em>Iem bỏ entry vào name server, anh cung cấp nội dung website, chúng ta cân bằng cán cân thương mại nhé, &#8230; Nếu mà cắt hợp đồng này thì anh kiện iem</em>&#8221;  thì sao?</p>
<p>Do đó, bỏ cái entry này ra khỏi DNS RR, chỉ dễ dàng về mặt kỹ thuật mà thôi.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.procul.org/blog/2009/05/18/giao-tr%e1%bb%a9ng-cho-ac/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Phiên tòa P2P của thập kỷ</title>
		<link>http://www.procul.org/blog/2009/03/04/phien-toa-p2p-c%e1%bb%a7a-th%e1%ba%adp-k%e1%bb%b7/</link>
		<comments>http://www.procul.org/blog/2009/03/04/phien-toa-p2p-c%e1%bb%a7a-th%e1%ba%adp-k%e1%bb%b7/#comments</comments>
		<pubDate>Wed, 04 Mar 2009 15:46:40 +0000</pubDate>
		<dc:creator>NQH</dc:creator>
				<category><![CDATA[Mạng máy tính]]></category>
		<category><![CDATA[Nhân vật và sự kiện]]></category>

		<guid isPermaLink="false">http://www.procul.org/blog/?p=1053</guid>
		<description><![CDATA[17 tháng 4 này sẽ tuyên án. Trích từ một editorial của Wired: When Swedish authorities raided The Pirate Bay and its servers in 2006 &#8212; paving the way for ongoing criminal trial that ended Tuesday &#8212; the pirates were unbowed, quickly resurrecting the site and setting their reverse-DNS to read: &#8220;hey.mpaa.and.apb.bite.my.shiny.metal.ass.thepiratebay.org.&#8221; &#8220;Even though no [...]]]></description>
			<content:encoded><![CDATA[<p>17 tháng 4 này sẽ tuyên án. Trích từ một <a href="http://www.wired.com/politics/onlinerights/news/2009/03/piratebay_editorial">editorial của Wired</a>:</p>
<blockquote><p>When Swedish authorities raided The Pirate Bay and its servers in 2006 &#8212; paving the way for ongoing criminal trial that ended Tuesday &#8212; the pirates were unbowed, quickly resurrecting the site and setting their reverse-DNS to read: &#8220;hey.mpaa.and.apb.bite.my.shiny.metal.ass.thepiratebay.org.&#8221;</p>
<p>&#8220;Even though no one spreads more culture than we do, it is the film and music-mob that are trying to close us down,&#8221; co-founder Fredrik Neij said, in a speech outside Swedish Parliament after the raid. &#8220;This time we&#8217;re firing with the big cannons and saying, &#8216;In your face, Hollywood!&#8217;&#8221;</p>
<p>But all that swagger evaporated like salt water on a beached schooner once The Pirate Bay landed on the witness stand in Stockholm, Sweden, where the three admitted founders &#8212; and a fourth man accused of financing them &#8212; face up to two years in prison each on allegations of facilitating copyright infringement. The trial wrapped up Tuesday, and a verdict is expected in April.</p>
<p>In the courtroom, the defendants quickly abandoned their revolutionary, free-culture ideals in favor of the simpler philosophy embraced by criminal defendants since time immemorial: I&#8217;m Not Responsible.
</p></blockquote>
<p>Một tin khác liên quan mật thiết: <a href="http://news.cnet.com/8301-13578_3-10187067-38.html">Obama picks Net neutrality backer as FCC chief<br />
</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.procul.org/blog/2009/03/04/phien-toa-p2p-c%e1%bb%a7a-th%e1%ba%adp-k%e1%bb%b7/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Lý thuyết tính toán trên mạng</title>
		<link>http://www.procul.org/blog/2007/01/22/ly-thuy%e1%ba%bft-tinh-toan-tren-m%e1%ba%a1ng/</link>
		<comments>http://www.procul.org/blog/2007/01/22/ly-thuy%e1%ba%bft-tinh-toan-tren-m%e1%ba%a1ng/#comments</comments>
		<pubDate>Mon, 22 Jan 2007 16:32:06 +0000</pubDate>
		<dc:creator>NQH</dc:creator>
				<category><![CDATA[Lý thuyết tính toán]]></category>
		<category><![CDATA[Mạng máy tính]]></category>

		<guid isPermaLink="false">http://www.procul.org/blog/2007/01/22/ly-thuy%e1%ba%bft-tinh-toan-tren-m%e1%ba%a1ng/</guid>
		<description><![CDATA[Bản nháp báo cáo của một workshop do NSF tài trợ.]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.cs.yale.edu/homes/jf/ToNC.html">Bản nháp</a> báo cáo của một workshop do NSF tài trợ.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.procul.org/blog/2007/01/22/ly-thuy%e1%ba%bft-tinh-toan-tren-m%e1%ba%a1ng/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Vài bài tổng quan về cấu trúc các mạng phức tạp</title>
		<link>http://www.procul.org/blog/2007/01/19/vai-bai-t%e1%bb%95ng-quan-v%e1%bb%81-c%e1%ba%a5u-truc-cac-m%e1%ba%a1ng-ph%e1%bb%a9c-t%e1%ba%a1p/</link>
		<comments>http://www.procul.org/blog/2007/01/19/vai-bai-t%e1%bb%95ng-quan-v%e1%bb%81-c%e1%ba%a5u-truc-cac-m%e1%ba%a1ng-ph%e1%bb%a9c-t%e1%ba%a1p/#comments</comments>
		<pubDate>Fri, 19 Jan 2007 21:30:54 +0000</pubDate>
		<dc:creator>NQH</dc:creator>
				<category><![CDATA[Mạng máy tính]]></category>
		<category><![CDATA[Thuật Toán]]></category>

		<guid isPermaLink="false">http://www.procul.org/blog/2007/01/19/vai-bai-t%e1%bb%95ng-quan-v%e1%bb%81-c%e1%ba%a5u-truc-cac-m%e1%ba%a1ng-ph%e1%bb%a9c-t%e1%ba%a1p/</guid>
		<description><![CDATA[M. E. J. Newman, The structure and function of complex networks, SIAM Review, vol. 45, no. 2, pp. 167&#8211;256, 2003. [pdf] J. Kleinberg. Navigation in a Small World. Nature 406(2000), 845. [pdf] J. Kleinberg. Complex Networks and Decentralized Search Algorithms. Proceedings of the International Congress of Mathematicians (ICM), 2006. [pdf]]]></description>
			<content:encoded><![CDATA[<ul>
<li> M. E. J. Newman, The structure and function of complex networks, SIAM Review, vol. 45, no. 2, pp. 167&#8211;256, 2003. [<a href="http://www-personal.umich.edu/~mejn/courses/2004/cscs535/review.pdf">pdf</a>]
<li> J. Kleinberg. Navigation in a Small World. Nature 406(2000), 845. [<a href="http://www.cs.cornell.edu/home/kleinber/nat00.pdf">pdf</a>]
<li> J. Kleinberg. Complex Networks and Decentralized Search Algorithms. Proceedings of the International Congress of Mathematicians (ICM), 2006. [<a href="http://www.cs.cornell.edu/home/kleinber/icm06-swn.pdf">pdf</a>]
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.procul.org/blog/2007/01/19/vai-bai-t%e1%bb%95ng-quan-v%e1%bb%81-c%e1%ba%a5u-truc-cac-m%e1%ba%a1ng-ph%e1%bb%a9c-t%e1%ba%a1p/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

