├── LICENSE ├── README.md ├── imgs ├── new_62_62.png └── official_accounts.jpg └── tests └── network ├── index.md ├── test01 ├── client.php ├── clientd.php └── server.php ├── test02 ├── c │ ├── Makefile │ ├── client.c │ ├── server.c │ └── tool.sh ├── java │ ├── Client.java │ ├── Makefile │ ├── Server.java │ └── tool.sh └── php │ ├── Makefile │ ├── client.php │ ├── server.php │ └── tool.sh ├── test03 ├── c │ ├── Makefile │ ├── client.c │ ├── server.c │ └── tool.sh ├── java │ ├── Client.java │ ├── Makefile │ ├── Server.java │ └── tool.sh └── php │ ├── Makefile │ ├── client.php │ ├── server.php │ └── tool.sh └── test04 └── main.c /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | **公众号: 开发内功修炼** 3 | 4 | 我们所有的开发同学每时每刻都在使用内核、都在使用硬件。所以能正确理解内核是怎么工作的、硬件的性能指标大概是多少,这些对于高阶的开发工程师来说非常重要。想成为技术大牛,扎实练习内功是必经之路! 5 | 6 | 飞哥的开发内功修炼从CPU、内存、磁盘、网络四大模块进行深度思考,总结出来,在这里分享给积极上进的你! 7 | 8 | 持续更新ing... 9 | 10 | ## 一、网络篇 11 | **1.1 内核收发包原理** 12 | - [🔥图解Linux网络包接收过程](https://mp.weixin.qq.com/s/GoYDsfy9m0wRoXi_NCfCmg) 13 | - [🔥25 张图,一万字,拆解 Linux 网络包发送过程](https://mp.weixin.qq.com/s/wThfD9th9e_-YGHJJ3HXNQ) 14 | - [🔥127.0.0.1 之本机网络通信过程知多少 ?!](https://mp.weixin.qq.com/s/6_OfoeD3ZpyQisY2F-4_bw) 15 | - [Linux网络包接收过程的监控与调优](https://mp.weixin.qq.com/s/6iQ-OhEbQJbEcgi9kakSjg) 16 | 17 | **1.2 内核如何与用户进程协作** 18 | - [图解 | 深入理解高性能网络开发路上的绊脚石 - 同步阻塞网络 IO](https://mp.weixin.qq.com/s/cIcw0S-Q8pBl1-WYN0UwnA) 19 | - [🔥图解 | 深入揭秘 epoll 是如何实现 IO 多路复用的!](https://mp.weixin.qq.com/s/OmRdUgO1guMX76EdZn11UQ) 20 | - [漫画 | 看进程小 P 讲述它的网络性能故事!](https://mp.weixin.qq.com/s/r7EDYsvVhWA2fv52mwM_zg) 21 | 22 | **1.3 TCP之三次握手** 23 | - [为什么服务端程序都需要先 listen 一下?](https://mp.weixin.qq.com/s/hv2tmtVpxhVxr6X-RNWBsQ) (:cn:新) 24 | - [TCP连接中客户端的端口号是如何确定的?](https://mp.weixin.qq.com/s/C-Eeoeh9GHxugF4J30fz1A) (:cn:新) 25 | - [能将三次握手理解到这个深度,面试官拍案叫绝!](https://mp.weixin.qq.com/s/vlrzGc5bFrPIr9a7HIr2eA) (:cn:新) 26 | - [深入解析常见三次握手异常](https://mp.weixin.qq.com/s/7Cum6Y28H_gXLyrRFrthNw) (:cn:新) 27 | - [如何正确查看线上半/全连接队列溢出情况?](https://mp.weixin.qq.com/s/f-TFX2t8CWRCGoyCByGkOw) (:cn:新) 28 | 29 | **1.4 TCP连接时间开销、内存开销** 30 | - [聊聊TCP连接耗时的那些事儿](https://mp.weixin.qq.com/s/wXyerOFoibRsaBmbl224gw) 31 | - [刨根问底儿,看我如何处理 Too many open files 错误!](https://mp.weixin.qq.com/s/GBn94vdL4xUL80WYrGdUWQ)、 32 | - [漫画 | 花了七天时间测试,我彻底搞明白了 TCP 的这些内存开销!](https://mp.weixin.qq.com/s/BwddYkVLSYlkKFNeA-NUVg) 33 | 34 | **1.5 单机百万并发系列** 35 | - [🔥漫画 | 一台Linux服务器最多能支撑多少个TCP连接](https://mp.weixin.qq.com/s/Lkyj42NtvqEj63DoCY5btQ) 36 | - [🔥漫画 | 理解了TCP连接的实现以后,客户端的并发也爆发了!](https://mp.weixin.qq.com/s/ta6upubg0o1w03YGUo8Trg) 37 | - [百看不如一练,动手测试单机百万连接的保姆级教程!](https://mp.weixin.qq.com/s/f_CMt2ni0vegB3-pf2BTTg) 38 | 39 | **1.6 网络工具** 40 | - [用户态 tcpdump 如何实现抓到内核网络包的?](https://mp.weixin.qq.com/s/ZX8Jluh-RgJXcVh3OvycRQ) (:cn:新) 41 | 42 | **1.7 电子书** 43 | - [🔥开发内功修炼网络篇电子书出炉!!!](https://mp.weixin.qq.com/s/kE8y9em9a0Xv80YaQqPbRg) 44 | 45 | ## 二、硬盘篇 46 | **2.1 硬件工作原理** 47 | - [磁盘开篇:扒开机械硬盘坚硬的外衣!](https://mp.weixin.qq.com/s/OqhwSI4WsEyZlBhkFGPUlg) 48 | - [磁盘分区也是隐含了技术技巧的](https://mp.weixin.qq.com/s/4HwUxy-4FClgIIei6JAzqw) 49 | - [我们怎么解决机械硬盘既慢又容易坏的问题?](https://mp.weixin.qq.com/s/n9Hf3Utm4NFp3jNRTgZNwg) 50 | - [拆解固态硬盘结构](https://mp.weixin.qq.com/s/6aPHMmz1kmiaBABhy8pF1Q) 51 | 52 | **2.2 文件系统浅析** 53 | - [新建一个空文件占用多少磁盘空间?](https://mp.weixin.qq.com/s/9YeUEnRnegplftpKlW4ZCA) 54 | - [只有1个字节的文件实际占用多少磁盘空间](https://mp.weixin.qq.com/s/WE6BodR_q0GSKks_TgYL1w) 55 | - [文件过多时ls命令为什么会卡住?](https://mp.weixin.qq.com/s/g-fFoYsBJkonV3ezdGDJKA) 56 | - [理解格式化原理](https://mp.weixin.qq.com/s/DobymgQ-TRXrO32wjf2fWQ) 57 | 58 | **2.3 文件读写性能** 59 | - [read文件一个字节实际会发生多大的磁盘IO?](https://mp.weixin.qq.com/s/vekemOfUHBjZSy3uXb49Rw) (:cn:新) 60 | - [write文件一个字节后何时发起写磁盘IO?](https://zhuanlan.zhihu.com/p/142441899) 61 | - [机械硬盘随机IO慢的超乎你的想象](https://mp.weixin.qq.com/s/qz57uPtFaoQ_5z59NSBEUQ) 62 | - [搭载固态硬盘的服务器究竟比搭机械硬盘快多少?](https://mp.weixin.qq.com/s/4CKPLpEDDbIyqJGxYDAUeA) 63 | 64 | 65 | ## 三、内存篇 66 | **3.1 硬件工作原理** 67 | - [带你深入理解内存对齐最底层原理](https://mp.weixin.qq.com/s/F0NTfz-3x3UxQeF-GSavRg) 68 | - [内存随机也比顺序访问慢,带你深入理解内存IO过程](https://mp.weixin.qq.com/s/ps8VfGpbL4-xKggM2ywjHw) 69 | - [从DDR到DDR4,内存核心频率其实基本上就没太大的进步](https://mp.weixin.qq.com/s/LRxhKrUOgyCexYN1lOwTyA) 70 | 71 | **3.2 内核内存管理** 72 | - [说出来你可能不信,内核这家伙在内存的使用上给自己开了个小灶!](https://mp.weixin.qq.com/s/OR2XB4J76haGc1THeq7WQg) (:cn:新) 73 | 74 | **3.3 内存性能测试** 75 | - [实际测试内存在顺序IO和随机IO时的访问延时差异](https://mp.weixin.qq.com/s/_-Ar944KlztzmFYdA3JXnQ) 76 | - [揭穿内存厂家“谎言”,实测内存带宽真实表现](https://mp.weixin.qq.com/s/AJjBHCNPWN8YW8v0iXjjig) 77 | - [NUMA架构下的内存访问延迟区别!](https://mp.weixin.qq.com/s/xUZl5wGRVvJI_Hfivg0hVQ) 78 | - [挑战Redis单实例内存最大极限,“遭遇”NUMA陷阱!](https://mp.weixin.qq.com/s/dag1Zp1h4lQfqeUUGz4Ogw) 79 | 80 | **3.4 内存性能优化实例** 81 | - [一次内存性能提升的项目实践](https://mp.weixin.qq.com/s/foJJ2E7_jVgnOeJ9Du6qJg) 82 | - [PHP7内存性能优化的思想精髓](https://mp.weixin.qq.com/s/3DrDb0CY8dUmFUKtuWzhqA) 83 | 84 | 85 | ## 四、CPU篇 86 | **4.1 了解CPU硬件** 87 | - [你以为你的多核CPU都是真核吗?多核“假象”](https://mp.weixin.qq.com/s/XX1yh8BTgT256pAnfosQkw) 88 | - [听说你只知内存,而不知缓存?CPU表示很伤心!](https://mp.weixin.qq.com/s/PQTuFZO51an6OAe3WX4BVw) 89 | - [TLB缓存是个神马鬼,如何查看TLB miss?](https://mp.weixin.qq.com/s/mssTS3NN7-w2df1vhYSuYw) 90 | 91 | **4.2 内核CPU开销浅析** 92 | - [进程/线程切换究竟需要多少开销?](https://mp.weixin.qq.com/s/uq5s5vwk5vtPOZ30sfNsOg) 93 | - [软中断会吃掉你多少CPU?](https://mp.weixin.qq.com/s/mlenlX3-6H0shfOIvi8E8g) 94 | - [一次系统调用开销到底有多大?](https://mp.weixin.qq.com/s/2nIDLeMR984_Sdgh01BHIQ) 95 | - [一次简单的php请求redis会有哪些开销?](https://mp.weixin.qq.com/s/yl5EuQ1wEXDuIg4E98QfZA) 96 | 97 | **4.3 用户态CPU开销分析** 98 | - [协程究竟比线程牛在什么地方?](https://mp.weixin.qq.com/s/N4W0-0cP1wlxtLILx3oXpg) 99 | - [函数调用太多了会有性能问题吗?](https://mp.weixin.qq.com/s/G30VtOIYjx2Wa54xlO7udw) 100 | 101 | ## 五、应用篇 102 | - [峰值 QPS 50 万 +,性能优异的网络框架开源力作 Sogou Workflow!](https://mp.weixin.qq.com/s/clILKrOO7_XJs6uHp5hoUw) (:cn:新) 103 | 104 | ## 六、公众号二维码 105 | **微信扫一扫关注!** 106 | ![avatar](imgs/official_accounts.jpg) 107 | -------------------------------------------------------------------------------- /imgs/new_62_62.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NFhook/coder-kung-fu/b3a5c5750330d673ed2570a48e9674c98f630b48/imgs/new_62_62.png -------------------------------------------------------------------------------- /imgs/official_accounts.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NFhook/coder-kung-fu/b3a5c5750330d673ed2570a48e9674c98f630b48/imgs/official_accounts.jpg -------------------------------------------------------------------------------- /tests/network/index.md: -------------------------------------------------------------------------------- 1 | 2 | - [通过多 IP 达成单机百万连接](tests/network/test02) 3 | - [通过端口重用达成单机百万连接](tests/network/test03) 4 | - [一个模拟 tcpdump 的简单抓包程序](tests/network/test04) -------------------------------------------------------------------------------- /tests/network/test01/client.php: -------------------------------------------------------------------------------- 1 | $ip){ 47 | echo $ip.":".pingAddress($ip)."\n"; 48 | } 49 | break; 50 | 51 | case "ifup": 52 | foreach($ips as $k=>$ip){ 53 | shell_exec("ifconfig eth0:$k $ip netmask ".$netmask." up"); 54 | } 55 | break; 56 | 57 | case "ifdown": 58 | foreach($ips as $k=>$ip){ 59 | shell_exec("ifconfig eth0:$k down"); 60 | } 61 | break; 62 | 63 | case "start": 64 | $cmd = "ps -ef | grep client.php | awk '{print $2}' | xargs kill -9"; 65 | shell_exec($cmd); 66 | shell_exec("echo '' > clientd.log"); 67 | 68 | foreach($ips as $ip){ 69 | $cmd = "php client.php $ip $serverIp $serverPort >> clientd.log &"; 70 | echo $cmd."\n"; 71 | shell_exec($cmd); 72 | } 73 | break; 74 | 75 | case "stop": 76 | $cmd = "ps -ef | grep client.php | awk '{print $2}' | xargs kill -9"; 77 | shell_exec($cmd); 78 | break; 79 | 80 | default: 81 | break; 82 | } 83 | 84 | -------------------------------------------------------------------------------- /tests/network/test01/server.php: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define MAX_CONNECTION_NUM 50000 9 | 10 | int buildConnect(const char *lIp, const char *sIp, int sPort) 11 | { 12 | int skFd; 13 | if((skFd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 14 | { 15 | printf("\n Error : Could not create socket\n"); 16 | return 0; 17 | } 18 | 19 | struct sockaddr_in cliAddr; 20 | cliAddr.sin_family = AF_INET; 21 | cliAddr.sin_addr.s_addr = inet_addr(lIp); 22 | cliAddr.sin_port = 0; 23 | if(bind(skFd, (struct sockaddr *)&cliAddr, sizeof(cliAddr)) < 0) 24 | { 25 | printf("\n Error : Bind Failed \n"); 26 | } 27 | 28 | struct sockaddr_in srvAddr; 29 | srvAddr.sin_family = AF_INET; 30 | srvAddr.sin_addr.s_addr = inet_addr(sIp); 31 | srvAddr.sin_port = htons(sPort); 32 | if(connect(skFd, (struct sockaddr *)&srvAddr, sizeof(srvAddr)) < 0) 33 | { 34 | printf("\n Error : Connect Failed \n"); 35 | return 0; 36 | } 37 | 38 | return skFd; 39 | } 40 | 41 | int main(int argc, char *argv[]) 42 | { 43 | int i = 0, sPort, fd; 44 | char lIp[16], sIp[16]; 45 | 46 | if(argc != 4) 47 | { 48 | printf("\n Usage: %s \n", argv[0]); 49 | return 1; 50 | } 51 | 52 | //1. 从命令行获取并解析local ip、server ip以及端口 53 | strcpy(lIp, argv[1]); 54 | strcpy(sIp, argv[2]); 55 | sPort = atoi(argv[3]); 56 | 57 | //2. 开始建立连接 58 | int *sockets = (int *)malloc(sizeof(int) * MAX_CONNECTION_NUM); 59 | for(i = 1; i <= MAX_CONNECTION_NUM; i++) 60 | { 61 | if(0 == i % 1000) 62 | {//稍稍停顿一下,避免把服务端的握手队列打满 63 | printf("%s 连接 %s:%d成功了 %d 条!\n", lIp, sIp, sPort, i); 64 | sleep(1); 65 | } 66 | 67 | fd = buildConnect(lIp, sIp, sPort); 68 | if(fd > 0) 69 | { 70 | sockets[i-1] = fd; 71 | }else{ 72 | return 1; 73 | } 74 | } 75 | sleep(300); 76 | 77 | //3. 释放所有的连接 78 | printf("关闭所有的连接...\n"); 79 | for(i = 0; i < MAX_CONNECTION_NUM; i++) 80 | { 81 | close(sockets[i]); 82 | } 83 | 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /tests/network/test02/c/server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define MAX_CONNECTION_NUM 1100000 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | char ip[16]; 11 | int lisFd, conFd, port; 12 | struct sockaddr_in servAddr; 13 | 14 | if(argc != 3) 15 | { 16 | printf("\n Usage: %s \n", argv[0]); 17 | return 1; 18 | } 19 | 20 | //1. 从命令行获取并解析server ip以及端口 21 | strcpy(ip, argv[1]); 22 | port = atoi(argv[2]); 23 | 24 | //2. 创建server 25 | if((lisFd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 26 | { 27 | printf("\n Error : Could not create socket\n"); 28 | return 0; 29 | } 30 | 31 | servAddr.sin_family = AF_INET; 32 | servAddr.sin_addr.s_addr = inet_addr(ip); 33 | servAddr.sin_port = htons(port); 34 | if(bind(lisFd, (struct sockaddr*)&servAddr, sizeof(servAddr)) < 0) 35 | { 36 | printf("\n Error : Bind Failed \n"); 37 | } 38 | if((listen(lisFd, 1024)) < 0) 39 | { 40 | printf("\n Error : Listen Failed \n"); 41 | } 42 | 43 | //3. 接收连接 44 | int i = 0; 45 | int *sockets = (int *)malloc(sizeof(int) * MAX_CONNECTION_NUM); 46 | while(1) 47 | { 48 | conFd = accept(lisFd, (struct sockaddr*)NULL, NULL); 49 | if(conFd > 0) 50 | { 51 | sockets[i++] = conFd; 52 | printf("%s %d accept success:%d\n", ip, port, i); 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /tests/network/test02/c/tool.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #--------------------------- begin ------------------------- 4 | #注意:这一部分的内容需要根据你自己的实验环境来设置 5 | 6 | #1.客户端 IP 列表:选择20个,且不能在局域网中存在 7 | # 示例 8 | # IPS=( 9 | # "192.168.1.200" 10 | # "192.168.1.201" 11 | # ) 12 | 13 | IPS=( 14 | "192.168.1.200" 15 | "192.168.1.201" 16 | ) 17 | 18 | #2.客户端 IP 对应的子网掩码 19 | #示例: 20 | #NETMASK="255.255.248.0" 21 | NETMASK="255.255.248.0" 22 | 23 | #3.服务端的 IP 和 端口 24 | #示例 25 | #SERVERIP="192.168.1.100" 26 | #SERVERPORT="8090" 27 | SERVERIP="192.168.1.100" 28 | SERVERPORT="8090" 29 | #--------------------------- end ------------------------- 30 | 31 | TYPE=$1 32 | 33 | exec_ping(){ 34 | for i in "${!IPS[@]}"; do 35 | ping -c 1 -W 1 ${IPS[$i]} > /dev/null 36 | if [[ $? != 0 ]];then 37 | echo ${IPS[$i]}" false" 38 | else 39 | echo ${IPS[$i]}" true" 40 | fi 41 | done 42 | } 43 | 44 | exec_ifup(){ 45 | for i in "${!IPS[@]}"; do 46 | echo ifconfig eth0:$i ${IPS[$i]} netmask $NETMASK up 47 | ifconfig eth0:$i ${IPS[$i]} netmask $NETMASK up 48 | done 49 | } 50 | 51 | exec_ifdown(){ 52 | for i in "${!IPS[@]}"; do 53 | echo ifconfig eth0:$i down 54 | ifconfig eth0:$i down 55 | done 56 | } 57 | 58 | exec_runcli(){ 59 | for i in "${!IPS[@]}"; do 60 | echo $CLIENT ${IPS[$i]} $SERVERIP $SERVERPORT 61 | $CLIENT ${IPS[$i]} $SERVERIP $SERVERPORT & 62 | done 63 | } 64 | 65 | exec_stopcli(){ 66 | ps -ef | grep $CLIENT | awk '{print $2}' | xargs kill -9 > /dev/null 67 | } 68 | 69 | exec_runsrv(){ 70 | echo $SERVER 0.0.0.0 $SERVERPORT 71 | $SERVER 0.0.0.0 $SERVERPORT 72 | } 73 | 74 | case $TYPE in 75 | "ping") exec_ping;; 76 | "ifup") exec_ifup;; 77 | "ifdown") exec_ifdown;; 78 | "runcli") CLIENT=$2; exec_runcli;; 79 | "stopcli") CLIENT=$2; exec_stopcli;; 80 | "runsrv") SERVER=$2; exec_runsrv;; 81 | *) echo "get unkown type $TYPE"; exit ;; 82 | esac 83 | 84 | -------------------------------------------------------------------------------- /tests/network/test02/java/Client.java: -------------------------------------------------------------------------------- 1 | import java.net.Socket; 2 | import java.net.InetSocketAddress; 3 | 4 | public class Client { 5 | 6 | public static final int MAX_CONNECTION_NUM = 50000; 7 | 8 | public static void main(String[] args) throws Exception { 9 | if(3 != args.length){ 10 | System.out.println("Usage: java Client \n"); 11 | return; 12 | } 13 | 14 | //1. 从命令行获取并解析local ip、server ip以及端口 15 | String lIp = args[0]; 16 | String sIp = args[1]; 17 | int sPort = Integer.parseInt(args[2]); 18 | 19 | //2. 开始建立连接 20 | //用数组将 socket 保存起来,防止连接被过早释放 21 | Socket[] sockets = new Socket[MAX_CONNECTION_NUM]; 22 | for(int i = 1; i <= MAX_CONNECTION_NUM; i++){ 23 | try { 24 | Socket s = new Socket(); 25 | s.bind(new InetSocketAddress(lIp, 0)); 26 | s.connect(new InetSocketAddress(sIp, sPort)); 27 | 28 | if(false == s.isConnected()){ 29 | System.out.println(lIp + " 连接 "+sIp+":"+sPort+" 失败! "); 30 | return; 31 | } 32 | sockets[i-1] = s; 33 | 34 | } catch (Exception e) { 35 | //连接失败则小憩一会儿接着连 36 | Thread.sleep(500); 37 | e.printStackTrace(); 38 | } 39 | 40 | //稍稍停顿一下,避免把服务端的握手队列打满 41 | if(0 == i % 500){ 42 | Thread.sleep(500); 43 | System.out.println(lIp + " 连接 "+sIp+":"+sPort+" 成功了 "+i+" 条"); 44 | } 45 | } 46 | 47 | //把所有连接都 hold 一会儿,方便观察 48 | Thread.sleep(300 * 1000); 49 | 50 | //3. 释放所有的连接 51 | System.out.println("关闭所有的连接...\n"); 52 | for(int i = 0; i < MAX_CONNECTION_NUM; i++){ 53 | sockets[i].close(); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /tests/network/test02/java/Makefile: -------------------------------------------------------------------------------- 1 | CLIENT_BINARY_NAME := "java Client" 2 | SERVER_BINARY_NAME := "java Server" 3 | 4 | .PHONY: ping 5 | ping: 6 | sh tool.sh ping 7 | 8 | .PHONY: ifup 9 | ifup: 10 | sh tool.sh ifup 11 | 12 | .PHONY: ifdown 13 | ifdown: 14 | sh tool.sh ifdown 15 | 16 | .PHONY: build-cli 17 | build-cli: 18 | javac Client.java 19 | 20 | .PHONY: run-cli 21 | run-cli: build-cli 22 | sh tool.sh runcli $(CLIENT_BINARY_NAME) 23 | 24 | .PHONY: stop-cli 25 | stop-cli: 26 | sh tool.sh stopcli 27 | 28 | .PHONY: build-srv 29 | build-srv: 30 | javac Server.java 31 | 32 | .PHONY: run-srv 33 | run-srv: build-srv 34 | sh tool.sh runsrv $(SERVER_BINARY_NAME) 35 | 36 | .PHONY: clean 37 | clean: 38 | rm -f *.class 39 | -------------------------------------------------------------------------------- /tests/network/test02/java/Server.java: -------------------------------------------------------------------------------- 1 | import java.io.IOException; 2 | import java.net.ServerSocket; 3 | import java.net.Socket; 4 | import java.net.InetSocketAddress; 5 | 6 | public class Server { 7 | public static final int MAX_CONNECTION_NUM = 1100000; 8 | 9 | public static void main(String[] args) { 10 | if(2 != args.length){ 11 | System.out.println("Usage: java Server \n"); 12 | return; 13 | } 14 | 15 | String sIp = args[0]; 16 | int sPort = Integer.parseInt(args[1]); 17 | 18 | //用数组将 socket 保存起来,防止连接被过早回收 19 | Socket[] sockets = new Socket[MAX_CONNECTION_NUM]; 20 | 21 | try { 22 | ServerSocket ss = new ServerSocket(); 23 | ss.bind(new InetSocketAddress(sIp, sPort), 1024); 24 | System.out.println("启动Server " + sIp + ":" + sPort + "..."); 25 | 26 | int i = 0; 27 | while(true){ 28 | try{ 29 | Socket s = ss.accept(); 30 | sockets[i] = s; 31 | i++; 32 | System.out.println("Server " + sIp + ":" + sPort + " 接收到第 " + i +" 条连接!"); 33 | } catch (IOException e) { 34 | e.printStackTrace(); 35 | } 36 | } 37 | } catch (IOException e) { 38 | e.printStackTrace(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/network/test02/java/tool.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #--------------------------- begin ------------------------- 4 | #注意:这一部分的内容需要根据你自己的实验环境来设置 5 | 6 | #1.客户端 IP 列表:选择20个,且不能在局域网中存在 7 | # 示例 8 | # IPS=( 9 | # "192.168.1.200" 10 | # "192.168.1.201" 11 | # ) 12 | 13 | IPS=( 14 | "192.168.1.200" 15 | "192.168.1.201" 16 | ) 17 | 18 | #2.客户端 IP 对应的子网掩码 19 | #示例: 20 | #NETMASK="255.255.248.0" 21 | NETMASK="255.255.248.0" 22 | 23 | #3.服务端的 IP 和 端口 24 | #示例 25 | #SERVERIP="192.168.1.100" 26 | #SERVERPORT="8090" 27 | SERVERIP="192.168.1.100" 28 | SERVERPORT="8090" 29 | #--------------------------- end ------------------------- 30 | 31 | TYPE=$1 32 | 33 | exec_ping(){ 34 | for i in "${!IPS[@]}"; do 35 | ping -c 1 -W 1 ${IPS[$i]} > /dev/null 36 | if [[ $? != 0 ]];then 37 | echo ${IPS[$i]}" false" 38 | else 39 | echo ${IPS[$i]}" true" 40 | fi 41 | done 42 | } 43 | 44 | exec_ifup(){ 45 | for i in "${!IPS[@]}"; do 46 | echo ifconfig eth0:$i ${IPS[$i]} netmask $NETMASK up 47 | ifconfig eth0:$i ${IPS[$i]} netmask $NETMASK up 48 | done 49 | } 50 | 51 | exec_ifdown(){ 52 | for i in "${!IPS[@]}"; do 53 | echo ifconfig eth0:$i down 54 | ifconfig eth0:$i down 55 | done 56 | } 57 | 58 | exec_runcli(){ 59 | for i in "${!IPS[@]}"; do 60 | echo $CLIENT ${IPS[$i]} $SERVERIP $SERVERPORT 61 | $CLIENT ${IPS[$i]} $SERVERIP $SERVERPORT & 62 | done 63 | } 64 | 65 | exec_stopcli(){ 66 | ps -ef | grep java | grep Client | awk '{print $2}' | xargs kill -9 67 | } 68 | 69 | exec_runsrv(){ 70 | echo $SERVER 0.0.0.0 $SERVERPORT 71 | $SERVER 0.0.0.0 $SERVERPORT 72 | } 73 | 74 | case $TYPE in 75 | "ping") exec_ping;; 76 | "ifup") exec_ifup;; 77 | "ifdown") exec_ifdown;; 78 | "runcli") CLIENT=$2; exec_runcli;; 79 | "stopcli") CLIENT=$2; exec_stopcli;; 80 | "runsrv") SERVER=$2; exec_runsrv;; 81 | *) echo "get unkown type $TYPE"; exit ;; 82 | esac 83 | 84 | -------------------------------------------------------------------------------- /tests/network/test02/php/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: ping 2 | ping: 3 | sh tool.sh ping 4 | 5 | .PHONY: ifup 6 | ifup: 7 | sh tool.sh ifup 8 | 9 | .PHONY: ifdown 10 | ifdown: 11 | sh tool.sh ifdown 12 | 13 | .PHONY: run-cli 14 | run-cli: 15 | sh tool.sh runcli 16 | 17 | .PHONY: stop-cli 18 | stop-cli: 19 | sh tool.sh stopcli 20 | 21 | .PHONY: run-srv 22 | run-srv: 23 | sh tool.sh runsrv 24 | -------------------------------------------------------------------------------- /tests/network/test02/php/client.php: -------------------------------------------------------------------------------- 1 | /dev/null 36 | if [[ $? != 0 ]];then 37 | echo ${IPS[$i]}" false" 38 | else 39 | echo ${IPS[$i]}" true" 40 | fi 41 | done 42 | } 43 | 44 | exec_ifup(){ 45 | for i in "${!IPS[@]}"; do 46 | echo ifconfig eth0:$i ${IPS[$i]} netmask $NETMASK up 47 | ifconfig eth0:$i ${IPS[$i]} netmask $NETMASK up 48 | done 49 | } 50 | 51 | exec_ifdown(){ 52 | for i in "${!IPS[@]}"; do 53 | echo ifconfig eth0:$i down 54 | ifconfig eth0:$i down 55 | done 56 | } 57 | 58 | exec_runcli(){ 59 | for i in "${!IPS[@]}"; do 60 | echo php client.php ${IPS[$i]} $SERVERIP $SERVERPORT & 61 | php client.php ${IPS[$i]} $SERVERIP $SERVERPORT & 62 | done 63 | } 64 | 65 | exec_stopcli(){ 66 | ps -ef | grep client.php | awk '{print $2}' | xargs kill -9 67 | } 68 | 69 | exec_runsrv(){ 70 | echo php server.php 0.0.0.0 $SERVERPORT 71 | php server.php 0.0.0.0 $SERVERPORT 72 | } 73 | 74 | case $TYPE in 75 | "ping") exec_ping;; 76 | "ifup") exec_ifup;; 77 | "ifdown") exec_ifdown;; 78 | "runcli") exec_runcli;; 79 | "stopcli") exec_stopcli;; 80 | "runsrv") exec_runsrv;; 81 | *) echo "get unkown type $TYPE"; exit ;; 82 | esac 83 | 84 | -------------------------------------------------------------------------------- /tests/network/test03/c/Makefile: -------------------------------------------------------------------------------- 1 | CLIENT_BINARY_NAME := "test-client" 2 | SERVER_BINARY_NAME := "test-server" 3 | 4 | .PHONY: build-cli 5 | build-cli: 6 | gcc client.c -o $(CLIENT_BINARY_NAME) 7 | 8 | .PHONY: run-cli 9 | run-cli: build-cli 10 | sh tool.sh runcli ./$(CLIENT_BINARY_NAME) 11 | 12 | .PHONY: stop-cli 13 | stop-cli: 14 | sh tool.sh stopcli ./$(CLIENT_BINARY_NAME) 15 | 16 | .PHONY: build-srv 17 | build-srv: 18 | gcc server.c -o $(SERVER_BINARY_NAME) 19 | 20 | .PHONY: run-srv 21 | run-srv: build-srv 22 | sh tool.sh runsrv ./$(SERVER_BINARY_NAME) 23 | 24 | .PHONY: stop-srv 25 | stop-srv: 26 | sh tool.sh stopsrv ./$(SERVER_BINARY_NAME) 27 | 28 | .PHONY: clean 29 | clean: 30 | rm -f ${CLIENT_BINARY_NAME} 31 | rm -f $(SERVER_BINARY_NAME) 32 | -------------------------------------------------------------------------------- /tests/network/test03/c/client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | #define MAX_CONNECTION_NUM 50000 10 | 11 | int buildConnect(const char *sIp, int sPort) 12 | { 13 | int skFd; 14 | if((skFd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 15 | { 16 | printf("\n Error : Could not create socket\n"); 17 | return 0; 18 | } 19 | 20 | struct sockaddr_in srvAddr; 21 | srvAddr.sin_family = AF_INET; 22 | srvAddr.sin_addr.s_addr = inet_addr(sIp); 23 | srvAddr.sin_port = htons(sPort); 24 | if(connect(skFd, (struct sockaddr *)&srvAddr, sizeof(srvAddr)) < 0) 25 | { 26 | printf("\n Error : Connect Failed \n"); 27 | return 0; 28 | } 29 | 30 | return skFd; 31 | } 32 | 33 | int main(int argc, char *argv[]) 34 | { 35 | int i = 0, sPort, fd; 36 | char sIp[16]; 37 | 38 | if(argc != 3) 39 | { 40 | printf("\n Usage: %s \n", argv[0]); 41 | return 1; 42 | } 43 | 44 | //1. 从命令行获取并解析server ip以及端口 45 | strcpy(sIp, argv[1]); 46 | sPort = atoi(argv[2]); 47 | 48 | //2. 开始建立连接 49 | int *sockets = (int *)malloc(sizeof(int) * MAX_CONNECTION_NUM); 50 | for(i = 1; i <= MAX_CONNECTION_NUM; i++) 51 | { 52 | if(0 == i % 1000) 53 | {//稍稍停顿一下,避免把服务端的握手队列打满 54 | printf("连接 %s:%d成功了 %d 条!\n", sIp, sPort, i); 55 | sleep(1); 56 | } 57 | 58 | fd = buildConnect(sIp, sPort); 59 | if(fd > 0) 60 | { 61 | sockets[i-1] = fd; 62 | }else{ 63 | return 1; 64 | } 65 | } 66 | sleep(300); 67 | 68 | //3. 释放所有的连接 69 | printf("关闭所有的连接...\n"); 70 | for(i = 0; i < MAX_CONNECTION_NUM; i++) 71 | { 72 | close(sockets[i]); 73 | } 74 | 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /tests/network/test03/c/server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define MAX_CONNECTION_NUM 1100000 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | char ip[16]; 11 | int lisFd, conFd, port; 12 | struct sockaddr_in servAddr; 13 | 14 | if(argc != 3) 15 | { 16 | printf("\n Usage: %s \n", argv[0]); 17 | return 1; 18 | } 19 | 20 | //1. 从命令行获取并解析server ip以及端口 21 | strcpy(ip, argv[1]); 22 | port = atoi(argv[2]); 23 | 24 | //2. 创建server 25 | if((lisFd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 26 | { 27 | printf("\n Error : Could not create socket\n"); 28 | return 0; 29 | } 30 | 31 | servAddr.sin_family = AF_INET; 32 | servAddr.sin_addr.s_addr = inet_addr(ip); 33 | servAddr.sin_port = htons(port); 34 | if(bind(lisFd, (struct sockaddr*)&servAddr, sizeof(servAddr)) < 0) 35 | { 36 | printf("\n Error : Bind Failed \n"); 37 | } 38 | if((listen(lisFd, 1024)) < 0) 39 | { 40 | printf("\n Error : Listen Failed \n"); 41 | } 42 | 43 | //3. 接收连接 44 | int i = 0; 45 | int *sockets = (int*)malloc(sizeof(int) * MAX_CONNECTION_NUM); 46 | while(1) 47 | { 48 | conFd = accept(lisFd, (struct sockaddr*)NULL, NULL); 49 | if(conFd > 0) 50 | { 51 | sockets[i++] = conFd; 52 | printf("%s %d accept success:%d\n", ip, port, i); 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /tests/network/test03/c/tool.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #--------------------------- begin ------------------------- 4 | #注意:这一部分的内容需要根据你自己的实验环境来设置 5 | 6 | #1.服务端的 IP 7 | #示例 8 | #SERVERIP="192.168.1.100" 9 | SERVERIP="192.168.1.100" 10 | 11 | #2.服务端的端口 12 | SERVERPORTS=( 13 | "8100" 14 | "8101" 15 | "8102" 16 | "8103" 17 | "8104" 18 | "8105" 19 | "8106" 20 | "8107" 21 | "8108" 22 | "8109" 23 | "8110" 24 | "8111" 25 | "8112" 26 | "8113" 27 | "8114" 28 | "8115" 29 | "8116" 30 | "8117" 31 | "8118" 32 | "8119" 33 | ) 34 | #--------------------------- end ------------------------- 35 | 36 | TYPE=$1 37 | 38 | exec_runcli(){ 39 | for i in "${!SERVERPORTS[@]}"; do 40 | echo $CLIENT $SERVERIP ${SERVERPORTS[$i]} & 41 | $CLIENT $SERVERIP ${SERVERPORTS[$i]} & 42 | done 43 | } 44 | 45 | exec_stopcli(){ 46 | ps -ef | grep $CLIENT | awk '{print $2}' | xargs kill -9 47 | } 48 | 49 | exec_runsrv(){ 50 | for i in "${!SERVERPORTS[@]}"; do 51 | echo $SERVER 0.0.0.0 ${SERVERPORTS[$i]} & 52 | $SERVER 0.0.0.0 ${SERVERPORTS[$i]} & 53 | done 54 | } 55 | 56 | exec_stopsrv(){ 57 | ps -ef | grep $SERVER | awk '{print $2}' | xargs kill -9 58 | } 59 | 60 | case $TYPE in 61 | "runcli") CLIENT=$2; exec_runcli;; 62 | "stopcli") CLIENT=$2; exec_stopcli;; 63 | "runsrv") SERVER=$2; exec_runsrv;; 64 | "stopsrv") SERVER=$2; exec_stopsrv;; 65 | *) echo "get unkown type $TYPE"; exit ;; 66 | esac 67 | 68 | -------------------------------------------------------------------------------- /tests/network/test03/java/Client.java: -------------------------------------------------------------------------------- 1 | import java.net.Socket; 2 | import java.net.InetSocketAddress; 3 | 4 | public class Client { 5 | public static final int MAX_CONNECTION_NUM = 50000; 6 | 7 | public static void main(String[] args) throws Exception { 8 | if(2 != args.length){ 9 | System.out.println("Usage: java Client \n"); 10 | return; 11 | } 12 | 13 | //1. 从命令行获取并解析local ip、server ip以及端口 14 | String sIp = args[0]; 15 | int sPort = Integer.parseInt(args[1]); 16 | 17 | //2. 开始建立连接 18 | //用数组将 socket 保存起来,防止连接被过早释放 19 | Socket[] sockets = new Socket[MAX_CONNECTION_NUM]; 20 | for(int i = 1; i <= MAX_CONNECTION_NUM; i++){ 21 | try { 22 | Socket s = new Socket(); 23 | s.connect(new InetSocketAddress(sIp, sPort)); 24 | 25 | if(false == s.isConnected()){ 26 | System.out.println(" 连接 "+sIp+":"+sPort+" 失败! "); 27 | return; 28 | } 29 | sockets[i-1] = s; 30 | 31 | } catch (Exception e) { 32 | //连接失败则小憩一会儿接着连 33 | Thread.sleep(500); 34 | e.printStackTrace(); 35 | } 36 | 37 | //稍稍停顿一下,避免把服务端的握手队列打满 38 | if(0 == i % 500){ 39 | Thread.sleep(500); 40 | System.out.println("连接 "+sIp+":"+sPort+" 成功了 "+i+" 条"); 41 | } 42 | } 43 | 44 | //把所有连接都 hold 一会儿,方便观察 45 | Thread.sleep(300 * 1000); 46 | 47 | //3. 释放所有的连接 48 | System.out.println("关闭所有的连接...\n"); 49 | for(int i = 0; i < MAX_CONNECTION_NUM; i++){ 50 | sockets[i].close(); 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /tests/network/test03/java/Makefile: -------------------------------------------------------------------------------- 1 | CLIENT_BINARY_NAME := "java Client" 2 | SERVER_BINARY_NAME := "java Server" 3 | 4 | .PHONY: build-cli 5 | build-cli: 6 | javac Client.java 7 | 8 | .PHONY: run-cli 9 | run-cli: build-cli 10 | sh tool.sh runcli $(CLIENT_BINARY_NAME) 11 | 12 | .PHONY: stop-cli 13 | stop-cli: 14 | sh tool.sh stopcli 15 | 16 | .PHONY: build-srv 17 | build-srv: 18 | javac Server.java 19 | 20 | .PHONY: run-srv 21 | run-srv: build-srv 22 | sh tool.sh runsrv $(SERVER_BINARY_NAME) 23 | 24 | .PHONY: stop-srv 25 | stop-srv: 26 | sh tool.sh stopsrv 27 | 28 | .PHONY: clean 29 | clean: 30 | rm -f *.class 31 | -------------------------------------------------------------------------------- /tests/network/test03/java/Server.java: -------------------------------------------------------------------------------- 1 | import java.io.IOException; 2 | import java.net.ServerSocket; 3 | import java.net.Socket; 4 | import java.net.InetSocketAddress; 5 | 6 | public class Server { 7 | 8 | public static final int MAX_CONNECTION_NUM = 1100000; 9 | 10 | public static void main(String[] args) { 11 | if(2 != args.length){ 12 | System.out.println("Usage: java Server \n"); 13 | return; 14 | } 15 | 16 | String sIp = args[0]; 17 | int sPort = Integer.parseInt(args[1]); 18 | 19 | //用数组将 socket 保存起来,防止连接被过早回收 20 | Socket[] sockets = new Socket[MAX_CONNECTION_NUM]; 21 | 22 | try { 23 | ServerSocket ss = new ServerSocket(); 24 | ss.bind(new InetSocketAddress(sIp, sPort), 1024); 25 | System.out.println("启动Server " + sIp + ":" + sPort + "..."); 26 | 27 | int i = 0; 28 | while(true){ 29 | try{ 30 | Socket s = ss.accept(); 31 | sockets[i] = s; 32 | i++; 33 | System.out.println("Server " + sIp + ":" + sPort + " 接收到第 " + i +" 条连接!"); 34 | } catch (IOException e) { 35 | e.printStackTrace(); 36 | } 37 | } 38 | } catch (IOException e) { 39 | e.printStackTrace(); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /tests/network/test03/java/tool.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #--------------------------- begin ------------------------- 4 | #注意:这一部分的内容需要根据你自己的实验环境来设置 5 | 6 | #1.服务端的 IP 7 | #示例 8 | #SERVERIP="192.168.1.100" 9 | SERVERIP="192.168.1.100" 10 | 11 | #2.服务端的端口 12 | SERVERPORTS=( 13 | "8100" 14 | "8101" 15 | "8102" 16 | "8103" 17 | "8104" 18 | "8105" 19 | "8106" 20 | "8107" 21 | "8108" 22 | "8109" 23 | "8110" 24 | "8111" 25 | "8112" 26 | "8113" 27 | "8114" 28 | "8115" 29 | "8116" 30 | "8117" 31 | "8118" 32 | "8119" 33 | ) 34 | #--------------------------- end ------------------------- 35 | 36 | TYPE=$1 37 | 38 | exec_runcli(){ 39 | for i in "${!SERVERPORTS[@]}"; do 40 | echo $CLIENT $SERVERIP ${SERVERPORTS[$i]} & 41 | $CLIENT $SERVERIP ${SERVERPORTS[$i]} & 42 | done 43 | } 44 | 45 | exec_stopcli(){ 46 | ps -ef | grep java | grep Client | awk '{print $2}' | xargs kill -9 47 | } 48 | 49 | exec_runsrv(){ 50 | for i in "${!SERVERPORTS[@]}"; do 51 | echo $SERVER 0.0.0.0 ${SERVERPORTS[$i]} & 52 | $SERVER 0.0.0.0 ${SERVERPORTS[$i]} & 53 | done 54 | } 55 | 56 | exec_stopsrv(){ 57 | ps -ef | grep java | grep Server | awk '{print $2}' | xargs kill -9 58 | } 59 | 60 | case $TYPE in 61 | "runcli") CLIENT=$2; exec_runcli;; 62 | "stopcli") exec_stopcli;; 63 | "runsrv") SERVER=$2; exec_runsrv;; 64 | "stopsrv") exec_stopsrv;; 65 | *) echo "get unkown type $TYPE"; exit ;; 66 | esac 67 | 68 | -------------------------------------------------------------------------------- /tests/network/test03/php/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: run-cli 2 | run-cli: 3 | sh tool.sh runcli 4 | 5 | .PHONY: stop-cli 6 | stop-cli: 7 | sh tool.sh stopcli 8 | 9 | .PHONY: run-srv 10 | run-srv: 11 | sh tool.sh runsrv 12 | 13 | .PHONY: stop-srv 14 | stop-srv: 15 | sh tool.sh stopsrv 16 | -------------------------------------------------------------------------------- /tests/network/test03/php/client.php: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define BUFFER_MAX 2048 10 | 11 | typedef int int32; 12 | typedef unsigned int u_int32; 13 | typedef unsigned char u_char; 14 | typedef unsigned short u_short; 15 | 16 | //参考内核 struct ethhdr 定义 (include/uapi/linux/if_ether.h) 17 | typedef struct eth_hdr { 18 | char h_dest[6]; 19 | char h_source[6]; 20 | short h_proto; 21 | }__attribute__((packed)); 22 | 23 | //参考内核 struct iphdr 定义(include/uapi/linux/ip.h) 24 | typedef struct iphdr{ 25 | #ifdef __LITTLE_ENDIAN_BIFIELD 26 | u_char ip_len:4, ip_ver:4; 27 | #else 28 | u_char ip_ver:4, ip_len:4; 29 | #endif 30 | u_char tos; 31 | u_short total_len; 32 | u_short id; 33 | u_short flags_off; 34 | u_char ttl; 35 | u_char protocol; 36 | u_short check; 37 | u_int32 saddr; 38 | u_int32 daddr; 39 | }__attribute__((packed)); 40 | 41 | int main(int argc, char *argv[]) 42 | { 43 | int sock; 44 | char buffer[BUFFER_MAX]; 45 | int len; 46 | 47 | struct eth_hdr *mac_hdr; 48 | struct iphdr *ip_hdr; 49 | char* p; 50 | 51 | if( (sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0 ){ 52 | printf("Create socket error.\n"); 53 | exit(0); 54 | } 55 | 56 | while(1){ 57 | len = recvfrom(sock, buffer, BUFFER_MAX, 0, NULL, NULL); 58 | if (len < 46) { 59 | printf("Catch packet length error.\n" ); 60 | close(sock); 61 | exit(0); 62 | } 63 | 64 | printf("截获内容长度 %d\n", len); 65 | 66 | mac_hdr = buffer; 67 | ip_hdr = buffer + sizeof(struct ethhdr); 68 | 69 | printf("源 MAC:%X:%X:%X:%X:%X:%X", 70 | (u_char)mac_hdr->h_source[0], 71 | (u_char)mac_hdr->h_source[1], 72 | (u_char)mac_hdr->h_source[2], 73 | (u_char)mac_hdr->h_source[3], 74 | (u_char)mac_hdr->h_source[4], 75 | (u_char)mac_hdr->h_source[5] 76 | ); 77 | 78 | printf(" ==> 目的 MAC:%X:%X:%X:%X:%X\n", 79 | (u_char)mac_hdr->h_dest[0], 80 | (u_char)mac_hdr->h_dest[1], 81 | (u_char)mac_hdr->h_dest[2], 82 | (u_char)mac_hdr->h_dest[3], 83 | (u_char)mac_hdr->h_dest[4], 84 | (u_char)mac_hdr->h_dest[5] 85 | ); 86 | 87 | p = (char*)&ip_hdr->saddr; 88 | printf("源 IP: %d.%d.%d.%d", 89 | (u_char)p[0], 90 | (u_char)p[1], 91 | (u_char)p[2], 92 | (u_char)p[3] 93 | ); 94 | 95 | p = (char*)&ip_hdr->daddr; 96 | printf(" ==> 目的 IP: %d.%d.%d.%d\n", 97 | (u_char)p[0], 98 | (u_char)p[1], 99 | (u_char)p[2], 100 | (u_char)p[3] 101 | ); 102 | 103 | printf("协议类型:"); 104 | switch(ip_hdr->protocol) { 105 | case IPPROTO_ICMP: 106 | printf("ICMP"); 107 | break; 108 | case IPPROTO_IGMP: 109 | printf("IGMP"); 110 | break; 111 | case IPPROTO_IPIP: 112 | printf("IPIP"); 113 | break; 114 | case IPPROTO_TCP: 115 | printf("TCP"); 116 | break; 117 | case IPPROTO_UDP: 118 | printf("UDP"); 119 | break; 120 | case IPPROTO_RAW: 121 | printf("RAW"); 122 | break; 123 | default: 124 | printf("Unknown type"); 125 | break; 126 | } 127 | 128 | printf("\n\n"); 129 | } 130 | 131 | close(sock); 132 | return 0; 133 | } 134 | --------------------------------------------------------------------------------