from: http://wooden-baby.javaeye.com/blog/351912
使用java线程扫描局域网ip简单方案
java 快速扫描局域网 ip 之二级嵌套类
方案一 :
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
public class LanIP {
public ArrayList<String> getLanIPArrayList() {
ArrayList<String> arrayIP = null;
try {
InitSystem initSystem = null;
initSystem = new InitSystem();
Thread thread = new Thread(initSystem);
thread.start();
thread.join();
arrayIP = initSystem.getArrayIPUsed();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return arrayIP;
}
private class InitSystem implements Runnable {
private int firstIP = 2;// 查询的 IP 地址的最后一位起始点
private int lastIP = 255;// 查询的 IP 地址的最后一位结束点
private volatile ArrayList<Thread> arrayThread;// 子线程段
private final int MAXTHREADNUM = 30; // 最大同时进行的子线程数量
private int threadNumNow;// 当前正在进行的子线程数量
private volatile ArrayList<String> arrayIP;// 局域网查询所有可能的 IP 地址的结果集
private volatile ArrayList<String> arrayIPUsed;// 局域网查询已经使用的 IP 地址的结果集
private InitSystem(String ip) {
arrayIP = new ArrayList<String>();
arrayIPUsed = new ArrayList<String>();
arrayThread = new ArrayList<Thread>();
setIPAddressList(ip);
}
private InitSystem() throws UnknownHostException {
this(InetAddress.getLocalHost().getHostAddress());
}
private synchronized ArrayList<String> getArrayIPUsed() {
try {
while (arrayIP.size() > 0) {
Thread.sleep(300);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return arrayIPUsed;
}
private void setIPAddressList(String ip) {
// 根据这个 ip 地址查询它所在的局域网的所有可能 IP 地址的集合
int lastPointIndex = ip.lastIndexOf('.');
String stringIPHead = ip.substring(0, ++lastPointIndex);
String stringIP = null;
for (int i = firstIP; i <= lastIP; i++) {
stringIP = stringIPHead + i;
arrayIP.add(stringIP);
}
}
public void run() {
synchronized (this) {
try {
while (arrayIP.size() > 0) {
while (threadNumNow >= MAXTHREADNUM) {
for (Thread thread : arrayThread) {
if (!thread.getState().equals(
Thread.State.TERMINATED)) {
thread.join(5);
}
--threadNumNow;
}
arrayThread = new ArrayList<Thread>();
}
Thread thread = new Thread(new InnerClass(arrayIP
.remove(0)));
thread.start();
threadNumNow++;
arrayThread.add(thread);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private class InnerClass implements Runnable {
// 线程查询一个 IP 是否是可以连接的 是则加入到相应的 IP 数组
private String ip;
private InnerClass(String ip) {
this.ip = ip;
}
private boolean isUsedIPAddress(String ip) {
synchronized (this) {
// 判断这个 IP 地址在当前局域网中是否是可连接的 IP
Process process = null;
BufferedReader bufReader = null;
String bufReadLineString = null;
try {
process = Runtime.getRuntime().exec(
"ping " + ip + " -w 100 -n 1");
bufReader = new BufferedReader(new InputStreamReader(
process.getInputStream()));
for (int i = 0; i < 6 && bufReader != null; i++) {
bufReader.readLine();
}
bufReadLineString = bufReader.readLine();
if (bufReadLineString == null) {
process.destroy();
return false;
}
if (bufReadLineString.indexOf("timed out") > 0
|| bufReadLineString.length() < 17
|| bufReadLineString.indexOf("invalid") > 0) {
process.destroy();
return false;
}
} catch (IOException e) {
e.printStackTrace();
}
process.destroy();
return true;
}
}
public void run() {
synchronized (this) {
if (isUsedIPAddress(ip)) {
arrayIPUsed.add(ip);
}
}
}
}
}
}
方案二 :
方案二与方案一只有一点是不一样的,就是在与下面这个相关的代码,采用的是队列而不是数组
将 private volatile ArrayList<Thread> arrayThread;// 子线程段
改为: private volatile ArrayBlockingQueue<Thread> queueThread;// 子线程队列
当然,其他相关的地方的处理也要做些修改.
注!!!!
在 linux下运行发现InetAddress.getLocalHost().getHostAddress();的返回值是127.0.0.1,这个与 windows下的返回值不一样。由于jdk在win和linux下这个方法的差异,这个程序在linux下不能如预期的那样工作,需要做一些技术上的改进。
---------------------------------------------------------------------------------------------------------------------------
摘要
想必大家对小榕时光等扫描器都非常熟悉了,有没有自己写一个的冲动。最近微软推实施了.NET战略方案,C#是主推语言,你们是否有兴趣用C#来实现对局域网IP地址的扫描,尝试一下自己写的快乐,那么请跟我来。
--------------------------------------------------------------------------------
目录
1.使用的类
2.获取本地主机IP地址
3.远程查询
4.实现网段的扫描
--------------------------------------------------------------------------------
正文
1.先介绍一下使用的类:
DNS类:在.net中的System.net命名空间下,主要的功能是从 Internet 域名系统 (DNS) 检索关于特定主机的信息。
IPHostEntry类:将一个域名系统 (DNS) 主机与一组别名和一组匹配的 IP 地址关联,和DNS类一起使用。
IPAddress 类:IP 网络上的地址。
使用的命名空间有:
System.Net 命名空间为当前网络上使用的多种协议提供了简单的编程接口.
System.IO命名空间包含允许在数据流和文件上进行同步和异步读取及写入的类型。
System.Thread 命名空间主要是用来多线程序编程。
程序实现以下几个功能:
2.获取本地主机IP地址
//对Button控件的事件的响应
private void buttion1_click(object sender,System.Event.Args e)
{
IPHostEntry myHost = new IPHostEntry();
Try
{
// Dns.GetHostName()获取本地计算机的主机名
// Dns.GetHostByName()获取指定 DNS 主机名的 DNS 信息
//得到本地主机的DNS信息
myHost = Dns.GetHostByName(Dns.GetHostName());
//显示本地主机名
textBox1.Text = myHost.HostName.ToString();
//显示本地主机的IP地址表
for(int i=0; i <myHost.AddressList.length;i++)
{
richTextBox1.AppendText(“本地主机IP地址-> ”+myHost.AddressList[i].ToString()+”/r”);
}
catch(Exception error)
{
MessageBox.Show(error.Message);
}
}//private
3.远程查询
private void buttion2_click(object Sender,System.EventArgs e)
{
IPHostEntry myDnsToIP = new IPHostEntry();
//Dns.Resolve 方法: 将 DNS 主机名或以点分隔的四部分表示法格式的 // IP 地址解析为 IPHostEntry实例
myDnsToIP =Dns.Resolve(textBox2.Text.ToString());
//显示此域名的IP地址的列表
for(int i=0;i <myDnsToIPAddressList.Length;i++)
{
rich.TextBox1.AppendText(textBox2.Text+”的IP地址是”+myDnsToIP.AddressList[i].ToString()+”/r”);
}
}
4.实现网段的扫描
实现网段的扫描,确定网络中正在使用的主机数目。这里使用了多线程技术,增加了一个线程,为了防止程序扫描的时间过长,影响程序的响应。不过在.net中由于使用了垃圾收集技术所以对线程的控制也不是很复杂的。
private void button3_click(object sender, System.EventArgs e)
{
//Thread 类: 创建并控制线程
Thread thScan = new thread(new ThreadStrart(ScanTarget));
//Thread.Start 方法:启动线程
thScan.Strart();
}
private void ScanTarget()
{
//构造IP地址的31-8BIT 位,也就是固定的IP地址的前段
// numericUpDown1是定义的System.Windows.Forms.NumericUpDown控件
string strIPAddress=numericUpDown1.Text+”.”+numericUpDown2.Text+”.”+numericUpDown3.Text+”.”;
//开始扫描地址
int nStrat = Int32.Parse(numericUpDown4.Text);
//终止扫描地址
int nEnd =Int32.Parse(numericUpDown5.Text);
//扫描的操作
for(int i=nStrat;i <=nEnd;i++)
{
string strScanIPAdd = strIPAddress +i.ToString();
//转换成IP地址
IPAddress myScanIP = IPAddress.Parse(strScanIPAdd);
try
{
//你可以加入自已的,增强功能
// Dns.GetHostByAddress 方法: 根据 IP 地
//址获取 DNS 主机信息。
IPHostEntry myScanHost =
Dns.GetHostByAddress(myScanIP);
//获取主机的名
string strHostName =myScanHost.HostName.ToString();
richTextBox1.AppendText(strScanIPAdd+”-> ”+strHostName+”/r”);
}
catch(Exception error)
{
MessageBox.Show(error.Message);
}
}//for
}//private
到此为止一个简单用C#实现扫描器的主要功能就完成了,试一下你可以看到你的网络上的主机,有没有成就感了
这是c#java把类换了,我想也是一样的
----------------------------------------------------------------------------------------------------------------------
自己写的局域网端口扫描程序
这是我自己写的端口扫描程序,不过有2点失误的地方,第一只能扫描自己的端口,如果是另一个IP,却扫描不出来,我发帖子问了,都没人回答.
第二,扫描的速度特别慢,所以最好从自己的IP开始扫描,而且有的端口第一次扫描出现,第二次没有出现,不知道为什么,希望有人解答.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.net.*;
public class SuperScaner extends JFrame
{
public static JTextField sjtf1,sjtf2,sjtf3,sjtf4,ejtf1,ejtf2,ejtf3,ejtf4,threadjtf;
public static JLabel sjl1,sjl2,sjl3,jl4,jl,ejl1,ejl2,ejl3,threadjl,areajl,resultjl;
public static JTextArea jta;
public JPanel jp1,jp2,jp3,jp4,jp;
public JScrollPane jsp;
public static JButton Sbutton,jb2;
public SuperScaner()
{
Container c=getContentPane();
sjtf1=new JTextField(4);sjtf2=new JTextField(4);sjtf3=new JTextField(4);sjtf4=new JTextField(4);
ejtf1=new JTextField(4);ejtf2=new JTextField(4);ejtf3=new JTextField(4);ejtf4=new JTextField(4);
threadjtf=new JTextField(7);
jl=new JLabel(" IP地址:");sjl1=new JLabel(".");sjl2=new JLabel(".");sjl3=new JLabel(".");
jl4=new JLabel("~");threadjl=new JLabel("线程数(1~100):");
areajl=new JLabel("扫描结果:");
ejl1=new JLabel(".");ejl2=new JLabel(".");ejl3=new JLabel(".");resultjl=new JLabel();
resultjl.setLayout(new FlowLayout(FlowLayout.LEFT));
jta=new JTextArea(15,65);
jsp=new JScrollPane(jta);
Sbutton=new JButton("确定");
jb2=new JButton("取消");
jp1=new JPanel();
jp1.setLayout(new FlowLayout(FlowLayout.LEFT));
jp2=new JPanel();
jp2.setLayout(new FlowLayout(FlowLayout.LEFT));
jp3=new JPanel();
jp3.setLayout(new BorderLayout());
jp4=new JPanel();
jp4.setLayout(new FlowLayout(FlowLayout.RIGHT));
jp1.add(jl);jp1.add(sjtf1);jp1.add(sjl1);jp1.add(sjtf2);jp1.add(sjl2);jp1.add(sjtf3);jp1.add(sjl3);jp1.add(sjtf4);
jp1.add(jl4);jp1.add(ejtf1);jp1.add(ejl1);jp1.add(ejtf2);jp1.add(ejl2);jp1.add(ejtf3);jp1.add(ejl3);jp1.add(ejtf4);
jp1.add(threadjl);jp1.add(threadjtf);
jp2.add(areajl);jp2.add(jsp);
jp3.add(resultjl,BorderLayout.CENTER);jp4.add(Sbutton);jp4.add(jb2);
jp3.add(jp4,BorderLayout.EAST);
c.add(jp1,BorderLayout.NORTH);
c.add(jp2,BorderLayout.CENTER);
c.add(jp3,BorderLayout.SOUTH);
setSize(740,400);
setResizable(false);
jta.setEditable(false);
setLocation(400,300);
show();
addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
Sbutton.addActionListener(new Sbutton());
}
public static void main(String args[])
{
new SuperScaner();
}
};
class ThreadScaner implements Runnable
{
public static InetAddress address;
public static int min,max;
private int i;
Object obj = new Object();
public Sbutton s;
public ThreadScaner(Sbutton s)
{
this.s=s;
}
public void run()
{
Socket theTCPsocket;
//SuperScaner.jta.append(address.getHostName()+" , "+address.getHostAddress()+"/n");
for(i=1;i<2000;i++)
{
SuperScaner.resultjl.setText("扫描状态:正在扫描 "+ i +" 端口"+"/n");
try
{
theTCPsocket=new Socket(address,i);
theTCPsocket.close();
SuperScaner.jta.append(" "+i);
switch(i)
{
case 21:
SuperScaner.jta.append("(FTP)");
break;
case 23:
SuperScaner.jta.append("(TELNET)");
break;
case 25:
SuperScaner.jta.append("(SMTP)");
break;
case 80:
SuperScaner.jta.append("(HTTP)");
break;
case 110:
SuperScaner.jta.append("(POP3)");
break;
case 135:
SuperScaner.jta.append("(Remote Procedure Call服务)");
break;
case 139:
SuperScaner.jta.append("(netBIOS)");
break;
case 2000:
SuperScaner.jta.append("(木马默认端口)");
break;
case 3389:
SuperScaner.jta.append("(Win2000 远程登陆端口)");
break;
case 4000:
SuperScaner.jta.append("(OICQ)");
break;
case 6667:
SuperScaner.jta.append("(IRC)");
break;
}
SuperScaner.jta.append("/n");
}
catch (Exception e)
{
}
}
if(i==2000){SuperScaner.jta.append("扫描完成/n");SuperScaner.resultjl.setText(ThreadScaner.address.getHostName()+"扫描状态:完成!/n");Sbutton.is4++;s.caclu();}
}
};
class Sbutton implements ActionListener
{
public static int is1,is2,is3,is4,ie1,ie2,ie3,ie4,threadnum;
ThreadScaner ts=new ThreadScaner(this);
public int i;
byte b[]=new byte[4];
public void actionPerformed(ActionEvent e)
{
if(SuperScaner.sjtf1.getText().length()!=0&&SuperScaner.sjtf2.getText().length()!=0&&SuperScaner.sjtf3.getText().length()!=0&&SuperScaner.sjtf4.getText().length()!=0)
{
is1=Integer.parseInt(SuperScaner.sjtf1.getText());is2=Integer.parseInt(SuperScaner.sjtf2.getText());is3=Integer.parseInt(SuperScaner.sjtf3.getText());is4=Integer.parseInt(SuperScaner.sjtf4.getText());
ie1=Integer.parseInt(SuperScaner.ejtf1.getText());ie2=Integer.parseInt(SuperScaner.ejtf2.getText());ie3=Integer.parseInt(SuperScaner.ejtf3.getText());ie4=Integer.parseInt(SuperScaner.ejtf4.getText());
threadnum=Integer.parseInt(SuperScaner.threadjtf.getText());
if(is1>=0 && is1<=255&&is2>=0&&is2<=255&&is3>=0&&is3<=255&&is4>=0&&is4<=255)
{
if(is1==ie1&&is2==ie2&&is3==ie3&&is4<ie4)
{
ThreadScaner.min=is4;ThreadScaner.max=ie4;
}
}
else JOptionPane.showMessageDialog(null,"数值超出范围","错误提示",JOptionPane.ERROR_MESSAGE);
SuperScaner.jta.setText("");
caclu();
}
else JOptionPane.showMessageDialog(null,"没有输入数据","错误提示",JOptionPane.ERROR_MESSAGE);
}
public void caclu()
{
int count=0;
try
{
if(is4<=ie4){System.out.println(""+is4);
b[0]=(byte)is1;b[1]=(byte)is2;b[2]=(byte)is3;b[3]=(byte)is4;
ThreadScaner.address=InetAddress.getByAddress(b);
SuperScaner.jta.append(ThreadScaner.address.getHostName()+" , "+ThreadScaner.address.getHostAddress()+"/n");
if(ThreadScaner.address.getHostName().equals(ThreadScaner.address.getHostAddress())){SuperScaner.jta.append("这个IP可能没人用!/n");is4++;caclu();}
else{
SuperScaner.jta.append("正在扫描 "+ThreadScaner.address.getHostName()+" 请稍等/n");
SuperScaner.jta.append("开放端口: /n");
while(count<threadnum){new Thread(ts).start();count++;}}
}
else {SuperScaner.jta.append("扫描完成!/n");SuperScaner.resultjl.setText("扫描状态:完成!");}
}
catch (Exception ex)
{
ex.getMessage();
}
}
};