查看: 267|回复: 0

[Java代码] Java网络编程实现的简单端口扫描器示例

发表于 2018-5-6 09:00:40

本文实例讲述了Java网络编程实现的简单端口扫描器。分享给大家供大家参考,具体如下:

在计算机网络的学习中,不由得觉得这门课的零碎知识点异常之多,同时因为学习的课本是老外的教材——自顶向下方法,因此学习起来不免觉得吃力,但是从老外的教材里更能从一定高度理解计算机网络的知识体系,也是乐在其中,同时做英语的习题感觉也很有趣味,从各方面来说可以说是获益良多,认识了很多专业词汇。节课之后,便想做一个简单的端口扫描器,用的语言是java,因为实现界面很简单,同时也有封装好的Socket类可以使用,主要思路如下:

在主程序界面里输入指定主机名或ip地址,按下start按钮,就可以扫描主机的常用端口是否打开。内部设置了常用端口号:21, 22, 23, 25, 26, 69, 80, 110, 143,443, 465, 995, 1080, 1158,1433, 1521, 2100, 3128, 3306, 3389,7001, 8080, 8081, 9080, 9090, 43958。也可以自行修改。程序实现原理就是利用Java建立Socket去连接目标ip的指定端口,如果能连接上就证明该端口开放。反之,若在超时之前都没有连接上,则该端口是关闭的,同时会产生异常。同时考虑到单线程操作效率较低,也利用了Java可以多线程编程的特点,使用了多线程扫描目标主机的一个端口是否开放,因此最终显示结果中端口的排列顺序是随机的,且内部设定最多同时运行10个线程(可以根据实际情况更改)。

主要运用的网络知识就是套接字的使用。以及java内部的List容器,java的界面设计,界面布局,以及简单的泛型编程的用法。

