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 thistext("线程执行完成!共耗时 " + (end-start) +" 毫秒"); 202 203 //如果porttext有数据则通知UI更新 204 if (portstext == null || portstext.length() == 0) { 205 return; 206 }else { 207 Message msg = Message.obtain(); 208 msg.what = 1; 209 msg.arg1 = 1; 210 msg.obj = "更新UI列表"; 211 mHandler.sendMessage(msg); 212 213 return; 214 } 215 } 216 } 217 218 //验证是否有空编辑框 219 public boolean iftext(){ 220 if (ip == null || ip.length() == 0 || portmax == 0 || portmin == 0){ 221 return false; 222 }else { 223 return true; 224 } 225 } 226 }
4.调试输出截图(模拟器2核4线程)
实际测试时 1-65535 端口 用16线程 跑了21分钟