
简要说明
本人才接触Android不就,这个月有个任务是这样的。客户端要和服务器进行Socket通信,由于服务器不固定也就导致了服务器IP不固定,就不能实现于多个服务器通信,于是有了这样一个需求。客户端根据服务器提供的端口号来扫描服务器IP,从而满足这个需求。拿到需求一看,果断不会,于是就百度去了。搜索解雇倒是不少,可是打开一看全是重复的代码,复制——粘贴。仔细一看,就连我这个新手也看出来了很多问题,果断拿来大大修改了一番,废话不多少直接看代码吧:
实现代码:
1 //本地IP
2 private String locAddress;
3 //核心线程数
4 private int corePoolSize = 2;
5 //最大线程数
6 private int maximumPoolSize = 5;
7 //线程池维护线程所允许的空闲时间
8 private long keepAliveTime = 30;
9 //线程池维护线程所允许的空闲时间的单位
10 private TimeUnit unit = TimeUnit.SECONDS;
1112 //线程池所使用的缓冲队列
13 private BlockingQueue<Runnable> workQueue = new LinkedBlockingDeque<Runnable>();
14 @SuppressWarnings("unused")
15 private ThreadPoolExecutor threadPoolExecutor
16 = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); 从这段代码可以看出,我主要是定义了一个线程池,之后要开启线程来扫描局域网IP的,百度的方法是直接开启255个线程,我对这种做法真不知道说什么了~~~不多说,直接看方法代码:
1
2 public void scan(final int SERVERPORT){
3 locAddress = getLocAddrIndex();//获取本地ip前缀
4
5 //开启线程
6 ute( new connectionServer(SERVERPORT, locAddress,0,100));
7 ute( new connectionServer(SERVERPORT, locAddress,101,200));
8 ute( new connectionServer(SERVERPORT, locAddress,201,256));
9 threadPoolExecutor.shutdownNow();
10
11 }
12 从这个方法是用于外部调用的scan方法,传递端口号,然后开启线程进行扫描,大家都知道,如果在一个局域网的话设备的网段是一样的,比如说:一台电脑和手机都连接了同一个wifi。那么电脑的IP就可能是192.168.8.X,手机IP就是192.168.8.Y。就是说前三个字段是一致的,那我们只要去适配最后一位,那手机就一定有几率来匹配到电脑。这样一来就简单了,最后一位无非就是1~255所以我把这个字段分开来,开启三个线程分别扫描。扫描方法之后会列出来,我们先看看怎么得到局域网前三个字段,也就是举例中的192.168.8
getLocAddrIndex()
方法是获得IP前缀的
1 /**
2 * @return
3 * 获取IP前缀
4 */
5
6 private String getLocAddrIndex() {
7 String str = getLocAddress();
8
9 if(!str.equals("")){
10 return str.substring(0,str.lastIndexOf(".")+1);
11 }
12 return null;
13 } 可以看到,这个方法只是将getLocAddress()方法获得的本地IP进行了截取,也就是截取出网段。下来放出如何获取本地IP:
1 public static String getLocAddress() {
2 String ipaddress = "";
3 try {
4 Enumeration<NetworkInterface> en = NetworkInterfaces();
5 // 遍历所用的网络接口
6 while (en.hasMoreElements()) {
7 NetworkInterface networks = en.nextElement();
8 // 得到每一个网络接口绑定的所有ip
9 Enumeration<InetAddress> address = InetAddresses();
10 // 遍历每一个接口绑定的所有ip
11 while (address.hasMoreElements()) {
12 InetAddress ip = Element();
13 if (!ip.isLoopbackAddress()
14 && InetAddressUtils.HostAddress())) {
15 ipaddress = ip.getHostAddress();
16
17 }
18 }
19 }
20 } catch (SocketException e) {
21
22 e.printStackTrace();
23 }
24
25
26 return ipaddress;
27 } 这个方法是百度找的,可以获取到设备的IP但是别忘记权限哦。到这里我们也就获取到了网段地址也就是我们所说的192.168.8
接下来放出线程扫描端口的方法:
1 public class connectionServer extends Thread{
2 private int sERVERPORT;//端口号
3 private String slocAddress;//网段
4 private int sNum;//开始扫描点
5 private int eNum;//结束扫描点
6 public connectionServer(int SERVERPORT, String locAddress,int startNum,int endNum) {
7 sERVERPORT = SERVERPORT;
8 slocAddress = locAddress;
9 sNum = startNum;
10 eNum = endNum;
11
12 }
13
14 @Override
15 public void run() {
16 for(int i = sNum;i < eNum; i ++){
17
18 String current_ip = slocAddress+i;
19 if(Call(current_ip, sERVERPORT)){
20 onSeekIp(current_ip);
21
22 }
23
24 }
25
26 }
27 } 可以看出来是用了一个构造将需要的参数传递进来。然后在run()方法里用for循环进来匹配 ,关于匹配的方法我要说几句,第一次我用的是命令行匹配的方法也就是- p - l 也就是先用了下Window DOS下的ping命令能平通的再尝试和服务器连接。可是后来发现有好多设备无法执行这个命令,比如 鄙人用的小米手机可以,同事的魅族就无法执行了,找来找去发现socket就有一个判断端口是否打开的方法,正式踏破铁屑无觅处,得来全不费工夫啊,各位看官,请看代码:
1 //判断端口是否打开
2 public boolean Call(String ip, int port) {
3
4 try {
5 Socket socket = new Socket();
6 t(new InetSocketAddress(ip, port), 15);
7 socket.close();
8 return true;
9 }catch(Exception e) {
10 return false;
11 }
12
13 } connect这个方法,没错就是这个方法可以判断端口是否打开,后面我用了阻塞连接,timeout设置了15如果连接不上就返回fasle一旦连接上了就返回true,在线程里面可以看到返回true就调用了一个onSeepIP的方法,这个是什么了,其实这个是写了一个供外部访问的接口,已经和这个需求没有多大关系了。另外在附上调取的Demo,如果能帮到大家就再好不过了。
1
2 public void setOnSeekListener(OnSeekIpListener listener){
3 this.listener = listener;
4 }
5
6 private void onSeekIp(String ip){
7 if( listener != null){
8 SeekIp(ip);
9 }
10 }; 这些还是写在这个类里面的,OnSeekIPListener 是从新定义了一个接口类,里面只有一个简单的方法:
1 public interface OnSeekIpListener {
2
3 public void onSeekIp(String ip);
4
5 } 到这里这个可供外部调用的的 寻找服务器IP的需求已经完成了。下来些一个简单的Demo来调用接口:
1 public class MainActivity extends Activity {
2
3 String date ;
4 @Override
5 protected void onCreate(Bundle savedInstanceState) {
6 // TODO Auto-generated method stub
7
8 Create(savedInstanceState);
9 UDPClient udpClient = new UDPClient();
10 udpClient.setOnSeekListener(new UDPSeekListenner());
11 udpClient.scan(6666);
12 }
13
14 class UDPSeekListenner implements OnSeekIpListener {
15
16 @Override
17 public void onSeekIp(String ip) {
18 Log.e("UDP", "demo server_ip:"+ip);
19
20 }
21 }
22 } 至此,所有流程已经完毕,还请各位大大轻喷。
转载于:.html
本文发布于:2024-01-28 17:46:39,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/17064352049160.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
| 留言与评论(共有 0 条评论) |