标签:android style blog io ar color os 使用 sp
简要说明
本人才接触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 threadPoolExecutor.execute( new connectionServer(SERVERPORT, locAddress,0,100)); 7 threadPoolExecutor.execute( new connectionServer(SERVERPORT, locAddress,101,200)); 8 threadPoolExecutor.execute( 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 = NetworkInterface.getNetworkInterfaces(); 5 // 遍历所用的网络接口 6 while (en.hasMoreElements()) { 7 NetworkInterface networks = en.nextElement(); 8 // 得到每一个网络接口绑定的所有ip 9 Enumeration<InetAddress> address = networks.getInetAddresses(); 10 // 遍历每一个接口绑定的所有ip 11 while (address.hasMoreElements()) { 12 InetAddress ip = address.nextElement(); 13 if (!ip.isLoopbackAddress() 14 && InetAddressUtils.isIPv4Address(ip.getHostAddress())) { 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 socket.connect(new InetSocketAddress(ip, port), 15); 7 socket.close(); 8 return true; 9 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 listener.onSeekIp(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 super.onCreate(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 }
至此,所有流程已经完毕,还请各位大大轻喷。
标签:android style blog io ar color os 使用 sp
原文地址:http://www.cnblogs.com/yishuifenglan/p/4164273.html