资源描述
网络综合实验
任 务 书
一、 目的与要求
1. 性质:设计性实验。
2. 任务:设计并实现一个端口扫描程序,检测某个IP或某段IP的计算机的端口工作情况。
3. 目的:加深对课堂讲授知识的理解,熟练掌握基本的网络编程技术和方法,建立网络编程整体概念,使得学生初步具有研究、设计、编制和调试网络程序的能力。
4. 要求:熟悉有关定义、概念和实现算法,设计出程序流程框图和数据结构,编写出完整的源程序,基本功能完善,方便易用,操作无误。
5. 学生要求人数:1人。
二、 主要内容
1. 编写一个端口扫描程序,能够显示某个IP或某段IP的计算机的某一个或某些端口是否正在工作。基本工作过程如下:
(1) 设定好一定的端口扫描范围;
(2) 设定每个端口扫描的次数,因为有可能有的端口一次扫描可能不通;
(3) 创建socket,通过socket的connect方法来连接远程IP地址以及对应的端口;
(4) 如果返回false,表示端口没有开放,否则端口开放。
三、 进度计划
序号
设计内容
完成时间
备注
1
任务布置及资料收集
第1周周一、周二
2
软件方案设计与制定
第1周周三至周四
3
编程实现
第1周周周五至第2周周二
4
程序测试与修改,撰写报告
第2周周三至周五上午
5
报告提交,软件验收
周五下午
四、设计成果要求
1. 完成规定的实验任务,保质保量;
2. 完成综合实验报告,要求格式规范,内容具体而翔实,应体现自身所做的工作,注重对实验思路的归纳和对问题解决过程的总结。
五、 考核方式
1. 平时成绩+验收答辩+实验报告;
2. 五级分制。
学生姓名:
指导教师:
2009 年 6月8 日
一、综合实验的目的与要求
1.目的:加深对课堂讲授知识的理解,熟练掌握基本的网络编程技术和方法,建立网络编程整体概念,加深对JAVA编程语言的使用,促进编程能力的提高,同时为网络编程打下一个比较好的基础。同时对实验的过程要有完全的了解。
2. 要求:熟悉有关定义、概念和实现算法,设计出程序流程框图和数据结构,编写出完整的源程序,基本功能完善,方便易用,操作无误。
二、综合实验正文
1.编程语言的选择
针对编写的是端口扫描的程序,所以我选择了JAVA编程,因为要简单而方便的试验端口扫描的功能。
2.端口扫描实现的功能是:显示某个IP或某段IP的计算机的某一个或某些端口是否正在工作
2.1 如何选择IP段和端口
创建socket,通过socket的connect方法来连接远程IP地址以及对应的端口。而我使用的是socket函数来实现端口的扫描和IP地址的选择扫描。
2.2 如何实现快速扫描端口
通过实现多线程,当一个IP或者一个端口同时分配多个线程进行扫描,速度会比单线程扫描快许多。
2.3 显示扫描结果
可以在使用JAVA编写的时候,可以通过使用JScrollPane控件实现显示结果。
2.4 实现要求功能之余美化外观
3.创建应用程序界面
3.1 建立主窗体 ,“JAVA端口扫描器”
图1-1
3.2 IP地址的输入部分
图1-2
3.3 端口部分,其中包括指定的端口和指定扫描的端口范围
图1-3
3.4 多线程的实现和延时的控制部分
图1-4
3.5 增加的保存及快捷键功能
图1-5
4.扫描的整个过程
4.1 填写IP地址 192.168.1.100—192.168.1.120
4.2 填写端口扫描的范围为1—300
4.3 线程数选择为100
4.4 扫描结果如下
图1-6
三.端口扫描的主要部分程序如下
import .*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/*
*实现扫描的主体程序
*/
public class ThreadScan{
public static JFrame main=new JFrame("JAVA端口扫描器");
//显示扫描结果
public static JTextArea Result=new JTextArea("",4,40);
//滚动条面板
public static JScroll PaneresultPane = newJScrollPane(Result,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED;
//输入主机名文本框
public static JTextField hostname=new JTextField("localhost",8);
//输入ip地址前3位的输入框
public static JTextField fromip1=new JTextField("0",3);
//输入ip地址4~6位的输入框
public static JTextField fromip2=new JTextField("0",3);
//输入ip地址7~9位的输入框
public static JTextField fromip3=new JTextField("0",3);
//输入起始ip地址最后4位的输入框
public static JTextField fromip4=new JTextField("0",3);
//输入目标ip地址最后4位的输入框
public static JTextField toip=new JTextField("0",3);
//输入最小端口的输入框
public static JTextField minPort=new JTextField("0",4);
//输入最大端口的输入框
public static JTextField maxPort=new JTextField("1000",4);
//输入最大线程数量的输入框
public static JTextField maxThread=new JTextField("100",3);
//错误提示框
public static JDialog DLGError=new JDialog(main,"错误!");
public static JLabel DLGINFO=new JLabel("");
public static JLabel type=new JLabel("请选择:");
//扫描类型
public static JRadioButton radioIp = new JRadioButton("IP地址:");
public static JRadioButton radioHost = new JRadioButton("主机名:",true);
//单选框组
public static ButtonGroup group = new ButtonGroup();
public static JLabel P1=new JLabel("端口范围:");
public static JLabel P2=new JLabel("~");
public static JLabel P3=new JLabel("~");
public static JLabel Pdot1 = new JLabel(".");
public static JLabel Pdot2 = new JLabel(".");
public static JLabel Pdot3 = new JLabel(".");
public static JLabel TNUM=new JLabel("线程数:");
public static JLabel RST=new JLabel("扫描结果: ");
public static JLabel con=new JLabel(" ");
//定义按钮
public static JButton OK = new JButton("确定");
public static JButton Submit = new JButton("开始扫描");
public static JButton Cancel = new JButton("退出");
public static JButton saveButton = new JButton("保存扫描结果");
//菜单栏
public static JMenuBar myBar = new JMenuBar();
public static JMenu myMenu = new JMenu("文件(F)");
public static JMenuItem saveItem = new JMenuItem("保存扫描结果(S)");
public static JMenuItem exitItem = new JMenuItem("退出(Q)");
public static void main(String[] args){
main.setSize(500,400);
main.setLocation(300,300);
main.setResizable(false);
main.setLayout(new GridBagLayout());
main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DLGError.setSize(300,100);
DLGError.setLocation(400,400);
//添加“菜单栏”
myMenu.add(saveItem);
myMenu.add(exitItem);
myBar.add(myMenu);
main.setJMenuBar(myBar);
//设置热键
myMenu.setMnemonic('F');
saveItem.setMnemonic ('S');
//为“另存为”组件设置快捷键为ctrl+s
saveItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,InputEvent.CTRL_MASK));
exitItem.setMnemonic('Q');
exitItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E,InputEvent.CTRL_MASK));
//采用表格包型布局
Container mPanel = main.getContentPane();
GridBagConstraints c = new GridBagConstraints();
c.insets = new Insets(10,0,0,10);
c.gridx = 0;
c.gridy = 0;
c.gridwidth = 10;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
mPanel.add(type,c);
group.add(radioIp);
group.add(radioHost);
c.gridx = 0;
c.gridy = 1;
c.gridwidth = 1;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
mPanel.add(radioIp,c);
c.gridx = 1;
c.gridy = 1;
c.gridwidth = 1;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
mPanel.add(fromip1,c);
c.gridx = 2;
c.gridy = 1;
c.gridwidth = 1;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
mPanel.add(Pdot1,c);
c.gridx = 3;
c.gridy = 1;
c.gridwidth = 1;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
mPanel.add(fromip2,c);
c.gridx = 4;
c.gridy = 1;
c.gridwidth = 1;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
mPanel.add(Pdot2,c);
c.gridx = 5;
c.gridy = 1;
c.gridwidth = 1;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
mPanel.add(fromip3,c);
c.gridx = 6;
c.gridy = 1;
c.gridwidth = 1;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
mPanel.add(Pdot3,c);
c.gridx = 7;
c.gridy = 1;
c.gridwidth = 1;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
mPanel.add(fromip4,c);
c.gridx = 8;
c.gridy = 1;
c.gridwidth = 1;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
mPanel.add(P2,c);
c.gridx = 9;
c.gridy = 1;
c.gridwidth = 1;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
mPanel.add(toip,c);
c.gridx = 0;
c.gridy = 2;
c.gridwidth = 1;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
mPanel.add(radioHost,c);
c.gridx = 1;
c.gridy = 2;
c.gridwidth = 3;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
mPanel.add(hostname,c);
c.gridx = 0;
c.gridy = 3;
c.gridwidth = 1;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
mPanel.add(P1,c);
c.gridx = 1;
c.gridy = 3;
c.gridwidth = 1;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
mPanel.add(minPort,c);
c.gridx = 2;
c.gridy = 3;
c.gridwidth = 1;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
mPanel.add(P3,c);
c.gridx = 3;
c.gridy = 3;
c.gridwidth = 1;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
mPanel.add(maxPort,c);
c.gridx = 0;
c.gridy = 4;
c.gridwidth = 1;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
mPanel.add(TNUM,c);
c.gridx = 1;
c.gridy = 4;
c.gridwidth = 3;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
mPanel.add(maxThread,c);
c.gridx = 0;
c.gridy = 5;
c.gridwidth = 3;
c.fill = GridBagConstraints.VERTICAL;
c.anchor = GridBagConstraints.CENTER;
mPanel.add(Submit,c);
c.gridx = 6;
c.gridy = 5;
c.gridwidth = 4;
c.fill = GridBagConstraints.VERTICAL;
c.anchor = GridBagConstraints.CENTER;
mPanel.add(Cancel,c);
c.gridx = 0;
c.gridy = 6;
c.gridwidth = 10;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
mPanel.add(RST,c);
//设置文本区域可以换行
Result.setLineWrap(true);
//设置文本区域不可编辑
Result.setEditable(false);
c.gridx = 0;
c.gridy = 7;
c.gridwidth = 10;
c.gridheight = 4;
c.fill = GridBagConstraints.VERTICAL;
c.anchor = GridBagConstraints.CENTER;
mPanel.add(resultPane,c);
Container dPanel = DLGError.getContentPane();
dPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
dPanel.add(DLGINFO);
dPanel.add(OK);
Submit.addActionListener(new SubmitAction());
Cancel.addActionListener(new CancleAction());
OK.addActionListener(new OKAction());
//实现退出功能
exitItem.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
System.exit(0);
}
});
//实现帮助功能
saveButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
JFileChooser fc=new JFileChooser();
int returnVal=fc.showSaveDialog(null);
//点击“保存”
if(returnVal == 0){
File saveFile=fc.getSelectedFile();
try {
FileWriter writeOut = new FileWriter(saveFile);
writeOut.write(ThreadScan.Result.getText());
writeOut.close();
}
catch (IOException ex) {
System.out.println("保存失败");
}
}
//点击“取消”
else
return;
}
});
main.setVisible(true);
}
}
/*
*实现“取消”功能
*退出程序
*/
class CancleAction implements ActionListener{
public void actionPerformed (ActionEvent e){
System.exit(0);
}
}
/*
*实现“确定”功能
*完成扫描
*/
class SubmitAction implements ActionListener{
public void actionPerformed (ActionEvent a){
int minPort;
int maxPort;
int maxThread;
int ip1 = 0;
int ip2 = 0;
int ip3 = 0;
int ipstart = 0;
int ipend = 0;
String ipaddress = "";
String hostname = "";
ThreadScan.Result.setText("");
//将"确定"按钮设置成为不可用
if(ThreadScan.Submit.isEnabled()){
ThreadScan.Submit.setEnabled(false);
}
/*
*判断搜索的类型
*按照ip地址扫描:type = 0
*按照主机名称扫描:type = 1
*/
if(ThreadScan.radioIp.isSelected()){
TCPThread.type = 0;
//判断ip的前3位是否为int型
try{
ip1=Integer.parseInt(ThreadScan.fromip1.getText());
}
catch(NumberFormatException e){
ThreadScan.DLGINFO.setText("错误的ip!");
ThreadScan.DLGError.setVisible(true);
return;
}
//判断ip的4~6位是否为int型
try{
ip2=Integer.parseInt(ThreadScan.fromip2.getText());
}
catch(NumberFormatException e){
ThreadScan.DLGINFO.setText("错误的ip!");
ThreadScan.DLGError.setVisible(true);
return;
}
//判断ip的7~9位是否为int型
try{
ip3=Integer.parseInt(ThreadScan.fromip3.getText());
}
catch(NumberFormatException e){
ThreadScan.DLGINFO.setText("错误的ip!");
ThreadScan.DLGError.setVisible(true);
return;
}
//判断起始ip的最后4位是否为int型
try{
ipstart=Integer.parseInt(ThreadScan.fromip4.getText());
}
catch(NumberFormatException e){
ThreadScan.DLGINFO.setText("错误的ip!");
ThreadScan.DLGError.setVisible(true);
return;
}
//判断目标ip的最后4位是否为int型
try{
ipend=Integer.parseInt(ThreadScan.toip.getText());
}
catch(NumberFormatException e){
ThreadScan.DLGINFO.setText("错误的目标ip!");
ThreadScan.DLGError.setVisible(true);
return;
}
//判断起始ip是否正确
//判断条件:大于0且小于等于255
if(ip1<0 || ip1>255||ip2<0 || ip2>255||ip3<0 || ip3>255||ipstart<0 || ipstart>255){
ThreadScan.DLGINFO.setText(" ip地址为0-255的整数! ");
ThreadScan.DLGError.setVisible(true);
return;
}
else{
TCPThread.ip1 = ip1;
TCPThread.ip2 = ip2;
TCPThread.ip3 = ip3;
TCPThread.ipstart = ipstart;
}
//判断目标ip是否正确
//判断条件:大于0且小于等于255
if(ipend<0 || ipend>255){
ThreadScan.DLGINFO.setText("目标ip地址为0-255的整数! ");
ThreadScan.DLGError.setVisible(true);
return;
}
else{
TCPThread.ipend = ipend;
}
ipaddress = "" + ip1 + ip2 + ip3 + ipstart;
/*
*判断ip地址的有效性
*/
try{
TCPThread.hostAddress=InetAddress.getByName(ipaddress);
}
catch(UnknownHostException e){
ThreadScan.DLGINFO.setText(" 错误的IP或地址不可达! ");
ThreadScan.DLGError.setVisible(true);
return;
}
}
//根据主机名进行端口扫描
if(ThreadScan.radioHost.isSelected()){
TCPThread.type = 1;
/*
*判断主机名称的有效性
*/
try{
TCPThread.hostAddress=InetAddress.getByName(ThreadScan.hostname.getText());
}
catch(UnknownHostException e){
ThreadScan.DLGINFO.setText("错误的域名或地址不可达! ");
ThreadScan.DLGError.setVisible(true);
return;
}
}
/*
*判断端口号的有效性
*/
try{
minPort=Integer.parseInt(ThreadScan.minPort.getText());
maxPort=Integer.parseInt(ThreadScan.maxPort.getText());
maxThread=Integer.parseInt(ThreadScan.maxThread.getText());
}
catch(NumberFormatException e){
ThreadScan.DLGINFO.setText("错误的端口号或线程数!端口号和线程数必须为整数!");
ThreadScan.DLGError.setVisible(true);
return;
}
/*
*判断最小端口号的有效范围
*判断条件:大于0且小于65535,最大端口应大于最小端口
*/
if(minPort<0 || minPort>65535 || minPort>maxPort){
ThreadScan.DLGINFO.setText("最小端口必须是0-65535并且小于最大端口的整数!");
ThreadScan.DLGError.setVisible(true);
return;
}
else{
TCPThread.MIN_port=minPort;
}
/*
*判断最大端口号的有效范围
*判断条件:大于0且小于65535,最大端口应大于最小端口
*/
if(maxPort<0 || maxPort>65535 || maxPort<minPort){
ThreadScan.DLGINFO.setText("最大端口必须是0-65535并且大于最小端口的整数!");
ThreadScan.DLGError.setVisible(true);
return;
}
else{
TCPThread.MAX_port=maxPort;
}
/*
*判断线程数量的有效范围
*判断条件:大于1且小于200
*/
if(maxThread<1 || maxThread>200){
ThreadScan.DLGINFO.setText("线程数为1-200的整数! ");
ThreadScan.DLGError.setVisible(true);
return;
}
ThreadScan.Result.append("线程数 "+ThreadScan.maxThread.getText()+"\n");
//启动线程
for(int i=0;i<maxThread;i++){
new TCPThread("T" + i,i).start();
}
}
}
/*
*实现错误提示框中的“确定”按钮功能
*/
class OKAction implements ActionListener{
public void actionPerformed (ActionEvent e){
ThreadScan.DLGError.dispose();
}
}
多线程类文件:
import .*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TCPThread extends Thread{
public st
展开阅读全文