Android Studio 3.1.4
Build #AI-173.4907809, built on July 24, 2018
JRE: 1.8.0_152-release-1024-b02 amd64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Windows 10 10.0
Lucky~
1.XML布局界面文件
1 <?xml version="1.0" encoding="utf-8"?>
2 <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 xmlns:tools="http://schemas.android.com/tools"
5 android:layout_width="match_parent"
6 android:layout_height="match_parent"
7 tools:context=".PortScan">
8
9 <TextView
10 android:id="@+id/textView3"
11 android:layout_width="75dp"
12 android:layout_height="26dp"
13 android:layout_marginBottom="8dp"
14 android:layout_marginEnd="8dp"
15 android:layout_marginStart="8dp"
16 android:layout_marginTop="8dp"
17 android:text="PortMin"
18 android:textColor="#FF00FF"
19 android:textSize="18sp"
20 app:layout_constraintBottom_toBottomOf="parent"
21 app:layout_constraintEnd_toEndOf="parent"
22 app:layout_constraintHorizontal_bias="0.0"
23 app:layout_constraintStart_toStartOf="parent"
24 app:layout_constraintTop_toTopOf="parent"
25 app:layout_constraintVertical_bias="0.25" />
26
27 <TextView
28 android:id="@+id/textView4"
29 android:layout_width="75dp"
30 android:layout_height="26dp"
31 android:layout_marginBottom="8dp"
32 android:layout_marginEnd="8dp"
33 android:layout_marginStart="8dp"
34 android:layout_marginTop="8dp"
35 android:text="PortMax"
36 android:textColor="#FF00FF"
37 android:textSize="18sp"
38 app:layout_constraintBottom_toBottomOf="parent"
39 app:layout_constraintEnd_toEndOf="parent"
40 app:layout_constraintHorizontal_bias="0.65"
41 app:layout_constraintStart_toStartOf="parent"
42 app:layout_constraintTop_toTopOf="parent"
43 app:layout_constraintVertical_bias="0.25" />
44
45 <TextView
46 android:id="@+id/textView"
47 android:layout_width="137dp"
48 android:layout_height="42dp"
49 android:layout_marginBottom="8dp"
50 android:layout_marginEnd="8dp"
51 android:layout_marginStart="8dp"
52 android:layout_marginTop="8dp"
53 android:text="PortScan"
54 android:textColor="#FF00FF"
55 android:textSize="30sp"
56 app:layout_constraintBottom_toBottomOf="parent"
57 app:layout_constraintEnd_toEndOf="parent"
58 app:layout_constraintHorizontal_bias="0.05"
59 app:layout_constraintStart_toStartOf="parent"
60 app:layout_constraintTop_toTopOf="parent"
61 app:layout_constraintVertical_bias="0.00999999" />
62
63 <TextView
64 android:id="@+id/textView2"
65 android:layout_width="75dp"
66 android:layout_height="26dp"
67 android:layout_marginBottom="8dp"
68 android:layout_marginEnd="8dp"
69 android:layout_marginStart="8dp"
70 android:layout_marginTop="8dp"
71 android:text="IP"
72 android:textColor="#FF00FF"
73 android:textSize="18sp"
74 app:layout_constraintBottom_toBottomOf="parent"
75 app:layout_constraintEnd_toEndOf="parent"
76 app:layout_constraintHorizontal_bias="0.0"
77 app:layout_constraintStart_toStartOf="parent"
78 app:layout_constraintTop_toTopOf="parent"
79 app:layout_constraintVertical_bias="0.13999999" />
80
81 <EditText
82 android:id="@+id/ipedit"
83 android:layout_width="267dp"
84 android:layout_height="42dp"
85 android:layout_marginBottom="8dp"
86 android:layout_marginEnd="8dp"
87 android:layout_marginStart="8dp"
88 android:layout_marginTop="8dp"
89 android:ems="10"
90 android:inputType="textPersonName"
91 android:text="127.0.0.1"
92 android:textSize="18sp"
93 app:layout_constraintBottom_toBottomOf="parent"
94 app:layout_constraintEnd_toEndOf="parent"
95 app:layout_constraintHorizontal_bias="1.0"
96 app:layout_constraintStart_toStartOf="parent"
97 app:layout_constraintTop_toTopOf="parent"
98 app:layout_constraintVertical_bias="0.13" />
99
100 <EditText
101 android:id="@+id/portmin"
102 android:layout_width="80dp"
103 android:layout_height="42dp"
104 android:layout_marginBottom="8dp"
105 android:layout_marginEnd="8dp"
106 android:layout_marginStart="8dp"
107 android:layout_marginTop="8dp"
108 android:ems="10"
109 android:inputType="textPersonName"
110 android:text="1"
111 app:layout_constraintBottom_toBottomOf="parent"
112 app:layout_constraintEnd_toEndOf="parent"
113 app:layout_constraintHorizontal_bias="0.35"
114 app:layout_constraintStart_toStartOf="parent"
115 app:layout_constraintTop_toTopOf="parent"
116 app:layout_constraintVertical_bias="0.239" />
117
118 <EditText
119 android:id="@+id/portmax"
120 android:layout_width="80dp"
121 android:layout_height="42dp"
122 android:layout_marginBottom="8dp"
123 android:layout_marginEnd="8dp"
124 android:layout_marginStart="8dp"
125 android:layout_marginTop="8dp"
126 android:ems="10"
127 android:inputType="textPersonName"
128 android:text="65535"
129 app:layout_constraintBottom_toBottomOf="parent"
130 app:layout_constraintEnd_toEndOf="parent"
131 app:layout_constraintHorizontal_bias="1.0"
132 app:layout_constraintStart_toStartOf="parent"
133 app:layout_constraintTop_toTopOf="parent"
134 app:layout_constraintVertical_bias="0.239" />
135
136 <Button
137 android:id="@+id/button"
138 android:layout_width="369dp"
139 android:layout_height="42dp"
140 android:layout_marginBottom="8dp"
141 android:layout_marginEnd="8dp"
142 android:layout_marginStart="8dp"
143 android:layout_marginTop="180dp"
144 android:onClick="play"
145 android:text="play"
146 android:textColor="#FF00FF"
147 app:layout_constraintBottom_toBottomOf="parent"
148 app:layout_constraintEnd_toEndOf="parent"
149 app:layout_constraintStart_toStartOf="parent"
150 app:layout_constraintTop_toTopOf="parent"
151 app:layout_constraintVertical_bias="0.005" />
152
153 <TextView
154 android:id="@+id/tv"
155 android:layout_width="368dp"
156 android:layout_height="23dp"
157 android:layout_marginBottom="16dp"
158 android:layout_marginEnd="8dp"
159 android:layout_marginStart="8dp"
160 android:layout_marginTop="8dp"
161 android:text="ing..."
162 android:textColor="#FF00FF"
163 android:textSize="14sp"
164 app:layout_constraintBottom_toBottomOf="parent"
165 app:layout_constraintEnd_toEndOf="parent"
166 app:layout_constraintStart_toStartOf="parent"
167 app:layout_constraintTop_toBottomOf="@+id/button"
168 app:layout_constraintVertical_bias="1.0" />
169
170 <ListView
171 android:id="@+id/listview"
172 android:layout_width="378dp"
173 android:layout_height="287dp"
174 android:layout_marginBottom="8dp"
175 android:layout_marginEnd="8dp"
176 android:layout_marginStart="16dp"
177 android:layout_marginTop="8dp"
178 app:layout_constraintBottom_toTopOf="@+id/tv"
179 app:layout_constraintEnd_toEndOf="parent"
180 app:layout_constraintStart_toStartOf="parent"
181 app:layout_constraintTop_toBottomOf="@+id/button"
182 app:layout_constraintVertical_bias="1.0" />
183
184 </android.support.constraint.ConstraintLayout>
2.添加权限
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.shawna.portscan">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".PortScan">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
3.项目代码
1 package com.shawna.portscan;
2
3 import android.os.Handler;
4 import android.os.Message;
5 import android.support.v7.app.AlertDialog;
6 import android.support.v7.app.AppCompatActivity;
7 import android.os.Bundle;
8 import android.view.View;
9 import android.widget.ArrayAdapter;
10 import android.widget.EditText;
11 import android.widget.ListView;
12 import android.widget.TextView;
13
14 import java.net.InetSocketAddress;
15 import java.net.Socket;
16 import java.net.SocketAddress;
17 import java.util.concurrent.ExecutorService;
18 import java.util.concurrent.Executors;
19
20 public class PortScan extends AppCompatActivity {
21
22 int portmin = 1;//最小ip取值
23 int portmax = 65535;//最大ip取值
24 String ip;//ip地址
25 String[] ports = new String[0];//成功连接的端口保存数组
26 String portstext;//成功连接的端口文本
27
28 @Override
29 protected void onCreate(Bundle savedInstanceState) {
30 super.onCreate(savedInstanceState);
31 setContentView(R.layout.activity_port_scan);
32
33 //状态条显示初始化信息
34 thistext("处理器核心数 " + thisGetCPUnum() + " 核,将使用 " + thisGetCPUnum()*2 + " 线程执行...");
35 }
36
37 public void play(View view){
38 //获取各个编辑框组件的内容
39 EditText ipEdit = (EditText) findViewById(R.id.ipedit);
40 EditText piedit = (EditText) findViewById(R.id.portmin);
41 EditText paedit = (EditText) findViewById(R.id.portmax);
42 ip = ipEdit.getText().toString();
43 portmin = Integer.parseInt(piedit.getText().toString());
44 portmax = Integer.parseInt(paedit.getText().toString());
45
46 //判断输入的内容是否合法
47 if (iftext() == false){
48 AlertDialog.Builder message = new AlertDialog.Builder(this);
49 message.setMessage("有数据漏填,请检查!");
50 AlertDialog m1 = message.create();
51 m1.show();
52 return;
53 }
54
55 //启动线程执行任务
56 thisiflink thisiflink = new thisiflink();
57 thisiflink.start();
58 }
59
60 //获取线程传出的消息更新UI
61 private Handler.Callback mCallback = new Handler.Callback() {
62 @Override
63 public boolean handleMessage(Message msg) {
64 if (msg.what == 1) {
65 if (msg.obj == "更新UI列表"){
66 if (portstext == null || portstext.length() == 0) {
67 return false;
68 } else {
69 //以#为分隔符分割文本
70 ports = portstext.split("\\#");
71 //调用函数更新UI状态条
72 thislist(ports);
73 }
74 }
75 }else if (msg.what == 1011){
76 if (msg.obj == null || msg.obj.toString().length() == 0){
77 return false;
78 }else {
79 //调用函数更新UI状态条
80 thistext(msg.obj.toString());
81 }
82 }
83
84 return false;
85 }
86 };
87
88 //创建一个Handler用于线程通讯
89 Handler mHandler = new Handler(mCallback);
90
91 //获取CPU核心数
92 public int thisGetCPUnum(){
93 return(Runtime.getRuntime().availableProcessors());
94 }
95
96 //列表框刷新数据
97 public void thislist(String[] text){
98 ListView mListView;
99 mListView = (ListView) findViewById(R.id.listview);
100 ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,text);
101 mListView.setAdapter(adapter);
102 }
103
104 //增加数据到数组
105 public static String[] thisArrayAdd(String[] text,String data){
106 //调用自定义函数增加数组成员
107 text = thisLengthArray(text);
108 //对新增加的数组成员赋值
109 text[text.length] = data;
110 //输出这个新数组
111 return text;
112 }
113
114 //状态条显示文本
115 public void thistext(String text){
116 TextView textView = (TextView) findViewById(R.id.tv);
117 textView.setText(text);
118 }
119
120 //数组增加成员数
121 public static String[] thisLengthArray(String[] text){
122 String[] newArray = new String[text.length+1];
123 System.arraycopy(text,0,newArray,0,text.length);
124 return newArray;
125 }
126
127 class thisiflink extends Thread{
128 //新建一个固定线程的线程池,线程数量为CPU核心数量的2倍
129 ExecutorService pool = Executors.newFixedThreadPool(thisGetCPUnum()*2);
130 @Override
131 public void run(){
132 //取任务开始时的时间
133 final long start = System.currentTimeMillis();
134 //防止数据重复执行前清空已保存的数据
135 portstext = null;
136 //循环执行,一个端口占用一个线程
137 for(int i = portmin ; i <= portmax ; i++) {
138 final int port = i;
139 Runnable runnable = new Runnable() {
140 @Override
141 public void run() {
142 boolean x = true;
143 try {
144 //port被5整除,则刷新UI状态条,显示当前扫描的端口
145 if (port%5 == 0){
146 Message msg1 = Message.obtain();
147 msg1.what = 1011;
148 msg1.arg1 = 1;
149 msg1.obj = "正在扫描 " + port + " 端口,请稍候...";
150 mHandler.sendMessage(msg1);
151 }
152
153 //socket尝试与指定IP的端口进行连接,超时300毫秒
154 Socket mSocket;
155 mSocket = new Socket();
156 SocketAddress socketAddress = new InetSocketAddress(ip, port);
157 mSocket.connect(socketAddress, 300);
158 mSocket.close();
159
160 //如果成功连接则输出连接成功
161 System.out.println("端口 " + port + " 连接成功!");
162
163 //防止下面代码有异常抛出将x赋值为false
164 x = false;
165
166 //将数据保存到porttext中
167 if (portstext == null || portstext.length() == 0){
168 portstext = "端口 " + port + " 连接成功!";
169 }else {
170 portstext = portstext + "#端口 " + port + " 连接成功!";
171 }
172
173 //通知刷新UI列表
174 Message msg = Message.obtain();
175 msg.what = 1;
176 msg.arg1 = 1;
177 msg.obj = "更新UI列表";
178 mHandler.sendMessage(msg);
179 } catch (Exception e) {
180 if (x) {
181 //如果连接失败则输出连接超时
182 System.out.println("端口 " + port + " 连接超时...");
183 }
184 }
185 }
186 };
187 pool.execute(runnable);//线程池循环
188 }
189 pool.shutdown();//线程池关闭
190 //等待线程结束
191 while (true){
192 if (pool.isTerminated()){
193 //线程结束输出保存的数据
194 System.out.println(portstext);
195 break;
196 }
197 }
198 //取任务结束时的时间
199 final long end = System.currentTimeMillis();
200 //计算时间差值输出到状态条
201 Message msg1 = Message.obtain();
202 msg1.what = 1011;
203 msg1.arg1 = 1;
204 msg1.obj = "线程执行完成!共耗时 " + (end-start) +" 毫秒";
205 mHandler.sendMessage(msg1);
206
207 //如果porttext有数据则通知UI更新
208 if (portstext == null || portstext.length() == 0) {
209 return;
210 }else {
211 Message msg = Message.obtain();
212 msg.what = 1;
213 msg.arg1 = 1;
214 msg.obj = "更新UI列表";
215 mHandler.sendMessage(msg);
216
217 return;
218 }
219 }
220 }
221
222 //验证是否有空编辑框
223 public boolean iftext(){
224 if (ip == null || ip.length() == 0 || portmax == 0 || portmin == 0){
225 return false;
226 }else {
227 return true;
228 }
229 }
230 }
4.调试输出截图(模拟器2核4线程)
实际测试时 1-65535 端口 用16线程 跑了21分钟