{"id":34465,"date":"2023-09-12T15:58:10","date_gmt":"2023-12-23T19:49:46","guid":{"rendered":"https:\/\/www.silicloud.com\/zh\/blog\/%e7%94%a8openflow%e3%80%81ruby%e3%80%81trema%e5%92%8copen-vswitch%e5%ae%9e%e7%8e%b0%e4%ba%86%e3%82%ba%e3%83%b3%e3%83%89%e3%82%b3%e3%82%ad%e3%83%a8%e3%82%b7%e5%8f%98%e6%8d%a2%e4%bb%a3%e7%90%86%e3%80%82\/"},"modified":"2024-05-03T23:24:23","modified_gmt":"2024-05-03T15:24:23","slug":"%e7%94%a8openflow%e3%80%81ruby%e3%80%81trema%e5%92%8copen-vswitch%e5%ae%9e%e7%8e%b0%e4%ba%86%e3%82%ba%e3%83%b3%e3%83%89%e3%82%b3%e3%82%ad%e3%83%a8%e3%82%b7%e5%8f%98%e6%8d%a2%e4%bb%a3%e7%90%86%e3%80%82","status":"publish","type":"post","link":"https:\/\/www.silicloud.com\/zh\/blog\/%e7%94%a8openflow%e3%80%81ruby%e3%80%81trema%e5%92%8copen-vswitch%e5%ae%9e%e7%8e%b0%e4%ba%86%e3%82%ba%e3%83%b3%e3%83%89%e3%82%b3%e3%82%ad%e3%83%a8%e3%82%b7%e5%8f%98%e6%8d%a2%e4%bb%a3%e7%90%86%e3%80%82\/","title":{"rendered":"\u7528OpenFlow\u3001Ruby\u3001Trema\u548cOpen vSwitch\u5b9e\u73b0\u4e86\u30ba\u30f3\u30c9\u30b3\u30ad\u30e8\u30b7\u53d8\u6362\u4ee3\u7406"},"content":{"rendered":"<p>\u53d7\u5230ZUNDOKO\u534f\u8bae\u7684\u542f\u53d1\uff0c\u6211\u51b3\u5b9a\u4e58\u4e0a\u8fd9\u80a1\u5927\u6d6a\uff0c\u4f7f\u7528OpenFlow\u521b\u5efa\u4e86ZUNDOKO\u7ee7\u627f\u4ee3\u7406\u3002<\/p>\n<p>\u6700\u8fd1\u5728\u4e2d\u56fd\u975e\u5e38\u6d41\u884c\u7684\u201c\u5522\u5450\uff08Zundoko\uff09\u7948\u613f\u6587\u201d\u6e90\u81ea\u4e0b\u9762\u7684\u63a8\u6587\uff0c\u5df2\u7ecf\u5728\u591a\u79cd\u8bed\u8a00\u4e2d\u5b9e\u73b0\u5e76\u6574\u7406\u6210\u4e86\u5522\u5450\u7948\u613f\u6587\u6982\u89c8\u3002\u539f\u672c\u4ee5\u4e3a\u53ea\u5728\u7f16\u7a0b\u9886\u57df\u6d41\u884c\uff0c\u4f46\u6700\u8fd1\u5728\u7f51\u7edc\u4e0a\u4e5f\u51fa\u73b0\u4e86\u5229\u7528Pcap4J\u5b9e\u73b0\u5522\u5450\u7948\u613f\u6587\u534f\u8bae\u7684\u6848\u4f8b\u3002<\/p>\n<blockquote><p>\u56e0\u4e3aJava\u7684\u8bfe\u7a0b\u8003\u8bd5\u8981\u6c42\u201c\u521b\u5efa\u5e76\u63cf\u8ff0\u4e00\u4e2a\u81ea\u5b9a\u4e49\u51fd\u6570\u201d\uff0c\u6240\u4ee5\u6211\u5199\u4e86\u4e00\u4e2a\u51fd\u6570\uff0c\u5b83\u4f1a\u6301\u7eed\u968f\u673a\u8f93\u51fa\u201c\u30ba\u30f3\u201d\u6216\u201c\u30c9\u30b3\u201d\uff0c\u76f4\u5230\u8f93\u51fa\u4e86\u201c\u30ba\u30f3\u201d\u3001\u201c\u30ba\u30f3\u201d\u3001\u201c\u30ba\u30f3\u201d\u3001\u201c\u30ba\u30f3\u201d\u3001\u201c\u30c9\u30b3\u201d\u8fd9\u4e2a\u6570\u7ec4\uff0c\u7136\u540e\u8f93\u51fa\u201c\u30ad\u30fb\u30e8\u30fb\u30b7\uff01\u201d\u5e76\u7ed3\u675f\u3002\u8fd9\u4e2a\u51fd\u6570\u83b7\u5f97\u4e86\u6ee1\u5206\u5e76\u62ff\u5230\u4e86\u5b66\u5206\u3002<\/p><\/blockquote>\n<p>\u5229\u7528\u7f51\u7edc\u6280\u80fd\uff0c\u4e3a\u4e86\u63d0\u5347\u6700\u8fd1\u5f00\u59cb\u5b66\u4e60\u7684OpenFlow\u6280\u80fd\uff0c\u6211\u5728OpenFlow\u63a7\u5236\u5668Trema\u4e2d\u5c1d\u8bd5\u5b9e\u73b0\u4e86\u4e00\u4e2a\u8f6c\u6362\u4ee3\u7406\uff0c\u5e76\u5728\u8fd9\u4e2a\u6d6a\u6f6e\u4e2d\u8bd5\u7740\u8ddf\u4e0a\u4e86\u8fdb\u5c55\u3002<\/p>\n<h1>\u300c\u30ba\u30f3\u30c9\u30b3\u30ad\u30e8\u30b7\u5909\u63db\u30d7\u30ed\u30ad\u30b7\u300d\u7684\u542b\u4e49\u662f\u5c06\u8f93\u5165\u7684\u5185\u5bb9\u8f6c\u6362\u4e3a\u7c7b\u4f3c\u4e8e\u65e5\u672c\u4f20\u7edf\u97f3\u4e50\u6e38\u620f\u4e2d\u7684&#8221;\u30ba\u30f3\u30c9\u30b3&#8221;\u97f3\u9891\u7ec4\u5408\u7684\u4ee3\u7406\u5de5\u5177\u3002<\/h1>\n<p>\u5f53\u5728TCP\u901a\u4fe1\u7684\u6570\u636e\u6d41\u4e2d\u4ee5UTF-8\u7f16\u7801\u627e\u5230\u5b57\u7b26\u4e32&#8221;\u30ba\u30f3\u30ba\u30f3\u30ba\u30f3\u30ba\u30f3\u30ba\u30f3\u30c9\u30b3&#8221;\u65f6\uff0c\u5c06\u5176\u8f6c\u6362\u4e3a&#8221;\u30ba\u30f3\u30ba\u30f3\u30ba\u30f3\u30ba\u30f3\u30ba\u30f3\u30c9\u30b3 \u30ad\u30fb\u30e8\u30fb\u30b7\uff01&#8221;\uff08\u5373\u8fdb\u884c\u30ba\u30f3\u30c9\u30b3\u30ad\u30e8\u30b7\u8f6c\u6362\uff09\u3002<\/p>\n<p>\u6211\u5011\u9019\u6b21\u4f7f\u7528\u4e86ECHO\u5354\u8b70\uff08RFC 862\uff09\u4f86\u9a57\u8b49Zundoko Kiyoshi\u8f49\u63db\u4ee3\u7406\u7684\u904b\u4f5c\u3002<\/p>\n<p>\u6309\u7167\u4e0b\u9762\u7684\u56fe\u793a\uff0c\u4f7f\u7528OpenFlow\u5c06\u201cECHO\u5ba2\u6237\u7aef\u201d\u548c\u201cECHO\u670d\u52a1\u5668\u201d\u7684TCP\u901a\u4fe1\u8f6c\u53d1\u5230\u201cZUNDOKO TCP\u4ee3\u7406\u201d\u3002\u5728\u201cZUNDOKO TCP\u4ee3\u7406\u201d\u4e2d\uff0c\u5b83\u4ee3\u7406\u4e0e\u201cECHO\u670d\u52a1\u5668\u201d\u7684TCP\u901a\u4fe1\uff0c\u5e76\u5c06\u63a5\u6536\u5230\u7684\u6570\u636e\u8fdb\u884c\u201cZundoko Kiyoshi\u201d\u8f6c\u6362\uff0c\u7136\u540e\u53d1\u9001\u56de\u201cECHO\u5ba2\u6237\u7aef\u201d\u3002<\/p>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d1d5f37434c4406c13157\/8-0.png\" alt=\"\u6982\u8981.PNG\" \/><\/div>\n<h2>\u8fdb\u884c<\/h2>\n<p>\u6309\u7167\u4e0b\u56fe\u6240\u793a\uff0c\u901a\u8fc7&#8221;OpenFlow\u4ea4\u6362\u673a&#8221;\u5bf9\u76ee\u6807\u5730\u5740\u7aef\u53e3\u8fdb\u884c\u8f6c\u6362\uff08\u76ee\u6807NATP\u8f6c\u6362\uff09\uff0c\u5c06\u76ee\u6807\u626d\u66f2\u4e3a&#8221;TCP\u4ee3\u7406&#8221;\u3002<br \/>\n\u5f53&#8221;OpenFlow\u63a7\u5236\u5668&#8221;\u6536\u5230&#8221;TCP SYN&#8221;\u7684PACKET_IN\u65f6\uff0c\u4f1a\u4f7f\u7528FLOW_MOD\u8fdb\u884c\u6ce8\u518c\uff0c\u4ee5\u8fdb\u884c\u6b63\u5411\u6d41\u548c\u53cd\u5411\u6d41\u7684\u76ee\u6807NAPT\u8f6c\u6362\uff0c\u5e76\u5c06\u539f\u59cb\u6570\u636e\u5305\u53d1\u9001\u4e3aPACKET_OUT\u3002\u5728\u6ce8\u518c\u6d41\u4e4b\u540e\uff0c\u7531\u4e8e\u6240\u6709\u64cd\u4f5c\u90fd\u7531&#8221;OpenFlow\u4ea4\u6362\u673a&#8221;\u5b8c\u6210\uff0c\u56e0\u6b64\u4e0d\u4f1a\u518d\u4ea7\u751fPACKET_IN\u3002<\/p>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d1d5f37434c4406c13157\/11-0.png\" alt=\"\u69cb\u6210.PNG\" \/><\/div>\n<h3>NAPT\u7684\u95ee\u9898\u4e4b\u4e00\u662f\u5b9b\u5148\u95ee\u9898\u3002<\/h3>\n<p>\u666e\u901a\u7684\u60c5\u51b5\u4e0b\u8fdb\u884cNAPT\u8f6c\u6362\u65f6\uff0c\u539f\u59cb\u76ee\u6807\u5730\u5740\u5c06\u4f1a\u4e22\u5931\uff0c\u5bfc\u81f4\u5728TCP\u4ee3\u7406\u4e2d\u65e0\u6cd5\u786e\u5b9a\u76ee\u6807\u5730\u5740\u3002\u800c\u5728HTTP\u4ee3\u7406\u4e2d\uff0c\u7531\u4e8e\u76ee\u6807\u4fe1\u606f\u5b58\u5728\u4e8eHTTP\u8bf7\u6c42\u5934\u4e2d\uff0c\u56e0\u6b64\u53ef\u4ee5\u901a\u8fc7\u89e3\u6790\u8bf7\u6c42\u5934\u6765\u786e\u5b9a\u76ee\u6807\u3002\u7136\u800c\uff0c\u5bf9\u4e8e\u901a\u7528\u7684TCP\u4ee3\u7406\uff0c\u7531\u4e8e\u7f3a\u4e4f\u7528\u4e8e\u89e3\u6790\u7684\u5934\u90e8\u4fe1\u606f\uff0c\u65e0\u6cd5\u786e\u5b9a\u76ee\u6807\u3002<\/p>\n<h3>NAPT\u7684\u89e3\u51b3\u65b9\u6848\u662f\u4ec0\u4e48\uff1f<\/h3>\n<p>\u4e3a\u4e86\u89e3\u51b3\u4e0a\u8ff0\u95ee\u9898\uff0c\u6211\u4eec\u5c06\u5b9e\u65bd&#8221;\u76ee\u6807\u7f13\u5b58&#8221;\u3002\u6211\u4eec\u4f1a\u5c06\u672a\u7ecfNAPT\u8f6c\u6362\u7684\u76ee\u6807\u4fe1\u606f\u6ce8\u518c\u5230&#8221;\u76ee\u6807\u7f13\u5b58&#8221;\u4e2d\uff0c\u5e76\u5728TCP\u4ee3\u7406\u4e2d\u4f7f\u7528\u5b83\u6765\u786e\u5b9a\u76ee\u6807\u3002<br \/>\n&#8220;OpenFlow\u63a7\u5236\u5668&#8221;\u53ef\u4ee5\u4e86\u89e3\u8f6c\u6362\u4e4b\u524d\u7684\u76ee\u6807IP\u5730\u5740\u548c\u7aef\u53e3\u53f7\u3002\u6211\u4eec\u4f1a\u5c06&#8221;\u6e90IP\u5730\u5740\u548c\u7aef\u53e3\u53f7&#8221;\u4f5c\u4e3a&#8221;\u76ee\u6807\u7f13\u5b58&#8221;\u7684\u952e\uff0c\u5e76\u6ce8\u518c&#8221;\u76ee\u6807IP\u5730\u5740\u548c\u7aef\u53e3\u53f7&#8221;\u3002<br \/>\nTCP\u4ee3\u7406\u5c06\u53c2\u8003&#8221;\u76ee\u6807\u7f13\u5b58&#8221;\u6765\u786e\u5b9a\u76ee\u6807\uff0c\u5e76\u4f5c\u4e3a\u901a\u7528TCP\u4ee3\u7406\u8bbf\u95ee\u76ee\u6807\u670d\u52a1\u5668\u3002<\/p>\n<h2>\u73af\u5883<\/h2>\n<p>\u4ee5\u4e0b\u662f\u6211\u4e3b\u8981\u4f7f\u7528\u7684\u8f6f\u4ef6\u548c\u5e93\u3002<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">OpenFlow 1.0<\/ul>\n<\/li>\n<\/ul>\n<p>\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9: Trema 0.10.1<br \/>\n\u30b9\u30a4\u30c3\u30c1: Open vSwitch 2.0.2<\/p>\n<p>Ubuntu 14.04<\/p>\n<p>Memcached 1.4.14\uff1a\u5b9b\u5148\u30ad\u30e3\u30c3\u30b7\u30e5<br \/>\nxinetd\uff1aecho\u30b5\u30fc\u30d0<\/p>\n<p>Ruby 2.2.4<\/p>\n<p>trema 0.10.1 : OpenFlow\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9<br \/>\nmemcache-client 1.8.5 : \u5b9b\u5148\u30ad\u30e3\u30c3\u30b7\u30e5 \u30a2\u30af\u30bb\u30b9\u7528<\/p>\n<p>\u6211\u5728VirtualBox\u4e0a\u8bbe\u7f6e\u4e86\u56db\u4e2a\u8fd0\u884cUbuntu\u7684\u7ec8\u7aef\uff0c\u5e76\u6784\u5efa\u4e86\u73af\u5883\u3002\u6211\u5c06\u7f51\u7edc\u5206\u5272\u4e3a\u5185\u90e8\u7cfb\u7edf\u548c\u7ba1\u7406\u7cfb\u7edf\u3002<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">u01\u30db\u30b9\u30c8<\/ul>\n<\/li>\n<\/ul>\n<p>ECHO\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\uff1azecho_client.rb\u3067\u5b9f\u88c5<\/p>\n<p>u02\u30db\u30b9\u30c8<\/p>\n<p>ECHO\u30b5\u30fc\u30d0\uff1axinetd\u3067TCP ECHO\u30b5\u30fc\u30d0\u3092\u52d5\u4f5c<\/p>\n<p>u03\u30db\u30b9\u30c8<\/p>\n<p>\u30ba\u30f3\u30c9\u30b3\u30ad\u30e8\u30b7\u5909\u63db\u30d7\u30ed\u30ad\u30b7\uff1azecho_proxy.rb\u3067\u5b9f\u88c5<\/p>\n<p>ovs1\u30db\u30b9\u30c8<\/p>\n<p>OpenFlow\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\uff08Trema\uff09\uff1azecho_trema.rb\u3067\u5b9f\u88c5<br \/>\nOpenFlow\u30b9\u30a4\u30c3\u30c1\uff08Open vSwitch\uff09\uff1aOVS\u3067u01\u30db\u30b9\u30c8\u3068\u5185\u90e8\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3092L2\u30d6\u30ea\u30c3\u30b8<br \/>\n\u5b9b\u5148\u30ad\u30e3\u30c3\u30b7\u30e5\uff08memcached\u30b5\u30fc\u30d0\uff09<\/p>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d1d5f37434c4406c13157\/21-0.png\" alt=\"\u74b0\u5883.PNG\" \/><\/div>\n<h2>ovs1 \u4e3b\u673a<\/h2>\n<p>ovs1\u30db\u30b9\u30c8\u3067\u306f\u3001\u4e0b\u8a18\u306e\u3088\u3046\u306bOpenFlow\u30b9\u30a4\u30c3\u30c1\u306e\u8a2d\u5b9a\u3057\u307e\u3059\u3002OVS\u306e\u30b9\u30a4\u30c3\u30c1\u3068\u3057\u3066ofs0\u3092\u5b9a\u7fa9\u3057\u3001\u30dd\u30fc\u30c8\u3068\u7269\u7406\u30dd\u30fc\u30c8\u3092\u52a0\u3048\u307e\u3059\u3002\u30ed\u30fc\u30ab\u30eb\u30db\u30b9\u30c8\u306eOpenFlow\u306e\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u3092\u6307\u5b9a\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n<pre class=\"post-pre\"><code>sudo ovs-vsctl init\r\nsudo ovs-vsctl add-br ofs0\r\nsudo ifconfig eth1 up\r\nsudo ifconfig eth2 up\r\n\r\nsudo ovs-vsctl add-port ofs0 eth1\r\nsudo ovs-vsctl add-port ofs0 eth2\r\n\r\nsudo ovs-vsctl set bridge ofs0 protocols=OpenFlow10\r\nsudo ovs-vsctl set-controller ofs0 tcp:127.0.0.1:6653\r\n<\/code><\/pre>\n<p>\u8bbe\u7f6e\u7ed3\u679c\u5982\u4e0b\u6240\u793a\u3002<\/p>\n<pre class=\"post-pre\"><code>$ sudo ovs-vsctl show\r\nce3126fd-82dd-4f67-abdd-a19aa23ef05e\r\n    Bridge \"ofs0\"\r\n        Controller \"tcp:127.0.0.1:6653\"\r\n            is_connected: true\r\n        Port \"eth2\"\r\n            Interface \"eth2\"\r\n        Port \"ofs0\"\r\n            Interface \"ofs0\"\r\n                type: internal\r\n        Port \"eth1\"\r\n            Interface \"eth1\"\r\n    ovs_version: \"2.0.2\"\r\n<\/code><\/pre>\n<h2>\u6e90\u4ee3\u7801<br \/>\n\u7f16\u7a0b\u6e90\u4ee3\u7801<\/h2>\n<h3>ECHO\u5ba2\u6237\u7aef<\/h3>\n<p>\u4ee5\u4e0b\u662f\u4e00\u4e2a\u7b80\u5355\u7684\u811a\u672c\uff0c\u5b83\u4f1a\u5411TCP ECHO\u7aef\u53e3\uff08TCP7\u53f7\uff09\u53d1\u9001\u968f\u673a\u751f\u6210\u7684\u201c\u30ba\u30f3\u201d\u548c\u201c\u30c9\u30b3\u201d\u5b57\u7b26\u4e32\uff0c\u5e76\u663e\u793a\u63a5\u6536\u7ed3\u679c\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"nb\">require<\/span> <span class=\"s1\">'socket'<\/span>\r\n<span class=\"n\">socket<\/span> <span class=\"o\">=<\/span> <span class=\"no\">TCPSocket<\/span><span class=\"p\">.<\/span><span class=\"nf\">open<\/span><span class=\"p\">(<\/span><span class=\"s1\">'172.16.0.2'<\/span><span class=\"p\">,<\/span> <span class=\"mi\">7<\/span><span class=\"p\">)<\/span>\r\n<span class=\"n\">words<\/span> <span class=\"o\">=<\/span> <span class=\"sx\">%w(\u30ba\u30f3 \u30c9\u30b3)<\/span>\r\n<span class=\"mi\">10<\/span><span class=\"p\">.<\/span><span class=\"nf\">times<\/span> <span class=\"k\">do<\/span>\r\n  <span class=\"n\">string<\/span> <span class=\"o\">=<\/span> <span class=\"no\">Array<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"mi\">5<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"n\">words<\/span><span class=\"p\">.<\/span><span class=\"nf\">sample<\/span> <span class=\"p\">}.<\/span><span class=\"nf\">join<\/span>\r\n  <span class=\"nb\">puts<\/span> <span class=\"s2\">\"SEND: <\/span><span class=\"si\">#{<\/span><span class=\"n\">string<\/span><span class=\"si\">}<\/span><span class=\"s2\">\"<\/span>\r\n  <span class=\"n\">socket<\/span><span class=\"p\">.<\/span><span class=\"nf\">puts<\/span> <span class=\"n\">string<\/span>\r\n  <span class=\"nb\">puts<\/span> <span class=\"s2\">\"RECV: <\/span><span class=\"si\">#{<\/span><span class=\"n\">socket<\/span><span class=\"p\">.<\/span><span class=\"nf\">gets<\/span><span class=\"si\">}<\/span><span class=\"s2\">\"<\/span>\r\n  <span class=\"nb\">puts<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<h3>\u6253\u5f00\u6d41\u63a7\u5236\u5668<\/h3>\n<p>switch_ready\u30e1\u30bd\u30c3\u30c9:<br \/>\n\u4eca\u56de\u306fu01\u30db\u30b9\u30c8\u304b\u3089\u9001\u4fe1\u3055\u308c\u305f\u30d1\u30b1\u30c3\u30c8\u306e\u307f\u3092\u51e6\u7406\u5bfe\u8c61\u3068\u3059\u308b\u305f\u3081\u3001u01\u4ee5\u5916\u306e\u30dd\u30fc\u30c8\u304b\u3089\u306e\u901a\u4fe1\u3068\u30d6\u30ed\u30fc\u30c9\u30ad\u30e3\u30b9\u30c8\u901a\u4fe1\u7528\u306e\u901a\u4fe1\u30d5\u30ed\u30fc\u3092\u8a2d\u5b9a\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n<p>packet_in\u30e1\u30bd\u30c3\u30c9:<br \/>\nu01\u30db\u30b9\u30c8\u304b\u3089\u53d7\u4fe1\u3057\u305f\u30d1\u30b1\u30c3\u30c8\u3092\u3001NAPT\u5909\u63db\u5bfe\u8c61\u304b\u3069\u3046\u304bsend_nat_packet_and_add_nat_flow\u3067\u632f\u308a\u5206\u3051\u3066\u3001NAPT\u5909\u63db\u5bfe\u8c61\u5916\u3060\u3063\u305f\u5834\u5408\u306f\u3001\u901a\u5e38\u901a\u308aPACKET_OUT\u3057\u307e\u3059\u3002<\/p>\n<p>send_nat_packet_and_add_nat_flow\u30e1\u30bd\u30c3\u30c9:<br \/>\nNAPT\u5909\u63db\u5bfe\u8c61\u306eTCP\u30d1\u30b1\u30c3\u30c8\u3060\u3063\u305f\u5834\u5408\u306b\u306f\u3001NAPT\u5909\u63db\u7528\u306e\u9806\u65b9\u5411\u30d5\u30ed\u30fc\u30c8\u9006\u65b9\u5411\u30d5\u30ed\u30fc\u3092OpenFlow\u30b9\u30a4\u30c3\u30c1\u306b\u8a2d\u5b9a\u3057\u307e\u3059\u3002\u4f75\u305b\u3066\u300c\u5b9b\u5148\u30ad\u30e3\u30c3\u30b7\u30e5\u300d\u306b\u5b9b\u5148\u60c5\u5831\u3092\u8a2d\u5b9a\u3057\u307e\u3059\u3002\u305d\u306e\u5f8cPACKET_OUT\u3057\u307e\u3059\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"nb\">require<\/span> <span class=\"s1\">'memcache'<\/span>\r\n\r\n<span class=\"no\">MEMCACHE<\/span> <span class=\"o\">=<\/span> <span class=\"no\">MemCache<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span> <span class=\"s1\">'192.168.88.4:11211'<\/span>\r\n\r\n<span class=\"no\">PROXY_L1_PORT<\/span>  <span class=\"o\">=<\/span> <span class=\"mi\">2<\/span>\r\n<span class=\"no\">PROXY_MAC<\/span>      <span class=\"o\">=<\/span> <span class=\"s1\">'08:00:27:b6:63:f2'<\/span><span class=\"p\">.<\/span><span class=\"nf\">freeze<\/span>\r\n<span class=\"no\">PROXY_IP<\/span>       <span class=\"o\">=<\/span> <span class=\"s1\">'172.16.0.3\/32'<\/span><span class=\"p\">.<\/span><span class=\"nf\">freeze<\/span>\r\n<span class=\"no\">PROXY_TCP_PORT<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">10000<\/span>\r\n\r\n<span class=\"no\">INTERNAL_PORT<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">1<\/span>\r\n<span class=\"no\">EXTERNAL_PORT<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">2<\/span>\r\n<span class=\"no\">IP_PROTO_TCP<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">6<\/span>\r\n\r\n<span class=\"c1\"># ZEcho Trema<\/span>\r\n<span class=\"k\">class<\/span> <span class=\"nc\">ZechoTrema<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">Trema<\/span><span class=\"o\">::<\/span><span class=\"no\">Controller<\/span>\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">start<\/span><span class=\"p\">(<\/span><span class=\"n\">_args<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"n\">logger<\/span><span class=\"p\">.<\/span><span class=\"nf\">info<\/span> <span class=\"s2\">\"<\/span><span class=\"si\">#{<\/span><span class=\"nb\">name<\/span><span class=\"si\">}<\/span><span class=\"s2\"> started.\"<\/span>\r\n  <span class=\"k\">end<\/span>\r\n\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">switch_ready<\/span><span class=\"p\">(<\/span><span class=\"n\">datapath_id<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"n\">logger<\/span><span class=\"p\">.<\/span><span class=\"nf\">info<\/span> <span class=\"s2\">\"switch_ready: <\/span><span class=\"si\">#{<\/span><span class=\"n\">datapath_id<\/span><span class=\"si\">}<\/span><span class=\"s2\">\"<\/span>\r\n    <span class=\"n\">send_flow_mod_add<\/span><span class=\"p\">(<\/span>\r\n      <span class=\"n\">datapath_id<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"ss\">match: <\/span><span class=\"no\">Match<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"ss\">in_port: <\/span><span class=\"no\">EXTERNAL_PORT<\/span><span class=\"p\">),<\/span>\r\n      <span class=\"ss\">actions: <\/span><span class=\"no\">SendOutPort<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"no\">INTERNAL_PORT<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"p\">)<\/span>\r\n    <span class=\"n\">send_flow_mod_add<\/span><span class=\"p\">(<\/span>\r\n      <span class=\"n\">datapath_id<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"ss\">match: <\/span><span class=\"no\">Match<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"ss\">destination_mac_address: <\/span><span class=\"s1\">'FF:FF:FF:FF:FF:FF'<\/span><span class=\"p\">),<\/span>\r\n      <span class=\"ss\">actions: <\/span><span class=\"no\">SendOutPort<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"ss\">:flood<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"p\">)<\/span>\r\n  <span class=\"k\">end<\/span>\r\n\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">switch_disconnected<\/span><span class=\"p\">(<\/span><span class=\"n\">datapath_id<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"n\">logger<\/span><span class=\"p\">.<\/span><span class=\"nf\">info<\/span> <span class=\"s2\">\"switch_disconnected: <\/span><span class=\"si\">#{<\/span><span class=\"n\">datapath_id<\/span><span class=\"si\">}<\/span><span class=\"s2\">\"<\/span>\r\n  <span class=\"k\">end<\/span>\r\n\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">packet_in<\/span><span class=\"p\">(<\/span><span class=\"n\">datapath_id<\/span><span class=\"p\">,<\/span> <span class=\"n\">message<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"n\">packet_send<\/span> <span class=\"o\">=<\/span> <span class=\"n\">send_nat_packet_and_add_nat_flow<\/span><span class=\"p\">(<\/span><span class=\"n\">datapath_id<\/span><span class=\"p\">,<\/span> <span class=\"n\">message<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"k\">unless<\/span> <span class=\"n\">packet_send<\/span>\r\n      <span class=\"n\">send_packet_out<\/span><span class=\"p\">(<\/span>\r\n        <span class=\"n\">datapath_id<\/span><span class=\"p\">,<\/span>\r\n        <span class=\"ss\">packet_in: <\/span><span class=\"n\">message<\/span><span class=\"p\">,<\/span>\r\n        <span class=\"ss\">actions: <\/span><span class=\"no\">SendOutPort<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"no\">EXTERNAL_PORT<\/span><span class=\"p\">)<\/span>\r\n      <span class=\"p\">)<\/span>\r\n    <span class=\"k\">end<\/span>\r\n  <span class=\"k\">end<\/span>\r\n\r\n  <span class=\"kp\">private<\/span>\r\n\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">send_nat_packet_and_add_nat_flow<\/span><span class=\"p\">(<\/span><span class=\"n\">datapath_id<\/span><span class=\"p\">,<\/span> <span class=\"n\">message<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"k\">return<\/span> <span class=\"kp\">false<\/span> <span class=\"k\">unless<\/span> <span class=\"n\">message<\/span><span class=\"p\">.<\/span><span class=\"nf\">in_port<\/span> <span class=\"o\">==<\/span> <span class=\"no\">INTERNAL_PORT<\/span>\r\n    <span class=\"k\">return<\/span> <span class=\"kp\">false<\/span> <span class=\"k\">unless<\/span> <span class=\"no\">Pio<\/span><span class=\"o\">::<\/span><span class=\"no\">Parser<\/span><span class=\"o\">::<\/span><span class=\"no\">IPv4Packet<\/span> <span class=\"o\">==<\/span> <span class=\"n\">message<\/span><span class=\"p\">.<\/span><span class=\"nf\">data<\/span><span class=\"p\">.<\/span><span class=\"nf\">class<\/span>\r\n    <span class=\"k\">return<\/span> <span class=\"kp\">false<\/span> <span class=\"k\">unless<\/span> <span class=\"n\">message<\/span><span class=\"p\">.<\/span><span class=\"nf\">ip_protocol<\/span> <span class=\"o\">==<\/span> <span class=\"no\">IP_PROTO_TCP<\/span>\r\n\r\n    <span class=\"n\">src_mac<\/span>  <span class=\"o\">=<\/span> <span class=\"n\">message<\/span><span class=\"p\">.<\/span><span class=\"nf\">source_mac<\/span>\r\n    <span class=\"n\">src_ip<\/span>   <span class=\"o\">=<\/span> <span class=\"n\">message<\/span><span class=\"p\">.<\/span><span class=\"nf\">source_ip_address<\/span>\r\n    <span class=\"n\">src_port<\/span> <span class=\"o\">=<\/span> <span class=\"n\">message<\/span><span class=\"p\">.<\/span><span class=\"nf\">transport_source_port<\/span>\r\n\r\n    <span class=\"n\">dst_mac<\/span>  <span class=\"o\">=<\/span> <span class=\"n\">message<\/span><span class=\"p\">.<\/span><span class=\"nf\">destination_mac<\/span>\r\n    <span class=\"n\">dst_ip<\/span>   <span class=\"o\">=<\/span> <span class=\"n\">message<\/span><span class=\"p\">.<\/span><span class=\"nf\">destination_ip_address<\/span>\r\n    <span class=\"n\">dst_port<\/span> <span class=\"o\">=<\/span> <span class=\"n\">message<\/span><span class=\"p\">.<\/span><span class=\"nf\">transport_destination_port<\/span>\r\n\r\n    <span class=\"no\">MEMCACHE<\/span><span class=\"p\">.<\/span><span class=\"nf\">set<\/span> <span class=\"s2\">\"<\/span><span class=\"si\">#{<\/span><span class=\"n\">src_ip<\/span><span class=\"si\">}<\/span><span class=\"s2\">:<\/span><span class=\"si\">#{<\/span><span class=\"n\">src_port<\/span><span class=\"si\">}<\/span><span class=\"s2\">\"<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"<\/span><span class=\"si\">#{<\/span><span class=\"n\">dst_ip<\/span><span class=\"si\">}<\/span><span class=\"s2\">:<\/span><span class=\"si\">#{<\/span><span class=\"n\">dst_port<\/span><span class=\"si\">}<\/span><span class=\"s2\">\"<\/span>\r\n    <span class=\"n\">logger<\/span><span class=\"p\">.<\/span><span class=\"nf\">info<\/span> <span class=\"s2\">\"NAT <\/span><span class=\"si\">#{<\/span><span class=\"n\">src_ip<\/span><span class=\"si\">}<\/span><span class=\"s2\">:<\/span><span class=\"si\">#{<\/span><span class=\"n\">src_port<\/span><span class=\"si\">}<\/span><span class=\"s2\"> =&gt; <\/span><span class=\"si\">#{<\/span><span class=\"n\">dst_ip<\/span><span class=\"si\">}<\/span><span class=\"s2\">:<\/span><span class=\"si\">#{<\/span><span class=\"n\">dst_port<\/span><span class=\"si\">}<\/span><span class=\"s2\"> via <\/span><span class=\"si\">#{<\/span><span class=\"no\">PROXY_IP<\/span><span class=\"si\">}<\/span><span class=\"s2\">:<\/span><span class=\"si\">#{<\/span><span class=\"no\">PROXY_TCP_PORT<\/span><span class=\"si\">}<\/span><span class=\"s2\">\"<\/span>\r\n\r\n    <span class=\"c1\"># forward rule<\/span>\r\n    <span class=\"n\">forward_match<\/span> <span class=\"o\">=<\/span> <span class=\"no\">ExactMatch<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"n\">message<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"n\">forward_actions<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span>\r\n      <span class=\"no\">Pio<\/span><span class=\"o\">::<\/span><span class=\"no\">OpenFlow10<\/span><span class=\"o\">::<\/span><span class=\"no\">SetDestinationMacAddress<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"no\">PROXY_MAC<\/span><span class=\"p\">),<\/span>\r\n      <span class=\"no\">Pio<\/span><span class=\"o\">::<\/span><span class=\"no\">OpenFlow10<\/span><span class=\"o\">::<\/span><span class=\"no\">SetDestinationIpAddress<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"no\">PROXY_IP<\/span><span class=\"p\">),<\/span>\r\n      <span class=\"no\">Pio<\/span><span class=\"o\">::<\/span><span class=\"no\">OpenFlow10<\/span><span class=\"o\">::<\/span><span class=\"no\">SetTransportDestinationPort<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"no\">PROXY_TCP_PORT<\/span><span class=\"p\">),<\/span>\r\n      <span class=\"no\">SendOutPort<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"no\">PROXY_L1_PORT<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"p\">]<\/span>\r\n    <span class=\"n\">send_flow_mod_add<\/span><span class=\"p\">(<\/span>\r\n      <span class=\"n\">datapath_id<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"ss\">priority: <\/span><span class=\"mi\">1000<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"ss\">idle_timeout: <\/span><span class=\"mi\">300<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"ss\">match: <\/span><span class=\"n\">forward_match<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"ss\">actions: <\/span><span class=\"n\">forward_actions<\/span>\r\n    <span class=\"p\">)<\/span>\r\n\r\n    <span class=\"c1\"># reverse rule<\/span>\r\n    <span class=\"n\">reverse_match<\/span> <span class=\"o\">=<\/span> <span class=\"no\">ExactMatch<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"n\">message<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"n\">reverse_match<\/span><span class=\"p\">.<\/span><span class=\"nf\">in_port<\/span>                    <span class=\"o\">=<\/span> <span class=\"no\">PROXY_L1_PORT<\/span>\r\n    <span class=\"n\">reverse_match<\/span><span class=\"p\">.<\/span><span class=\"nf\">source_mac_address<\/span>         <span class=\"o\">=<\/span> <span class=\"no\">PROXY_MAC<\/span>\r\n    <span class=\"n\">reverse_match<\/span><span class=\"p\">.<\/span><span class=\"nf\">destination_mac_address<\/span>    <span class=\"o\">=<\/span> <span class=\"n\">src_mac<\/span>\r\n    <span class=\"n\">reverse_match<\/span><span class=\"p\">.<\/span><span class=\"nf\">source_ip_address<\/span>          <span class=\"o\">=<\/span> <span class=\"no\">PROXY_IP<\/span>\r\n    <span class=\"n\">reverse_match<\/span><span class=\"p\">.<\/span><span class=\"nf\">destination_ip_address<\/span>     <span class=\"o\">=<\/span> <span class=\"n\">src_ip<\/span>\r\n    <span class=\"n\">reverse_match<\/span><span class=\"p\">.<\/span><span class=\"nf\">transport_source_port<\/span>      <span class=\"o\">=<\/span> <span class=\"no\">PROXY_TCP_PORT<\/span>\r\n    <span class=\"n\">reverse_match<\/span><span class=\"p\">.<\/span><span class=\"nf\">transport_destination_port<\/span> <span class=\"o\">=<\/span> <span class=\"n\">src_port<\/span>\r\n    <span class=\"n\">reverse_actions<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span>\r\n      <span class=\"no\">Pio<\/span><span class=\"o\">::<\/span><span class=\"no\">OpenFlow10<\/span><span class=\"o\">::<\/span><span class=\"no\">SetSourceMacAddress<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"n\">dst_mac<\/span><span class=\"p\">),<\/span>\r\n      <span class=\"no\">Pio<\/span><span class=\"o\">::<\/span><span class=\"no\">OpenFlow10<\/span><span class=\"o\">::<\/span><span class=\"no\">SetSourceIpAddress<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"n\">dst_ip<\/span><span class=\"p\">),<\/span>\r\n      <span class=\"no\">Pio<\/span><span class=\"o\">::<\/span><span class=\"no\">OpenFlow10<\/span><span class=\"o\">::<\/span><span class=\"no\">SetTransportSourcePort<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"n\">dst_port<\/span><span class=\"p\">),<\/span>\r\n      <span class=\"no\">SendOutPort<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"n\">message<\/span><span class=\"p\">.<\/span><span class=\"nf\">in_port<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"p\">]<\/span>\r\n    <span class=\"n\">send_flow_mod_add<\/span><span class=\"p\">(<\/span>\r\n      <span class=\"n\">datapath_id<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"ss\">priority: <\/span><span class=\"mi\">1000<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"ss\">idle_timeout: <\/span><span class=\"mi\">300<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"ss\">match: <\/span><span class=\"n\">reverse_match<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"ss\">actions: <\/span><span class=\"n\">reverse_actions<\/span>\r\n    <span class=\"p\">)<\/span>\r\n\r\n    <span class=\"n\">send_packet_out<\/span><span class=\"p\">(<\/span>\r\n      <span class=\"n\">datapath_id<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"ss\">packet_in: <\/span><span class=\"n\">message<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"ss\">actions: <\/span><span class=\"n\">forward_actions<\/span>\r\n    <span class=\"p\">)<\/span>\r\n\r\n    <span class=\"k\">return<\/span> <span class=\"kp\">true<\/span>\r\n  <span class=\"k\">rescue<\/span> <span class=\"no\">NotImplementedError<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"n\">e<\/span>\r\n    <span class=\"n\">logger<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span> <span class=\"s2\">\"<\/span><span class=\"si\">#{<\/span><span class=\"n\">e<\/span><span class=\"si\">}<\/span><span class=\"s2\">: <\/span><span class=\"si\">#{<\/span><span class=\"n\">message<\/span><span class=\"p\">.<\/span><span class=\"nf\">data<\/span><span class=\"si\">}<\/span><span class=\"s2\">\"<\/span>\r\n  <span class=\"k\">end<\/span>\r\n\r\n  <span class=\"kp\">false<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<h3>\u30ba\u30f3\u30c9\u30b3\u30ad\u30e8\u30b7\u5909\u63db\u30d7\u30ed\u30ad\u30b7<\/h3>\n<p>\u8fd9\u4e2aZechoProxyServer\u7c7b\u4f1a\u5728\u4ee3\u7406\u7aef\u53e3\u4e0a\u8fdb\u884c\u76d1\u542c\uff0c\u5e76\u4e14\u7531ZechoProxyClient\u7c7b\u52a8\u6001\u751f\u6210\uff0c\u6bcf\u5f53\u6709\u8fde\u63a5\u8bf7\u6c42\u65f6\u3002<\/p>\n<p>ZechoProxyServer\u7c7b\uff1a<br \/>\n\u8be5\u7c7b\u76d1\u542cPROXY_TCP_PORT\u7aef\u53e3\uff0c\u5f53\u63a5\u6536\u5230\u6765\u81ea\u5ba2\u6237\u7aef\u7684\u8fde\u63a5\u8bf7\u6c42\u65f6\uff0c\u4f1a\u751f\u6210\u4e00\u4e2aZechoProxyClient\u7c7b\u7684\u5b9e\u4f8b\u3002\u8fd9\u662f\u4e00\u4e2a\u7b80\u5355\u7684\u5b9e\u73b0\u3002<\/p>\n<p>ZechoProxyClient\u7c7b\uff1a<br \/>\n\u6839\u636e\u53d1\u9001\u65b9\u7684IP\u5730\u5740\u548c\u7aef\u53e3\u53f7\uff0c\u67e5\u9605&#8221;\u76ee\u6807\u7f13\u5b58&#8221;\uff0c\u83b7\u53d6\u8fde\u63a5\u7684\u76ee\u6807IP\u5730\u5740\u548c\u7aef\u53e3\u53f7\u3002\u7136\u540e\uff0c\u901a\u8fc7TCPSocket.new\u4e0e\u76ee\u6807\u5efa\u7acb\u8fde\u63a5\u3002<br \/>\n\u751f\u6210\u7528\u4e8e\u53d1\u9001\u548c\u63a5\u6536\u7684\u7ebf\u7a0b\uff0c\u5c06\u4ece\u670d\u52a1\u5668\u63a5\u6536\u7684\u6570\u636e\u4f20\u9012\u7ed9zundoko\u65b9\u6cd5\uff0c\u6267\u884c&#8221;\u30ba\u30f3\u30c9\u30b3\u30ad\u30e8\u30b7&#8221;\u8f6c\u6362\uff0c\u5e76\u5c06\u5176\u53d1\u9001\u7ed9\u5ba2\u6237\u7aef\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"nb\">require<\/span> <span class=\"s1\">'socket'<\/span>\r\n<span class=\"nb\">require<\/span> <span class=\"s1\">'memcache'<\/span>\r\n\r\n<span class=\"no\">PROXY_TCP_PORT<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">10_000<\/span>\r\n<span class=\"no\">MEMCACHE<\/span> <span class=\"o\">=<\/span> <span class=\"no\">MemCache<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span> <span class=\"s1\">'192.168.88.4:11211'<\/span>\r\n<span class=\"no\">ZUNDOKO_REGEXP<\/span> <span class=\"o\">=<\/span> <span class=\"sr\">\/((\u30ba\u30f3\\s*){4}\u30c9\u30b3)\/<\/span>\r\n\r\n<span class=\"no\">IPPort<\/span> <span class=\"o\">=<\/span> <span class=\"no\">Struct<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"ss\">:ip<\/span><span class=\"p\">,<\/span> <span class=\"ss\">:port<\/span><span class=\"p\">)<\/span>\r\n<span class=\"no\">Thread<\/span><span class=\"p\">.<\/span><span class=\"nf\">abort_on_exception<\/span> <span class=\"o\">=<\/span> <span class=\"kp\">true<\/span>\r\n\r\n<span class=\"c1\"># ZEchoProxy<\/span>\r\n<span class=\"k\">class<\/span> <span class=\"nc\">ZechoProxyClient<\/span>\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">initialize<\/span><span class=\"p\">(<\/span><span class=\"n\">server_socket<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"vi\">@threads<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[]<\/span>\r\n    <span class=\"vi\">@server_socket<\/span> <span class=\"o\">=<\/span> <span class=\"n\">server_socket<\/span>\r\n    <span class=\"vi\">@client_socket<\/span><span class=\"p\">,<\/span> <span class=\"vi\">@src<\/span><span class=\"p\">,<\/span> <span class=\"vi\">@dst<\/span> <span class=\"o\">=<\/span> <span class=\"n\">lookup_nat_table<\/span><span class=\"p\">(<\/span><span class=\"n\">server_socket<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"k\">end<\/span>\r\n\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">run<\/span>\r\n    <span class=\"nb\">puts<\/span> <span class=\"s2\">\"<\/span><span class=\"si\">#{<\/span><span class=\"nb\">self<\/span><span class=\"si\">}<\/span><span class=\"s2\">: start proxy client\"<\/span>\r\n    <span class=\"k\">return<\/span> <span class=\"k\">unless<\/span> <span class=\"vi\">@client_socket<\/span>\r\n\r\n    <span class=\"vi\">@threads<\/span> <span class=\"o\">&lt;&lt;<\/span> <span class=\"no\">Thread<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span> <span class=\"k\">do<\/span>\r\n      <span class=\"k\">begin<\/span>\r\n        <span class=\"k\">while<\/span> <span class=\"n\">data<\/span> <span class=\"o\">=<\/span> <span class=\"vi\">@server_socket<\/span><span class=\"p\">.<\/span><span class=\"nf\">recv<\/span><span class=\"p\">(<\/span><span class=\"mi\">65535<\/span><span class=\"p\">)<\/span>\r\n          <span class=\"k\">break<\/span> <span class=\"k\">if<\/span> <span class=\"n\">data<\/span><span class=\"p\">.<\/span><span class=\"nf\">size<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span>\r\n          <span class=\"vi\">@client_socket<\/span><span class=\"p\">.<\/span><span class=\"nf\">write<\/span><span class=\"p\">(<\/span><span class=\"n\">data<\/span><span class=\"p\">)<\/span>\r\n          <span class=\"vi\">@client_socket<\/span><span class=\"p\">.<\/span><span class=\"nf\">flush<\/span>\r\n        <span class=\"k\">end<\/span>\r\n      <span class=\"k\">rescue<\/span> <span class=\"no\">IOError<\/span>\r\n      <span class=\"k\">ensure<\/span>\r\n        <span class=\"n\">close<\/span>\r\n      <span class=\"k\">end<\/span>\r\n    <span class=\"k\">end<\/span>\r\n    <span class=\"vi\">@threads<\/span> <span class=\"o\">&lt;&lt;<\/span> <span class=\"no\">Thread<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span> <span class=\"k\">do<\/span>\r\n      <span class=\"k\">begin<\/span>\r\n        <span class=\"k\">while<\/span> <span class=\"n\">data<\/span> <span class=\"o\">=<\/span> <span class=\"vi\">@client_socket<\/span><span class=\"p\">.<\/span><span class=\"nf\">recv<\/span><span class=\"p\">(<\/span><span class=\"mi\">65535<\/span><span class=\"p\">)<\/span>\r\n          <span class=\"k\">break<\/span> <span class=\"k\">if<\/span> <span class=\"n\">data<\/span><span class=\"p\">.<\/span><span class=\"nf\">size<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span>\r\n          <span class=\"n\">data<\/span> <span class=\"o\">=<\/span> <span class=\"n\">zundoko<\/span><span class=\"p\">(<\/span><span class=\"n\">data<\/span><span class=\"p\">)<\/span>\r\n          <span class=\"vi\">@server_socket<\/span><span class=\"p\">.<\/span><span class=\"nf\">write<\/span><span class=\"p\">(<\/span><span class=\"n\">data<\/span><span class=\"p\">)<\/span>\r\n          <span class=\"vi\">@server_socket<\/span><span class=\"p\">.<\/span><span class=\"nf\">flush<\/span>\r\n        <span class=\"k\">end<\/span>\r\n      <span class=\"k\">rescue<\/span> <span class=\"no\">IOError<\/span>\r\n      <span class=\"k\">ensure<\/span>\r\n        <span class=\"n\">close<\/span>\r\n      <span class=\"k\">end<\/span>\r\n    <span class=\"k\">end<\/span>\r\n  <span class=\"k\">end<\/span>\r\n\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">close<\/span>\r\n    <span class=\"vi\">@client_socket<\/span><span class=\"p\">.<\/span><span class=\"nf\">close<\/span> <span class=\"k\">unless<\/span> <span class=\"vi\">@client_socket<\/span><span class=\"p\">.<\/span><span class=\"nf\">closed?<\/span>\r\n    <span class=\"vi\">@server_socket<\/span><span class=\"p\">.<\/span><span class=\"nf\">close<\/span> <span class=\"k\">unless<\/span> <span class=\"vi\">@server_socket<\/span><span class=\"p\">.<\/span><span class=\"nf\">closed?<\/span>\r\n  <span class=\"k\">end<\/span>\r\n\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">join<\/span>\r\n    <span class=\"vi\">@threads<\/span><span class=\"p\">.<\/span><span class=\"nf\">map<\/span> <span class=\"p\">{<\/span> <span class=\"o\">|<\/span><span class=\"n\">t<\/span><span class=\"o\">|<\/span> <span class=\"n\">t<\/span><span class=\"p\">.<\/span><span class=\"nf\">join<\/span> <span class=\"k\">if<\/span> <span class=\"n\">t<\/span> <span class=\"p\">}<\/span>\r\n  <span class=\"k\">end<\/span>\r\n\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">to_s<\/span>\r\n    <span class=\"s2\">\"<\/span><span class=\"si\">#{<\/span><span class=\"vi\">@src<\/span><span class=\"p\">.<\/span><span class=\"nf\">ip<\/span><span class=\"si\">}<\/span><span class=\"s2\">:<\/span><span class=\"si\">#{<\/span><span class=\"vi\">@src<\/span><span class=\"p\">.<\/span><span class=\"nf\">port<\/span><span class=\"si\">}<\/span><span class=\"s2\"> =&gt; <\/span><span class=\"si\">#{<\/span><span class=\"vi\">@dst<\/span><span class=\"p\">.<\/span><span class=\"nf\">ip<\/span><span class=\"si\">}<\/span><span class=\"s2\">:<\/span><span class=\"si\">#{<\/span><span class=\"vi\">@dst<\/span><span class=\"p\">.<\/span><span class=\"nf\">port<\/span><span class=\"si\">}<\/span><span class=\"s2\">\"<\/span>\r\n  <span class=\"k\">end<\/span>\r\n\r\n  <span class=\"kp\">private<\/span>\r\n\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">zundoko<\/span><span class=\"p\">(<\/span><span class=\"n\">data<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"k\">begin<\/span>\r\n      <span class=\"n\">encoded_data<\/span> <span class=\"o\">=<\/span> <span class=\"n\">data<\/span><span class=\"p\">.<\/span><span class=\"nf\">encode<\/span><span class=\"p\">(<\/span><span class=\"s1\">'UTF-8'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'UTF-8'<\/span><span class=\"p\">,<\/span> <span class=\"ss\">invalid: :replace<\/span><span class=\"p\">,<\/span> <span class=\"ss\">undef: :replace<\/span><span class=\"p\">)<\/span>\r\n      <span class=\"k\">if<\/span> <span class=\"no\">ZUNDOKO_REGEXP<\/span> <span class=\"o\">===<\/span> <span class=\"n\">encoded_data<\/span>\r\n        <span class=\"n\">data<\/span> <span class=\"o\">=<\/span> <span class=\"n\">encoded_data<\/span><span class=\"p\">.<\/span><span class=\"nf\">gsub<\/span><span class=\"p\">(<\/span><span class=\"no\">ZUNDOKO_REGEXP<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"s2\">\"<\/span><span class=\"si\">#{<\/span><span class=\"vg\">$1<\/span><span class=\"si\">}<\/span><span class=\"s2\"> \u30ad\u30fb\u30e8\u30fb\u30b7\uff01\"<\/span> <span class=\"p\">}<\/span>\r\n      <span class=\"k\">end<\/span>\r\n    <span class=\"k\">rescue<\/span> <span class=\"no\">ArgumentError<\/span>\r\n    <span class=\"k\">rescue<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"n\">e<\/span>\r\n      <span class=\"nb\">puts<\/span> <span class=\"s2\">\"<\/span><span class=\"si\">#{<\/span><span class=\"n\">e<\/span><span class=\"p\">.<\/span><span class=\"nf\">class<\/span><span class=\"si\">}<\/span> <span class=\"si\">#{<\/span><span class=\"n\">e<\/span><span class=\"si\">}<\/span><span class=\"s2\">\"<\/span>\r\n    <span class=\"k\">end<\/span>\r\n    <span class=\"n\">data<\/span>\r\n  <span class=\"k\">end<\/span>\r\n\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">lookup_nat_table<\/span><span class=\"p\">(<\/span><span class=\"n\">server_socket<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"n\">_inet<\/span><span class=\"p\">,<\/span> <span class=\"n\">src_port<\/span><span class=\"p\">,<\/span> <span class=\"n\">_src_host<\/span><span class=\"p\">,<\/span> <span class=\"n\">src_ip<\/span> <span class=\"o\">=<\/span> <span class=\"n\">server_socket<\/span><span class=\"p\">.<\/span><span class=\"nf\">peeraddr<\/span>\r\n    <span class=\"n\">client_socket<\/span> <span class=\"o\">=<\/span> <span class=\"kp\">nil<\/span>\r\n    <span class=\"n\">src<\/span> <span class=\"o\">=<\/span> <span class=\"no\">IPPort<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"n\">src_ip<\/span><span class=\"p\">,<\/span> <span class=\"n\">src_port<\/span><span class=\"p\">.<\/span><span class=\"nf\">to_s<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"n\">dst<\/span> <span class=\"o\">=<\/span> <span class=\"no\">IPPort<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span>\r\n    <span class=\"n\">ip_port_key<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">\"<\/span><span class=\"si\">#{<\/span><span class=\"n\">src<\/span><span class=\"p\">.<\/span><span class=\"nf\">ip<\/span><span class=\"si\">}<\/span><span class=\"s2\">:<\/span><span class=\"si\">#{<\/span><span class=\"n\">src<\/span><span class=\"p\">.<\/span><span class=\"nf\">port<\/span><span class=\"si\">}<\/span><span class=\"s2\">\"<\/span>\r\n    <span class=\"mi\">10<\/span><span class=\"p\">.<\/span><span class=\"nf\">times<\/span> <span class=\"k\">do<\/span>\r\n      <span class=\"n\">ip_port<\/span> <span class=\"o\">=<\/span> <span class=\"no\">MEMCACHE<\/span><span class=\"p\">.<\/span><span class=\"nf\">get<\/span><span class=\"p\">(<\/span><span class=\"n\">ip_port_key<\/span><span class=\"p\">)<\/span>\r\n      <span class=\"k\">if<\/span> <span class=\"n\">ip_port<\/span>\r\n        <span class=\"no\">MEMCACHE<\/span><span class=\"p\">.<\/span><span class=\"nf\">delete<\/span><span class=\"p\">(<\/span><span class=\"n\">ip_port_key<\/span><span class=\"p\">)<\/span>\r\n        <span class=\"n\">dst<\/span><span class=\"p\">.<\/span><span class=\"nf\">ip<\/span><span class=\"p\">,<\/span> <span class=\"n\">dst<\/span><span class=\"p\">.<\/span><span class=\"nf\">port<\/span> <span class=\"o\">=<\/span> <span class=\"n\">ip_port<\/span><span class=\"p\">.<\/span><span class=\"nf\">split<\/span><span class=\"p\">(<\/span><span class=\"sr\">\/:\/<\/span><span class=\"p\">)<\/span>\r\n        <span class=\"n\">client_socket<\/span> <span class=\"o\">=<\/span> <span class=\"no\">TCPSocket<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"n\">dst<\/span><span class=\"p\">.<\/span><span class=\"nf\">ip<\/span><span class=\"p\">,<\/span> <span class=\"n\">dst<\/span><span class=\"p\">.<\/span><span class=\"nf\">port<\/span><span class=\"p\">)<\/span>\r\n        <span class=\"k\">break<\/span>\r\n      <span class=\"k\">end<\/span>\r\n      <span class=\"nb\">sleep<\/span> <span class=\"mf\">0.5<\/span>\r\n    <span class=\"k\">end<\/span>\r\n    <span class=\"p\">[<\/span><span class=\"n\">client_socket<\/span><span class=\"p\">,<\/span> <span class=\"n\">src<\/span><span class=\"p\">,<\/span> <span class=\"n\">dst<\/span><span class=\"p\">]<\/span>\r\n  <span class=\"k\">end<\/span>\r\n<span class=\"k\">end<\/span>\r\n\r\n<span class=\"c1\"># ZEchoProxyServer<\/span>\r\n<span class=\"k\">class<\/span> <span class=\"nc\">ZechoProxyServer<\/span>\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">initialize<\/span><span class=\"p\">(<\/span><span class=\"n\">port<\/span> <span class=\"o\">=<\/span> <span class=\"no\">PROXY_TCP_PORT<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"vi\">@threads<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[]<\/span>\r\n    <span class=\"vi\">@port<\/span> <span class=\"o\">=<\/span> <span class=\"n\">port<\/span>\r\n  <span class=\"k\">end<\/span>\r\n\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">run<\/span>\r\n    <span class=\"nb\">puts<\/span> <span class=\"s2\">\"proxy server start: port:<\/span><span class=\"si\">#{<\/span><span class=\"vi\">@port<\/span><span class=\"si\">}<\/span><span class=\"s2\">\"<\/span>\r\n    <span class=\"vi\">@threads<\/span> <span class=\"o\">&lt;&lt;<\/span> <span class=\"no\">Thread<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span> <span class=\"k\">do<\/span>\r\n      <span class=\"n\">tcp_server<\/span> <span class=\"o\">=<\/span> <span class=\"no\">TCPServer<\/span><span class=\"p\">.<\/span><span class=\"nf\">open<\/span><span class=\"p\">(<\/span><span class=\"vi\">@port<\/span><span class=\"p\">)<\/span>\r\n      <span class=\"kp\">loop<\/span> <span class=\"k\">do<\/span>\r\n        <span class=\"n\">socket<\/span> <span class=\"o\">=<\/span> <span class=\"n\">tcp_server<\/span><span class=\"p\">.<\/span><span class=\"nf\">accept<\/span>\r\n        <span class=\"n\">client<\/span> <span class=\"o\">=<\/span> <span class=\"no\">ZechoProxyClient<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"n\">socket<\/span><span class=\"p\">)<\/span>\r\n        <span class=\"n\">client<\/span><span class=\"p\">.<\/span><span class=\"nf\">run<\/span>\r\n      <span class=\"k\">end<\/span>\r\n    <span class=\"k\">end<\/span>\r\n  <span class=\"k\">end<\/span>\r\n\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">join<\/span>\r\n    <span class=\"vi\">@threads<\/span><span class=\"p\">.<\/span><span class=\"nf\">map<\/span> <span class=\"p\">{<\/span> <span class=\"o\">|<\/span><span class=\"n\">t<\/span><span class=\"o\">|<\/span> <span class=\"n\">t<\/span><span class=\"p\">.<\/span><span class=\"nf\">join<\/span> <span class=\"k\">if<\/span> <span class=\"n\">t<\/span> <span class=\"p\">}<\/span>\r\n  <span class=\"k\">end<\/span>\r\n<span class=\"k\">end<\/span>\r\n\r\n<span class=\"k\">if<\/span> <span class=\"kp\">__FILE__<\/span> <span class=\"o\">==<\/span> <span class=\"vg\">$0<\/span>\r\n  <span class=\"n\">server<\/span> <span class=\"o\">=<\/span> <span class=\"no\">ZechoProxyServer<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span>\r\n  <span class=\"n\">server<\/span><span class=\"p\">.<\/span><span class=\"nf\">run<\/span>\r\n  <span class=\"n\">server<\/span><span class=\"p\">.<\/span><span class=\"nf\">join<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<h2>\u6267\u884c\u7ed3\u679c<\/h2>\n<p>\u5728ECHO\u5ba2\u6237\u7aef\u7684\u63a7\u5236\u53f0\u754c\u9762\u4e0a\uff0cECHO\u5ba2\u6237\u7aef\u4f1a\u968f\u673a\u53d1\u9001&#8221;\u30ba\u30f3\u30c9\u30b3&#8221;\u7ed9ECHO\u670d\u52a1\u5668\uff0c\u5982\u679c\u6761\u4ef6\u5339\u914d\uff0c\u4f1a\u989d\u5916\u663e\u793a&#8221;\u30ad\u30fb\u30e8\u30fb\u30b7\uff01&#8221;\u3002<\/p>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d1d5f37434c4406c13157\/43-0.png\" alt=\"\u5b9f\u884c\u7d50\u679cCLI.png\" \/><\/div>\n<h1>\u9644\u5f55<\/h1>\n<p>\u4eca\u56de\u306f\u6c4e\u7528\u7684\u306aTCP\u30d7\u30ed\u30ad\u30b7\u3092\u5b9f\u88c5\u3057\u305f\u305f\u3081\u3001\u901a\u5e38\u306eWeb\u30d6\u30e9\u30a6\u30b6\u304b\u3089\u306e\u901a\u4fe1\u3082\u30ba\u30f3\u30c9\u30b3\u30ad\u30e8\u30b7\u5909\u63db\u3067\u304d\u307e\u3059\u3002<br \/>\nu01\u30db\u30b9\u30c8\u3067Web\u30d6\u30e9\u30a6\u30b6\u3092\u8d77\u52d5\u3057\u3001u02\u30db\u30b9\u30c8\u3067\u4e0b\u8a18\u306eWeb\u30b5\u30fc\u30d0\u306b\u30a2\u30af\u30bb\u30b9\u3057\u305f\u5b9f\u884c\u7d50\u679c\u306f\u4e0b\u8a18\u306e\u3068\u304a\u308a\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"nb\">require<\/span> <span class=\"s1\">'sinatra'<\/span>\r\n<span class=\"n\">set<\/span> <span class=\"ss\">bind: <\/span><span class=\"s1\">'0.0.0.0'<\/span>\r\n<span class=\"n\">get<\/span> <span class=\"s1\">'\/'<\/span> <span class=\"k\">do<\/span>\r\n  <span class=\"n\">erb<\/span> <span class=\"ss\">:index<\/span>\r\n<span class=\"k\">end<\/span>\r\n\r\n<span class=\"cp\">__END__\r\n@@ index\r\n&lt;% words = %w(\u30ba\u30f3 \u30c9\u30b3) %&gt;\r\n&lt;html&gt;&lt;head&gt;&lt;\/head&gt;&lt;body&gt;&lt;ul&gt;\r\n&lt;% 100.times do %&gt;\r\n&lt;li&gt;&lt;%= Array.new(5) { words.sample }.join %&gt;&lt;\/li&gt;\r\n&lt;% end %&gt;\r\n&lt;\/ul&gt;&lt;\/body&gt;&lt;\/html&gt;\r\n<\/span><\/code><\/pre>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d1d5f37434c4406c13157\/47-0.png\" alt=\"\u5b9f\u884c\u7d50\u679cWEB.png\" \/><\/div>\n<p>\u5b9f\u969b\u306e\u30a4\u30f3\u30bf\u30fc\u30cd\u30c3\u30c8\u4e0a\u3067\u3082\u8a66\u3057\u3066\u307f\u307e\u3057\u305f\u304c\u3001\u30e1\u30b8\u30e3\u30fc\u306a\u30b5\u30a4\u30c8\u306fHTTPS\u306e\u305f\u3081\u3001\u6b8b\u5ff5\u306a\u304c\u3089\u30ba\u30f3\u30c9\u30b3\u30ad\u30e8\u30b7\u5909\u63db\u3092\u304b\u3051\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u3053\u306e\u305f\u3081\u3001\u30ed\u30fc\u30ab\u30eb\u3067\u7c21\u6613\u306aWeb\u30b5\u30fc\u30d0\u3092\u7acb\u3061\u4e0a\u3052\u3066\u5b9f\u884c\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n<h1>\u8bf7\u4f60\u63d0\u4f9b\u4e00\u79cd\u4e2d\u6587\u7684\u540c\u4e49\u6539\u5199\u3002<\/h1>\n<p>\uff3b\u5897\u88dc\u6539\u8a02\u7248\uff3d\u30af\u30e9\u30a6\u30c9\u6642\u4ee3\u306e\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u6280\u8853 OpenFlow\u5b9f\u8df5\u5165\u9580<\/p>\n<p>@qb0c80aE\u3055\u3093\u63d0\u4f9b\u3042\u308a\u304c\u3068\u3046\u3054\u3056\u3044\u307e\u3057\u305f\uff01<\/p>\n<p>Trema\u3067OpenFlow\u30d7\u30ed\u30b0\u30e9\u30df\u30f3\u30b0<br \/>\n\u30ba\u30f3\u30c9\u30b3\u30ad\u30e8\u30b7\u307e\u3068\u3081<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u53d7\u5230ZUNDOKO\u534f\u8bae\u7684\u542f\u53d1\uff0c\u6211\u51b3\u5b9a\u4e58\u4e0a\u8fd9\u80a1\u5927\u6d6a\uff0c\u4f7f\u7528OpenFlow\u521b\u5efa\u4e86ZUNDOKO\u7ee7\u627f\u4ee3\u7406\u3002 \u6700\u8fd1\u5728\u4e2d [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-34465","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v21.5 (Yoast SEO v21.5) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>\u7528OpenFlow\u3001Ruby\u3001Trema\u548cOpen vSwitch\u5b9e\u73b0\u4e86\u30ba\u30f3\u30c9\u30b3\u30ad\u30e8\u30b7\u53d8\u6362\u4ee3\u7406 - Blog - Silicon Cloud<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.silicloud.com\/zh\/blog\/\u7528openflow\u3001ruby\u3001trema\u548copen-vswitch\u5b9e\u73b0\u4e86\u30ba\u30f3\u30c9\u30b3\u30ad\u30e8\u30b7\u53d8\u6362\u4ee3\u7406\u3002\/\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"\u7528OpenFlow\u3001Ruby\u3001Trema\u548cOpen vSwitch\u5b9e\u73b0\u4e86\u30ba\u30f3\u30c9\u30b3\u30ad\u30e8\u30b7\u53d8\u6362\u4ee3\u7406\" \/>\n<meta property=\"og:description\" content=\"\u53d7\u5230ZUNDOKO\u534f\u8bae\u7684\u542f\u53d1\uff0c\u6211\u51b3\u5b9a\u4e58\u4e0a\u8fd9\u80a1\u5927\u6d6a\uff0c\u4f7f\u7528OpenFlow\u521b\u5efa\u4e86ZUNDOKO\u7ee7\u627f\u4ee3\u7406\u3002 \u6700\u8fd1\u5728\u4e2d [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.silicloud.com\/zh\/blog\/\u7528openflow\u3001ruby\u3001trema\u548copen-vswitch\u5b9e\u73b0\u4e86\u30ba\u30f3\u30c9\u30b3\u30ad\u30e8\u30b7\u53d8\u6362\u4ee3\u7406\u3002\/\" \/>\n<meta property=\"og:site_name\" content=\"Blog - Silicon Cloud\" \/>\n<meta property=\"article:published_time\" content=\"2023-12-23T19:49:46+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-05-03T15:24:23+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d1d5f37434c4406c13157\/8-0.png\" \/>\n<meta name=\"author\" content=\"\u79d1, \u9896\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"\u79d1, \u9896\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e7%94%a8openflow%e3%80%81ruby%e3%80%81trema%e5%92%8copen-vswitch%e5%ae%9e%e7%8e%b0%e4%ba%86%e3%82%ba%e3%83%b3%e3%83%89%e3%82%b3%e3%82%ad%e3%83%a8%e3%82%b7%e5%8f%98%e6%8d%a2%e4%bb%a3%e7%90%86%e3%80%82\/\",\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e7%94%a8openflow%e3%80%81ruby%e3%80%81trema%e5%92%8copen-vswitch%e5%ae%9e%e7%8e%b0%e4%ba%86%e3%82%ba%e3%83%b3%e3%83%89%e3%82%b3%e3%82%ad%e3%83%a8%e3%82%b7%e5%8f%98%e6%8d%a2%e4%bb%a3%e7%90%86%e3%80%82\/\",\"name\":\"\u7528OpenFlow\u3001Ruby\u3001Trema\u548cOpen vSwitch\u5b9e\u73b0\u4e86\u30ba\u30f3\u30c9\u30b3\u30ad\u30e8\u30b7\u53d8\u6362\u4ee3\u7406 - Blog - Silicon Cloud\",\"isPartOf\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#website\"},\"datePublished\":\"2023-12-23T19:49:46+00:00\",\"dateModified\":\"2024-05-03T15:24:23+00:00\",\"author\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/8ca01ba7f7362ad4edb7da206a12f29e\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e7%94%a8openflow%e3%80%81ruby%e3%80%81trema%e5%92%8copen-vswitch%e5%ae%9e%e7%8e%b0%e4%ba%86%e3%82%ba%e3%83%b3%e3%83%89%e3%82%b3%e3%82%ad%e3%83%a8%e3%82%b7%e5%8f%98%e6%8d%a2%e4%bb%a3%e7%90%86%e3%80%82\/#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.silicloud.com\/zh\/blog\/%e7%94%a8openflow%e3%80%81ruby%e3%80%81trema%e5%92%8copen-vswitch%e5%ae%9e%e7%8e%b0%e4%ba%86%e3%82%ba%e3%83%b3%e3%83%89%e3%82%b3%e3%82%ad%e3%83%a8%e3%82%b7%e5%8f%98%e6%8d%a2%e4%bb%a3%e7%90%86%e3%80%82\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e7%94%a8openflow%e3%80%81ruby%e3%80%81trema%e5%92%8copen-vswitch%e5%ae%9e%e7%8e%b0%e4%ba%86%e3%82%ba%e3%83%b3%e3%83%89%e3%82%b3%e3%82%ad%e3%83%a8%e3%82%b7%e5%8f%98%e6%8d%a2%e4%bb%a3%e7%90%86%e3%80%82\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.silicloud.com\/zh\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"\u7528OpenFlow\u3001Ruby\u3001Trema\u548cOpen vSwitch\u5b9e\u73b0\u4e86\u30ba\u30f3\u30c9\u30b3\u30ad\u30e8\u30b7\u53d8\u6362\u4ee3\u7406\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#website\",\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/\",\"name\":\"Blog - Silicon Cloud\",\"description\":\"\",\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/8ca01ba7f7362ad4edb7da206a12f29e\",\"name\":\"\u79d1, \u9896\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/8a6fb3cc7ba2f69d2189ba532aec4633ea7ed75ac0af162ec367cb3abc0fb2af?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/8a6fb3cc7ba2f69d2189ba532aec4633ea7ed75ac0af162ec367cb3abc0fb2af?s=96&d=mm&r=g\",\"caption\":\"\u79d1, \u9896\"},\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/author\/keying\/\"},{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e7%94%a8openflow%e3%80%81ruby%e3%80%81trema%e5%92%8copen-vswitch%e5%ae%9e%e7%8e%b0%e4%ba%86%e3%82%ba%e3%83%b3%e3%83%89%e3%82%b3%e3%82%ad%e3%83%a8%e3%82%b7%e5%8f%98%e6%8d%a2%e4%bb%a3%e7%90%86%e3%80%82\/#local-main-organization-logo\",\"url\":\"\",\"contentUrl\":\"\",\"caption\":\"Blog - Silicon Cloud\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"\u7528OpenFlow\u3001Ruby\u3001Trema\u548cOpen vSwitch\u5b9e\u73b0\u4e86\u30ba\u30f3\u30c9\u30b3\u30ad\u30e8\u30b7\u53d8\u6362\u4ee3\u7406 - Blog - Silicon Cloud","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.silicloud.com\/zh\/blog\/\u7528openflow\u3001ruby\u3001trema\u548copen-vswitch\u5b9e\u73b0\u4e86\u30ba\u30f3\u30c9\u30b3\u30ad\u30e8\u30b7\u53d8\u6362\u4ee3\u7406\u3002\/","og_locale":"zh_CN","og_type":"article","og_title":"\u7528OpenFlow\u3001Ruby\u3001Trema\u548cOpen vSwitch\u5b9e\u73b0\u4e86\u30ba\u30f3\u30c9\u30b3\u30ad\u30e8\u30b7\u53d8\u6362\u4ee3\u7406","og_description":"\u53d7\u5230ZUNDOKO\u534f\u8bae\u7684\u542f\u53d1\uff0c\u6211\u51b3\u5b9a\u4e58\u4e0a\u8fd9\u80a1\u5927\u6d6a\uff0c\u4f7f\u7528OpenFlow\u521b\u5efa\u4e86ZUNDOKO\u7ee7\u627f\u4ee3\u7406\u3002 \u6700\u8fd1\u5728\u4e2d [&hellip;]","og_url":"https:\/\/www.silicloud.com\/zh\/blog\/\u7528openflow\u3001ruby\u3001trema\u548copen-vswitch\u5b9e\u73b0\u4e86\u30ba\u30f3\u30c9\u30b3\u30ad\u30e8\u30b7\u53d8\u6362\u4ee3\u7406\u3002\/","og_site_name":"Blog - Silicon Cloud","article_published_time":"2023-12-23T19:49:46+00:00","article_modified_time":"2024-05-03T15:24:23+00:00","og_image":[{"url":"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d1d5f37434c4406c13157\/8-0.png"}],"author":"\u79d1, \u9896","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"\u79d1, \u9896","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"6 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e7%94%a8openflow%e3%80%81ruby%e3%80%81trema%e5%92%8copen-vswitch%e5%ae%9e%e7%8e%b0%e4%ba%86%e3%82%ba%e3%83%b3%e3%83%89%e3%82%b3%e3%82%ad%e3%83%a8%e3%82%b7%e5%8f%98%e6%8d%a2%e4%bb%a3%e7%90%86%e3%80%82\/","url":"https:\/\/www.silicloud.com\/zh\/blog\/%e7%94%a8openflow%e3%80%81ruby%e3%80%81trema%e5%92%8copen-vswitch%e5%ae%9e%e7%8e%b0%e4%ba%86%e3%82%ba%e3%83%b3%e3%83%89%e3%82%b3%e3%82%ad%e3%83%a8%e3%82%b7%e5%8f%98%e6%8d%a2%e4%bb%a3%e7%90%86%e3%80%82\/","name":"\u7528OpenFlow\u3001Ruby\u3001Trema\u548cOpen vSwitch\u5b9e\u73b0\u4e86\u30ba\u30f3\u30c9\u30b3\u30ad\u30e8\u30b7\u53d8\u6362\u4ee3\u7406 - Blog - Silicon Cloud","isPartOf":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/#website"},"datePublished":"2023-12-23T19:49:46+00:00","dateModified":"2024-05-03T15:24:23+00:00","author":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/8ca01ba7f7362ad4edb7da206a12f29e"},"breadcrumb":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e7%94%a8openflow%e3%80%81ruby%e3%80%81trema%e5%92%8copen-vswitch%e5%ae%9e%e7%8e%b0%e4%ba%86%e3%82%ba%e3%83%b3%e3%83%89%e3%82%b3%e3%82%ad%e3%83%a8%e3%82%b7%e5%8f%98%e6%8d%a2%e4%bb%a3%e7%90%86%e3%80%82\/#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.silicloud.com\/zh\/blog\/%e7%94%a8openflow%e3%80%81ruby%e3%80%81trema%e5%92%8copen-vswitch%e5%ae%9e%e7%8e%b0%e4%ba%86%e3%82%ba%e3%83%b3%e3%83%89%e3%82%b3%e3%82%ad%e3%83%a8%e3%82%b7%e5%8f%98%e6%8d%a2%e4%bb%a3%e7%90%86%e3%80%82\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e7%94%a8openflow%e3%80%81ruby%e3%80%81trema%e5%92%8copen-vswitch%e5%ae%9e%e7%8e%b0%e4%ba%86%e3%82%ba%e3%83%b3%e3%83%89%e3%82%b3%e3%82%ad%e3%83%a8%e3%82%b7%e5%8f%98%e6%8d%a2%e4%bb%a3%e7%90%86%e3%80%82\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.silicloud.com\/zh\/blog\/"},{"@type":"ListItem","position":2,"name":"\u7528OpenFlow\u3001Ruby\u3001Trema\u548cOpen vSwitch\u5b9e\u73b0\u4e86\u30ba\u30f3\u30c9\u30b3\u30ad\u30e8\u30b7\u53d8\u6362\u4ee3\u7406"}]},{"@type":"WebSite","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#website","url":"https:\/\/www.silicloud.com\/zh\/blog\/","name":"Blog - Silicon Cloud","description":"","inLanguage":"zh-Hans"},{"@type":"Person","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/8ca01ba7f7362ad4edb7da206a12f29e","name":"\u79d1, \u9896","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/8a6fb3cc7ba2f69d2189ba532aec4633ea7ed75ac0af162ec367cb3abc0fb2af?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/8a6fb3cc7ba2f69d2189ba532aec4633ea7ed75ac0af162ec367cb3abc0fb2af?s=96&d=mm&r=g","caption":"\u79d1, \u9896"},"url":"https:\/\/www.silicloud.com\/zh\/blog\/author\/keying\/"},{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e7%94%a8openflow%e3%80%81ruby%e3%80%81trema%e5%92%8copen-vswitch%e5%ae%9e%e7%8e%b0%e4%ba%86%e3%82%ba%e3%83%b3%e3%83%89%e3%82%b3%e3%82%ad%e3%83%a8%e3%82%b7%e5%8f%98%e6%8d%a2%e4%bb%a3%e7%90%86%e3%80%82\/#local-main-organization-logo","url":"","contentUrl":"","caption":"Blog - Silicon Cloud"}]}},"_links":{"self":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/34465","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/comments?post=34465"}],"version-history":[{"count":2,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/34465\/revisions"}],"predecessor-version":[{"id":94730,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/34465\/revisions\/94730"}],"wp:attachment":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/media?parent=34465"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/categories?post=34465"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/tags?post=34465"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}