主要代码如下:

  1. import java.awt.BorderLayout;
  2. import java.awt.Color;
  3. import java.awt.Font;
  4. import java.awt.GridLayout;
  5. import java.awt.event.ActionEvent;
  6. import java.awt.event.ActionListener;
  7. import java.io.IOException;
  8. import java.net.InetAddress;
  9. import java.net.InetSocketAddress;
  10. import java.net.Socket;
  11. import java.net.SocketAddress;
  12. import java.net.UnknownHostException;
  13. import java.util.Arrays;
  14. import java.util.LinkedList;
  15. import java.util.List;
  16. import java.util.concurrent.ExecutorService;
  17. import java.util.concurrent.Executors;
  18. import javax.swing.BorderFactory;
  19. import javax.swing.JButton;
  20. import javax.swing.JFrame;
  21. import javax.swing.JLabel;
  22. import javax.swing.JPanel;
  23. import javax.swing.JScrollPane;
  24. import javax.swing.JTextArea;
  25. import javax.swing.JTextField;
  26. public class ScanPort extends JFrame {
  27. /**
  28. * 端口扫描启动主程序
  29. */
  30. private static final long serialVersionUID = 1L;
  31. String str1 = " 常见端口有:";
  32. String str2 = "ftp:21,22,telnet:23,smtp:25,http:80";
  33. String str3 = "dns:53,tftp:69,snmp:161,162";
  34. String str4 = "1158,1433,1521,2100,3128,26,69";
  35. String str5 = "3306,3389,7001,8080,8081,110,143";
  36. String str6 = "9080,9090,43958,443,465,995,1080";
  37. JButton jb1 = new JButton("strat");
  38. JTextArea jta = new JTextArea();
  39. JScrollPane jsp = new JScrollPane(jta);
  40. JTextField jtf = new JTextField(17);
  41. String IP = "";//待扫描IP或域名
  42. List <Integer>portList = new LinkedList<Integer>();// 定义一个List容器表示扫描的团口的List集合
  43. Integer[] ports = new Integer[] { 21, 22, 23, 25, 26, 53,69, 80, 110, 143,
  44. 443,465,69,161,162,135,995,1080,1158,1433,1521,2100, 3128, 3306, 3389,
  45. 7001, 8080, 8081, 9080, 9090, 43958 ,135,445,1025,1026,1027,1028,1055,5357};
  46. // 常见端口集合
  47. public ScanPort() {
  48. this.add(getPanel(), BorderLayout.SOUTH);
  49. jsp.setBorder(BorderFactory.createEtchedBorder());
  50. jsp.setBackground(Color.cyan);
  51. this.add(jsp, BorderLayout.CENTER);
  52. this.add(getPanel2(), BorderLayout.NORTH);
  53. this.add(getPanel3(), BorderLayout.WEST);
  54. this.setBounds(300, 60, 600, 600);
  55. this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  56. this.setTitle("ScanPort");
  57. jta.setTabSize(4);
  58. jta.setFont(new Font("标楷体", Font.BOLD, 16));
  59. jta.setLineWrap(true);// 激活自动换行功能
  60. jta.setWrapStyleWord(true);// 激活断行不断字功能
  61. portList.addAll(Arrays.asList(ports));
  62. //将ports中的值加入到set中,并去掉重复的
  63. jb1.addActionListener(new ActionListener() {
  64. @Override
  65. public void actionPerformed(ActionEvent e) {
  66. // TODO Auto-generated method stub
  67. IP = jta.getText();
  68. //ip为文本框内输入的字符串
  69. scanPorts(IP, portList, 10, 800);
  70. //超时时间设定为800,线程数设定为10
  71. }
  72. });
  73. this.setVisible(true);
  74. }
  75. /**
  76. * 多线程扫描目标主机指定List端口集合的开放情况
  77. *
  78. * @param ip
  79. * 待扫描IP或域名
  80. * @param portList
  81. * 待扫描的端口的List集合
  82. * @param threadNumber
  83. * 线程数
  84. * @param timeout
  85. * 连接超时时间
  86. * */
  87. public void scanPorts(String ip, List<Integer> portSet,int threadNumber, int timeout) {
  88. ExecutorService threadPool = Executors.newCachedThreadPool();
  89. //线程池
  90. for (int i = 0; i < threadNumber; i++) {
  91. //10个线程 加入到线程池里
  92. ScanMethod scanMethod2 = new ScanMethod(ip, portSet,threadNumber, i, timeout);
  93. threadPool.execute(scanMethod2);
  94. }
  95. threadPool.shutdown();
  96. while (true) {
  97. if (threadPool.isTerminated()) {
  98. System.out.println("扫描结束");
  99. break;
  100. }
  101. try {
  102. Thread.sleep(1000);
  103. } catch (InterruptedException e) {
  104. e.printStackTrace();
  105. }
  106. }// end of while
  107. }
  108. /*
  109. * 扫描方式:针对一个待扫描的端口的List集合进行扫描
  110. */
  111. private class ScanMethod implements Runnable {
  112. private String ip; // 目标IP
  113. private List<Integer> portList; // 待扫描的端口的List集合
  114. private int threadNumber, serial, timeout; // 线程数,这是第几个线程,超时时间
  115. public ScanMethod(String ip, List<Integer> portList, int threadNumber,int serial, int timeout) {
  116. this.ip = ip;
  117. this.portList = portList;
  118. this.threadNumber = threadNumber;
  119. this.serial = serial;
  120. this.timeout = timeout;
  121. }
  122. public void run() {
  123. int port = 0;
  124. Integer[] ports = portList.toArray(new Integer[portList.size()]); // List转数组
  125. try {
  126. InetAddress address = InetAddress.getByName(ip); //如果输入的是主机名,尝试获取ip地址
  127. Socket socket;//定义套接字
  128. SocketAddress socketAddress;//传递ip和端口
  129. if (ports.length < 1)
  130. //若数组没有元素,返回,不执行
  131. return;
  132. for (port = 0 + serial; port <= ports.length - 1; port += threadNumber) {
  133. //每次运行10个线程
  134. socket = new Socket();
  135. //为对象分配内存空间
  136. socketAddress = new InetSocketAddress(address, ports[port]);
  137. try {
  138. socket.connect(socketAddress, timeout);
  139. //对目标主机的指定端口进行连接,超时后连接失败
  140. socket.close();
  141. //关闭端口
  142. System.out.println("端口 " + ports[port] + " :开放");
  143. jta.append("端口 " + ports[port] + " :开放\n");
  144. //在文本区域里更新消息
  145. } catch (IOException e) {
  146. System.out.println("端口 " + ports[port] + " :关闭");
  147. jta.append("端口 " + ports[port] + " :关闭\n");
  148. //产生异常表示端口关闭
  149. }
  150. }
  151. } catch (UnknownHostException e) {
  152. e.printStackTrace();
  153. }
  154. }
  155. //end of run()
  156. }//end of ScanMethod
  157. public JPanel getPanel() {
  158. JPanel jp = new JPanel();
  159. jp.add(jb1, BorderLayout.CENTER);
  160. jp.setBorder(BorderFactory.createRaisedBevelBorder());
  161. jp.setBackground(Color.lightGray);
  162. return jp;
  163. }
  164. public JPanel getPanel2() {
  165. JPanel jp = new JPanel();
  166. JLabel jl = new JLabel();
  167. jl.setText("请输入主机名或ip地址,将扫描该主机的常见端口号:");
  168. jp.add(jl);
  169. jp.add(jtf);
  170. jp.setBorder(BorderFactory.createRaisedBevelBorder());
  171. jp.setBackground(Color.LIGHT_GRAY);
  172. return jp;
  173. }
  174. public JPanel getPanel3() {
  175. JLabel jl1 = new JLabel(str1);
  176. JLabel jl2 = new JLabel(str2);
  177. JLabel jl3 = new JLabel(str3);
  178. JLabel jl4 = new JLabel(str4);
  179. JLabel jl5 = new JLabel(str5);
  180. JLabel jl6 = new JLabel(str6);
  181. JPanel jp = new JPanel();
  182. jp.setLayout(new GridLayout(6, 1));
  183. jp.add(jl1);
  184. jp.add(jl2);
  185. jp.add(jl3);
  186. jp.add(jl4);
  187. jp.add(jl5);
  188. jp.add(jl6);
  189. jp.setBorder(BorderFactory.createEtchedBorder());
  190. //蚀刻边框
  191. return jp;
  192. }
  193. public static void main(String[] args) {
  194. new ScanPort();
  195. }
  196. }
复制代码

更多关于java相关内容感兴趣的读者可查看本站专题:《Java网络编程技巧总结》、《Java Socket编程技巧总结》、《Java文件与目录操作技巧汇总》、《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》和《Java缓存操作技巧汇总》

希望本文所述对大家java程序设计有所帮助。



回复

使用道具 举报