java实现端口扫描设计UI界面

一、前言

1.实验目的
参照superscan等端口扫描软件的运行情况,自行设计一个简单的端口扫描软件。能够根据TCP、IMCP等探测方法,设计程序对IP地址(单个IP,一段IP范围)、指定主机名的端口(部分端口,所有端口)进行扫描,以获得相关的信息。要求多线程技术实现;扫描过程中能显示扫描时间;图形化界面;异常告警窗口(如IP地址范围出界等)。
2.实验环境
电脑需要安装java虚拟机(JDK7或者JDK8),使用eclipse软件运行java程序,实现端口扫描。
3.安装说明
安装好JDK8以后,打开eclipse,新建一个package“a_scan_own”,新建一个类“OwnTCPScan”,将代码拷贝进去,并将passwd.txt文件放入“a_scan_own”内。
请注意,该代码内包含密码文件读写操作,因此需要修改OwnTCPScan.java文件的500行与1043行的代码,将“E:\grade_3\grade_3_code\first_semester\JavaGrade3\src\”改为该package所在的位置,即可运行。
4.操作系统版本
Windows8、Windows10的32位、64位均可以运行本代码。

二、系统分析

2.1 基本要求
本课题的基本要求如下:

  1. 该端口扫描程序可以对IP地址进行扫描,可以扫描单个IP地址和一段范围内的IP地址;
  2. 该端口扫描程序可以对指定主机名的端口进行扫描,可以扫描部分端口或者所有端口;
  3. 采用多线程技术,可以由用户控制同时运行的线程数;
  4. 可以显示扫描时间和异常警告窗口(当用户输入不合法的信息时,给予提示);
  5. 实现图形化界面,界面友好、美观、可用性强。
    2.2 实验内容
    本课题实现了所有的基本要求,并附加了一部分功能,以提高用户的使用舒适度。用户使用该端口扫描设计软件的过程如下:
    用户输入用户名与密码进入主界面;
    用户可在主界面进行扫描操作和文件操作;
    扫描操作下,用户需要选择扫描方式,包括“根据IP地址扫描”和“根据主机名与端口号扫描”。其中,“根据IP地址扫描”的选项下包括“单个IP地址”和“一段IP地址”;“根据主机名与端口号扫描”的选项下包括“常用端口”和“部分端口”。用户可以点击“查看”按钮查看常用端口,也可以选择“部分端口”,输入端口范围进行扫描。
    扫描方式选择完成后,用户需要输入线程数。之后,点击“开始扫描”,扫描结果与扫描时间会自动显示在扫描结果显示框内。若点击“退出”,系统会弹出“确认退出吗?”的对话框以提醒用户。若点击“清空”,则会自动清空界面[1]。
    文件操作下,用户可以选择“修改密码”、“保存扫描结果”和“退出”。若点击“修改密码”,则会提示用户修改登录密码,保存密码的文件在该package目录下,打开之后,可以见到输入密码的密文形式。若点击“保存扫描结果”,用户可以自行选择将扫描结果保存在哪个目录下。若点击“退出”,系统会弹出“确认退出吗?”的对话框以提醒用户。
    用户使用端口扫描软件的流程图

三、代码关键点

IP地址的多线程扫描
IP地址扫描采用多线程技术,以用户输入的IP地址和线程数为参数采用多线程的方式扫描IP地址,调用PingTester类实现IP地址扫描,PingTester类包含3个部分:构造函数、startPing函数、内部类PingRunner。
1.构造函数
构造函数PingTester(int fromip1,int fromip2,int fromip3,int fromip4,int toip3,int toip4),用于传递用户输入的参数起始IP地址,并生成包含所有的IP地址的LinkedList,对象名为allIP。具体代码出现在OwnTCPScan.java文件的905~921行。
2.startPing函数
startPing函数用于创建一个线程池[5],使用ExecutorService类的对象进行多线程异步执行。startPing方法中声明了ExecutorService类的executor对象,并调用了该对象的executor方法,以异步的方式调用PingRunner类,执行多线程。具体代码出现在OwnTCPScan.java文件的922~943行。
3.PingRunner类
内部类PingRunner用于扫描IP地址并输出IP地址的可达性信息。PingRunner以Runnable类为接口,实现抽象方法run(),调用InetAddress类的isReachable()函数,判断该IP地址是否可达,若可达,则将结果添加到最终的扫描结果;若不可达,则不做任何操作。具体代码出现在OwnTCPScan.java文件的945~981行。

端口号的多线程扫描
根据主机和端口号的扫描采用多线程技术,以用户输入的主机名、线程数与端口范围为参数进行多线程扫描,调用scanPorts函数传递参数,scanPorts函数调用ScanMethod类实现端口的扫描。主要分为3个部分:scanPorts函数、ScanMethod类的构造函数、ScanMethod类的run函数。
1.scanPorts函数
scanPorts函数的形参包括主机名、端口范围、线程数、超时时间。scanPorts函数用于创建一个线程池,使用ExecutorService类的对象进行多线程异步执行。scanPorts函数中声明了ExecutorService类的threadPool对象,并调用了该对象的executor方法,以异步的方式调用ScanMethod类,执行多线程。具体代码出现在OwnTCPScan.java文件的818~839行。
2.ScanMethod类的构造函数
ScanMethod类同样拥有Runnable类的接口,其构造函数较为简单,仅实现传参作用。传递的参数包括主机名(或者主机IP地址)、待扫描的端口、线程数、超时时间。超时时间设置为0.8s。具体代码出现在OwnTCPScan.java文件的858~864行。
3.ScanMethod类的run函数
因为ScanMethod类拥有Runnable类的接口,因此必须实现抽象函数run()。通过主机IP地址和端口号,实例化SocketAddress类的对象socketAddress,建立套接字之后,再调用Socket类的connect函数,判断在规定的超时时间内能否连接上该端口。具体代码出现在OwnTCPScan.java文件的865~895行。

四、界面展示

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

运行说明

代码比较长,1000+。用户名为admin,密码为123456。password.txt中存放的是密码密文,而非登录密码的明文。初始内容是ADKIy3,只需要放在项目OwnTCPScan.java同级目录下。

五、完整代码


```java

@SuppressWarnings("serial")
public class OwnTCPScan extends JFrame implements ActionListener{

	JPanel panel1;
	//扫描类型
	JLabel choiceTip=new JLabel("请选择扫描方式:");
	protected static JRadioButton radioIp = new JRadioButton("根据IP地址扫描:");//IP地址单选按钮,默认选中IP地址
	protected static JRadioButton radioHost = new JRadioButton("根据主机名与端口号扫描:",true);//主机名单选按钮
	JLabel hostIP=new JLabel("(主机名或者主机IP地址)");

	protected static ButtonGroup group1 = new ButtonGroup();
	//IP地址扫描,十进制IP地址最多有12位,每3个一组,需要四个输入框

	protected static JRadioButton radiosingle = new JRadioButton("单个IP地址");//IP地址单选按钮,默认选中IP地址
	protected static JRadioButton radiomulti = new JRadioButton("一段IP地址",true);//主机名单选按钮
	protected static ButtonGroup group3 = new ButtonGroup();

	protected static JTextField singleip1=new JTextField("183",3);//输入扫描的起始IP地址前3位的可编辑文本框
	protected static JTextField singleip2=new JTextField("232",3);//输入起始IP地址4~6位的可编辑文本框
	protected static JTextField singleip3=new JTextField("231",3);//输入起始IP地址7~9位的输入框
	protected static JTextField singleip4=new JTextField("172",3);//输入起始IP地址10~12位的输入
	protected static JTextField fromip1=new JTextField("203",3);//输入扫描的起始IP地址前3位的可编辑文本框
	protected static JTextField fromip2=new JTextField("208",3);//输入起始IP地址4~6位的可编辑文本框
	protected static JTextField fromip3=new JTextField("40",3);//输入起始IP地址7~9位的输入框
	protected static JTextField fromip4=new JTextField("110",3);//输入起始IP地址10~12位的输入

	JLabel sPdot1 = new JLabel(".");
	JLabel sPdot2 = new JLabel(".");
	JLabel sPdot3 = new JLabel(".");//单个IP地址的分隔符,3个

	JLabel P1=new JLabel("~");//一个文本显示框
	JLabel Pdot1 = new JLabel(".");
	JLabel Pdot2 = new JLabel(".");
	JLabel Pdot3 = new JLabel(".");
	JLabel Pdot4 = new JLabel(".");//IP地址段的分隔符,4个

	protected static JTextField toip0=new JTextField("40",3);//输入扫描的结束IP地址第三部分
	protected static JTextField toip=new JTextField("130",3);//输入扫描的结束IP地址最后4位的输入框,默认前3部分相同
	//根据主机端口扫描
	protected static JTextField hostname=new JTextField("LAPTOP-J860BMB3",10);//初始状态下显示本机的主机号,输入主机名的可编辑文本框,可输入10个字符
	//分为所有端口和指定端口
	protected static JRadioButton radioAll=new JRadioButton("常用端口",true);
	JButton browser=new JButton("查看");
	protected static JRadioButton radioPart=new JRadioButton("部分端口");
	protected static ButtonGroup group2=new ButtonGroup();
	//指定端口的两个输入
	JLabel P2=new JLabel("~");
	protected static JTextField minPort=new JTextField("0",4);//输入最小端口号的输入框,规定最多4位数,默认为0
	protected static JTextField maxPort=new JTextField("1000",4);//输入最大端口的输入框,最多4位数,默认为1000
	//线程数
	JLabel THNUM=new JLabel("线程数:");
	protected static JTextField maxThread=new JTextField("10",3);//输入最大线程数量的输入框,默认为10个线程,3位数
	//定义按钮
	protected static JButton Submit = new JButton("开始扫描");
	protected static JButton Cancel = new JButton("退出");
	protected static JButton Clear=new JButton("清空");
	//扫描进度


	//扫描结果
	JLabel RST=new JLabel("扫描结果:  ");
	protected static JTextArea Result=new JTextArea();//显示文本,显示扫描结果
	//菜单栏
	protected static JMenu Menu0=new JMenu("文件(F)");//声明菜单项为文件
	protected static JMenuItem menu0Change=new JMenuItem("修改密码(G)");//声明文件下的子菜单项,3个
	protected static JMenuItem menu0Save=new JMenuItem("保存扫描结果(S)");
	protected static JMenuItem menu0Exit=new JMenuItem("退出(Q)");

	//主函数
	public static void main(String[] args) {
		LoginFrame lf=new LoginFrame();
		lf.setVisible(true);
		//		OwnTCPScan ownTCPScan=new OwnTCPScan();//创建一个对象
		//		ownTCPScan.setVisible(true);//显示该对象的界面
	}


	public OwnTCPScan(){//构造函数,在构造函数中完成布局
		super();
		JMenuBar menuBar=new JMenuBar();
		this.setTitle("Java端口扫描设计");
		this.setResizable(false);
		this.setSize(600,900);
		this.setLocationRelativeTo(this.getOwner());
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置主体完毕

		//初始状态
		singleip1.setEditable(false);
		singleip2.setEditable(false);
		singleip3.setEditable(false);
		singleip4.setEditable(false);
		fromip1.setEditable(false);
		fromip2.setEditable(false);
		fromip3.setEditable(false);
		fromip4.setEditable(false);
		toip0.setEditable(false);
		toip.setEditable(false);//初始情况下,这些项不可以修改
		radiosingle.setEnabled(false);
		radiomulti.setEnabled(false);//初始情况下,这些项不可以选中

		//设置界面
		this.setJMenuBar(menuBar);//menuBar添加到主界面
		menu0Change.addActionListener(this);
		Menu0.add(menu0Change);//修改密码项添加进Menu0即文件下面
		menu0Save.addActionListener(this);
		menu0Save.setEnabled(false);//一开始,是灰的,不能点
		Menu0.add(menu0Save);
		menu0Exit.addActionListener(this);//从始至终,都可以退出
		Menu0.add(menu0Exit);
		Menu0.setMnemonic('F');//设置文件的快捷键为crtl+F
		menu0Save.setMnemonic('S');//设置保存的快捷键为crtl+S
		menu0Exit.setMnemonic('Q');//设置退出的快捷键为crtl+Q
		menu0Change.setMnemonic('G');//设置更改密码的快捷键为crtl+G
		menu0Change.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_G,InputEvent.CTRL_MASK));
		menu0Save.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,InputEvent.CTRL_MASK));
		menu0Exit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q,InputEvent.CTRL_MASK));
		menuBar.add(Menu0);//菜单栏建立完成

		panel1 = new JPanel();
		JScrollPane scroll = new JScrollPane(Result);
		scroll.setPreferredSize(new Dimension(600,480));
		Container pane = getContentPane();
		getContentPane().add(panel1);
		getContentPane().add(Result);
		panel1.setPreferredSize(new Dimension(600, 420));
		panel1.setLayout(null);//采用无布局方式添加控件

		choiceTip.setBounds(30,30,100,20);
		panel1.add(choiceTip);
		group1.add(radioIp);
		group1.add(radioHost);
		radioIp.setBounds(30,60,200,20);
		panel1.add(radioIp);
		radioHost.setBounds(30,150,200,20);
		panel1.add(radioHost);

		group3.add(radiosingle);
		group3.add(radiomulti);
		radiosingle.setBounds(60,90,100,20);
		panel1.add(radiosingle);
		singleip1.setBounds(160,90,35,20);
		panel1.add(singleip1);
		sPdot1.setBounds(195,95,10,10);
		panel1.add(sPdot1);
		singleip2.setBounds(205,90,35,20);
		panel1.add(singleip2);
		sPdot2.setBounds(240,95,10,10);
		panel1.add(sPdot2);
		singleip3.setBounds(250,90,35,20);
		panel1.add(singleip3);
		sPdot3.setBounds(285,95,10,10);
		panel1.add(sPdot3);
		singleip4.setBounds(295,90,35,20);
		panel1.add(singleip4);//单个IP地址的输入设计完成

		radiomulti.setBounds(60,120,100,20);
		panel1.add(radiomulti);

		fromip1.setBounds(160,120,35,20);
		panel1.add(fromip1);
		Pdot1.setBounds(195,125,10,10);
		panel1.add(Pdot1);
		fromip2.setBounds(205,120,35,20);
		panel1.add(fromip2);
		Pdot2.setBounds(240,125,10,10);
		panel1.add(Pdot2);
		fromip3.setBounds(250,120,35,20);
		panel1.add(fromip3);
		Pdot3.setBounds(285,125,10,10);
		panel1.add(Pdot3);
		fromip4.setBounds(295,120,35,20);
		panel1.add(fromip4);
		P1.setBounds(330,120,10,20);
		panel1.add(P1);
		toip0.setBounds(340,120,35,20);
		panel1.add(toip0);
		Pdot4.setBounds(375,125,10,10);
		panel1.add(Pdot4);
		toip.setBounds(385,120,35,20);
		panel1.add(toip);//一段IP地址设计完成

		hostname.setBounds(230,150,150,20);
		panel1.add(hostname);
		hostIP.setBounds(380,150,150,15);
		panel1.add(hostIP);
		group2.add(radioAll);
		group2.add(radioPart);
		radioAll.setBounds(60,180,120,20);
		panel1.add(radioAll);
		browser.setBounds(180,180,60,20);
		panel1.add(browser);
		browser.setFont(new Font("",Font.BOLD,12));
		//常用端口设计完成
		radioPart.setBounds(60,210,120,20);
		panel1.add(radioPart);
		minPort.setBounds(180,210,40,20);
		panel1.add(minPort);
		P2.setBounds(220,210,10,20);
		panel1.add(P2);
		maxPort.setBounds(230,210,40,20);//指定端口设计完成
		panel1.add(maxPort);
		THNUM.setBounds(30,240,60,20);
		panel1.add(THNUM);
		maxThread.setBounds(90,240,60,20);
		panel1.add(maxThread);//线程数设计完成

		Submit.setBounds(80,290,120,30);
		panel1.add(Submit);
		Cancel.setBounds(240,290,120,30);
		panel1.add(Cancel);
		Clear.setBounds(400,290,120,30);
		panel1.add(Clear);//三个按钮设计完成
		RST.setBounds(30,350,120,20);
		panel1.add(RST);//扫描结果提示语句设计完成,至此,panel1建立完成

		pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));//下面是滚动条,即结果显示区域
		Result.setLayout(null);
		scroll.setViewportView(Result);
		scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		pane.add(scroll);
		Result.setEditable(true);//结果显示区域可编辑
		Result.setTabSize(10);
		Result.setLineWrap(true);//激活自动换行功能
		Result.setWrapStyleWord(true);//激活断行不断字功能
		Result.setBounds(40,420,500,200);
		Result.setFont(new Font("宋体",Font.BOLD,14));//面板建立完成

		//按钮的监听事件

		//两组单选按钮需要互斥,因此设置监听事件
		radioIp.addItemListener(new ItemListener() {//Host的三个项都不可以修改
			@Override
			public void itemStateChanged(ItemEvent arg0) {
				if(arg0.getSource()==radioIp){
					fromip1.setEditable(true);
					fromip2.setEditable(true);
					fromip3.setEditable(true);
					fromip4.setEditable(true);
					toip.setEditable(true);
					toip0.setEditable(true);
					singleip1.setEditable(true);
					singleip2.setEditable(true);
					singleip3.setEditable(true);
					singleip4.setEditable(true);//IP下,这些项可以修改

					radiosingle.setEnabled(true);
					radiomulti.setEnabled(true);//IP下,可以选中

					hostname.setEditable(false);
					minPort.setEditable(false);
					maxPort.setEditable(false);//IP下,这三项不可以修改

					radioAll.setEnabled(false);
					radioPart.setEnabled(false);
				}
			}
		});

		radioHost.addItemListener(new ItemListener() {

			@Override
			public void itemStateChanged(ItemEvent arg0) {
				if(arg0.getSource()==radioHost){
					OwnTCPScan.maxThread.setText("10");
					fromip1.setEditable(false);
					fromip2.setEditable(false);
					fromip3.setEditable(false);
					fromip4.setEditable(false);
					toip.setEditable(false);
					toip0.setEditable(false);
					singleip1.setEditable(false);
					singleip2.setEditable(false);
					singleip3.setEditable(false);
					singleip4.setEditable(false);//Host下,不可以修改
					radiosingle.setEnabled(false);
					radiomulti.setEnabled(false);//host下,不可以选中


					hostname.setEditable(true);
					minPort.setEditable(true);
					maxPort.setEditable(true);//Host下,这三项恢复修改
					radioAll.setEnabled(true);
					radioPart.setEnabled(true);
				}

			}
		});

		radiosingle.addItemListener(new ItemListener() {//选择单个IP地址,默认状态,不可修改IP范围下的输入
			@Override
			public void itemStateChanged(ItemEvent arg0) {
				OwnTCPScan.maxThread.setText("1");
				fromip1.setEditable(false);
				fromip2.setEditable(false);
				fromip3.setEditable(false);
				fromip4.setEditable(false);
				toip.setEditable(false);
				toip0.setEditable(false);
				singleip1.setEditable(true);
				singleip2.setEditable(true);
				singleip3.setEditable(true);
				singleip4.setEditable(true);
			}
		});

		radiomulti.addItemListener(new ItemListener() {//选中IP范围下,不可修改单个IP的输入
			@Override
			public void itemStateChanged(ItemEvent arg0) {
				OwnTCPScan.maxThread.setText("10");
				fromip1.setEditable(true);
				fromip2.setEditable(true);
				fromip3.setEditable(true);
				fromip4.setEditable(true);
				toip.setEditable(true);
				toip0.setEditable(true);
				singleip1.setEditable(false);
				singleip2.setEditable(false);
				singleip3.setEditable(false);
				singleip4.setEditable(false);
			}
		});

		radioAll.addItemListener(new ItemListener() {//选择常用端口,最小最大不可编辑

			@Override
			public void itemStateChanged(ItemEvent arg0) {

				minPort.setEditable(false);
				maxPort.setEditable(false);

			}
		});

		radioPart.addItemListener(new ItemListener() {

			@Override
			public void itemStateChanged(ItemEvent arg0) {

				minPort.setEditable(true);
				maxPort.setEditable(true);

			}
		});

		browser.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				JOptionPane.showMessageDialog(null, "常用端口包括:\n21, 22, 23, 25, 26, 53,69, 80, 110, 143,443,465,69,161,162,\r\n" +
								"							135,995,1080,1158,1433,1521,2100, 3128, 3306, 3389,7001, 8080,\r\n" +
								"							8081, 9080, 9090, 43958 ,135,445,1025,1026,1027,1028,1055,5357",
						"查看常用端口", JOptionPane.INFORMATION_MESSAGE);
			}
		});

		Submit.addActionListener(new ActionListener() {//开始扫描的点击事件,调用一个类

			@Override
			public void actionPerformed(ActionEvent arg0) {
				SubmitAction submitAction=new SubmitAction();
				submitAction.actionPerformed(arg0);

			}
		});//扫描按钮的实现,是最重要的部分,里面包含合法性判别与扫描过程

		Cancel.addActionListener(new ActionListener() {//取消按钮的实现,直接退出,调用exitDialog()函数
			@Override
			public void actionPerformed(ActionEvent arg0) {
				exitDialog();//调用退出对话框函数
			}
		});

		Clear.addActionListener(new ActionListener() {//清空按钮的实现,将界面完全清空

			@Override
			public void actionPerformed(ActionEvent arg0) {
				radioIp.setSelected(false);
				radioHost.setSelected(true);
				radioAll.setSelected(true);
				singleip1.setText("");
				singleip2.setText("");
				singleip3.setText("");
				singleip4.setText("");
				fromip1.setText("");
				fromip2.setText("");
				fromip3.setText("");
				fromip4.setText("");
				toip.setText("");
				toip0.setText("");
				hostname.setText("");
				minPort.setText("");
				maxPort.setText("");
				maxThread.setText("");
				Result.setText("");

			}
		});

	}

	//菜单选项的3个点击事件
	@Override
	public void actionPerformed(ActionEvent e) {
		if(e.getSource()==menu0Save){
			menu0Save.setEnabled(true);
			JFileChooser fc=new JFileChooser();
			int returnVal=fc.showSaveDialog(null);
			//点击“保存”
			if(returnVal == 0){
				File saveFile=fc.getSelectedFile();
				try {
					FileWriter writeOut = new FileWriter(saveFile);
					writeOut.write(OwnTCPScan.Result.getText());
					writeOut.close();
				}
				catch (IOException ex) {
					ex.printStackTrace();
					System.out.println("保存失败");
				}
			}
			//点击“取消”
			else return;
			JOptionPane.showMessageDialog(null, "您已经成功保存数据","保存", JOptionPane.INFORMATION_MESSAGE);
		}
		if(e.getSource()==menu0Change){
			String s=JOptionPane.showInputDialog(null, "请输入新密码:", "修改密码", JOptionPane.PLAIN_MESSAGE);
			if(s==null)
				return;
			s=s.trim();
			if(s.length()==0){
				JOptionPane.showMessageDialog(null, "密码不能为空!", "修改密码", JOptionPane.ERROR_MESSAGE);
				return;
			}
			String clearText = 	"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
			String cipherText=	"UADKIy3FxgVkl5iZzWuGd1HNhOCtvjJ2pEn6Yw7PqrcQReB8Mfm0STsLX9a4ob";
			String resultText=		"";
			for(int i=0;i<s.length();i++){
				char c=s.charAt(i);
				if(clearText.indexOf(""+c)==-1){
					JOptionPane.showMessageDialog(null, "密码中包含非法字符", "修改密码", JOptionPane.ERROR_MESSAGE);
					return;
				}else{
					resultText+=""+cipherText.charAt(clearText.indexOf(""+c));
				}
			}
			try {
				FileOutputStream fos = new FileOutputStream("./src/password.txt");
				OutputStreamWriter dos=new OutputStreamWriter(fos);
				BufferedWriter writer=new BufferedWriter(dos);
				writer.write(resultText);
				writer.close();dos.close();fos.close();
				JOptionPane.showMessageDialog(null, "密码修改成功!", "学生信息管理系统", JOptionPane.INFORMATION_MESSAGE);
			} catch (FileNotFoundException e1) {
				e1.printStackTrace();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}
		if(e.getSource()==menu0Exit){
			exitDialog();
		}

	}

	protected void noteDialog(String tip){//调用时需要传参,传递错误信息是什么
		JOptionPane.showMessageDialog(null, tip, "错误", JOptionPane.ERROR_MESSAGE);
	}


	//实现“开始扫描”功能,完成扫描,含所有输入合法的判断,以及端口扫描的入口函数scanPorts,进行参数传递
	class SubmitAction implements ActionListener{

		public SubmitAction() {

		}
		private static final int MAXTHREAD=100;//最大线程数设为100
		public void noteDialog(String tip){//调用时需要传参,传递错误信息是什么
			JOptionPane.showMessageDialog(null, tip, "错误", JOptionPane.ERROR_MESSAGE);
		}
		public void actionPerformed (ActionEvent a){//点击确定按钮后要做的事情

			//首先判断输入合法性,包括五个IP地址是否是整型数,是否是有效数0~255;端口是否是整型数
			long startTime=System.currentTimeMillis();//获取开始时间
			long endTime=0;//结束时间初始化
			int minPort;
			int maxPort;//端口扫描用的
			int maxThread;
			int sip1=0;
			int sip2=0;
			int sip3=0;
			int sip4=0;//单个IP地址用的
			int ip1 = 0;
			int ip2 = 0;
			int ip3 = 0;
			int ipstart = 0;
			int ipend0 = 0;
			int ipend = 0;//用这些变量代指,编码方便,IP范围用的
			String hostname = "";
			OwnTCPScan.Result.setText("");
			OwnTCPScan.Submit.setEnabled(false);
			OwnTCPScan.menu0Save.setEnabled(false);//将"确定"按钮和保存按钮设置成为不可用

			if(OwnTCPScan.radioIp.isSelected()){//根据IP地址扫描,默认是主句号与端口

				if(OwnTCPScan.radiomulti.isSelected()){//如果是扫描一段IP地址范围
					//逐位判断IP地址是否合法,如果非法,则直接退出

					try{//判断IP的前3位是否为int型
						ip1=Integer.parseInt(OwnTCPScan.fromip1.getText().trim());
					}
					catch(NumberFormatException e){
						noteDialog("起始IP地址的第一部分必须存在,且为整数!");
						OwnTCPScan.Submit.setEnabled(true);
						return;
					}

					try{//判断IP的4~6位是否为int型
						ip2=Integer.parseInt(OwnTCPScan.fromip2.getText().trim());
					}
					catch(NumberFormatException e){
						noteDialog("起始IP地址的第二部分必须存在,且为整数!");
						OwnTCPScan.Submit.setEnabled(true);
						return;
					}

					try{//判断IP的7~9位是否为int型
						ip3=Integer.parseInt(OwnTCPScan.fromip3.getText().trim());
					}
					catch(NumberFormatException e){
						noteDialog("起始IP地址的第三部分必须存在,且为整数!");
						OwnTCPScan.Submit.setEnabled(true);
						return;
					}

					try{//判断起始IP的最后4位是否为int型
						ipstart=Integer.parseInt(OwnTCPScan.fromip4.getText().trim());
					}
					catch(NumberFormatException e){
						noteDialog("起始IP地址的第四部分必须存在,且为整数!");
						OwnTCPScan.Submit.setEnabled(true);
						return;
					}

					try{//判断目标IP的最后4位是否为int型
						ipend0=Integer.parseInt(OwnTCPScan.toip0.getText().trim());
						ipend=Integer.parseInt(OwnTCPScan.toip.getText().trim());
					}
					catch(NumberFormatException e){
						noteDialog("结束IP地址必须存在,且为整数!");
						OwnTCPScan.Submit.setEnabled(true);
						return;
					}

					try{//判断进程数的有效性
						maxThread=Integer.parseInt(OwnTCPScan.maxThread.getText().trim());
					}
					catch(NumberFormatException e){
						noteDialog("线程数必须存在,并且是整数!");
						OwnTCPScan.Submit.setEnabled(true);
						return;
					}//合法性判断完成,是整数

					//判断条件:大于0且小于等于255
					if(ip1<0 || ip1>255||ip2<0 || ip2>255||ip3<0 || ip3>255||ipstart<0 || ipstart>255 ||ipend<0 || ipend>255 ||ipend0<0 || ipend0>255){
						noteDialog("IP地址必须是0~255之间的整数!");
						OwnTCPScan.Submit.setEnabled(true);
						return;
					}
					//判断from是否比to要小
					if(ip3>ipend0) {
						noteDialog("起始扫描地址要小于终止扫描地址!");
						OwnTCPScan.Submit.setEnabled(true);
						return;
					}
					if(ip3==ipend0&&ipstart>ipend) {
						noteDialog("起始扫描地址要小于终止扫描地址!");
						OwnTCPScan.Submit.setEnabled(true);
						return;
					}

					if(maxThread<1 || maxThread>MAXTHREAD){//判断线程数量的有效范围判断条件:大于1且小于200
						noteDialog("线程数为1-"+MAXTHREAD+"之间的整数!");
						OwnTCPScan.Submit.setEnabled(true);
						return;
					}//有效性判断完成,是符合条件的数

					else{//说明上面6个IP地址都对,且线程数正确,开始扫描IP地址,调用PingTester类,所有的内容都在这个类中
						OwnTCPScan.Result.append("线程数 "+OwnTCPScan.maxThread.getText()+"\n");
						PingTester tester = new PingTester(ip1,ip2,ip3,ipstart,ipend0,ipend);
						tester.startPing(maxThread);//读进来的最大线程数
						OwnTCPScan.Submit.setEnabled(true);//允许重新扫描
						OwnTCPScan.menu0Save.setEnabled(true);//允许保存
						endTime=System.currentTimeMillis(); //获取结束时间
						System.out.println("扫描时长为:"+(double)(endTime-startTime)/1000+"s");
						OwnTCPScan.Result.append("扫描时长为:"+(double)(endTime-startTime)/1000+"s\n");
					}//执行结束
				}//一段IP地址的扫描结束

				if(OwnTCPScan.radiosingle.isSelected()){//选择单个IP地址扫描
					try{//判断IP的前3位是否为int型
						sip1=Integer.parseInt(OwnTCPScan.singleip1.getText().trim());
					}
					catch(NumberFormatException e){
						noteDialog("起始IP地址的第一部分必须存在,且为整数!");
						OwnTCPScan.Submit.setEnabled(true);
						return;
					}

					try{//判断IP的4~6位是否为int型
						sip2=Integer.parseInt(OwnTCPScan.singleip2.getText().trim());
					}
					catch(NumberFormatException e){
						noteDialog("起始IP地址的第二部分必须存在,且为整数!");
						OwnTCPScan.Submit.setEnabled(true);
						return;
					}

					try{//判断IP的7~9位是否为int型
						sip3=Integer.parseInt(OwnTCPScan.singleip3.getText().trim());
					}
					catch(NumberFormatException e){
						noteDialog("起始IP地址的第三部分必须存在,且为整数!");
						OwnTCPScan.Submit.setEnabled(true);
						return;
					}

					try{//判断IP的最后4位是否为int型
						sip4=Integer.parseInt(OwnTCPScan.singleip4.getText().trim());
					}
					catch(NumberFormatException e){
						noteDialog("起始IP地址的第四部分必须存在,且为整数!");
						OwnTCPScan.Submit.setEnabled(true);
						return;
					}
					try{//判断进程数的有效性,这个不变
						maxThread=Integer.parseInt(OwnTCPScan.maxThread.getText().trim());
					}
					catch(NumberFormatException e){
						noteDialog("线程数必须存在,并且是整数!");
						OwnTCPScan.Submit.setEnabled(true);
						return;
					}//输入合法性判断结束,是整数

					//判断条件:大于0且小于等于255
					if(sip1<0 || sip1>255||sip2<0 || sip2>255||sip3<0 || sip3>255||sip4<0 ||sip4>255){
						noteDialog("IP地址必须是0~255之间的整数!");
						OwnTCPScan.Submit.setEnabled(true);
						return;
					}

					if(maxThread<1 || maxThread>MAXTHREAD){//判断线程数量的有效范围判断条件:大于1且小于200
						noteDialog("线程数为1-"+MAXTHREAD+"之间的整数!");
						OwnTCPScan.Submit.setEnabled(true);
						return;
					}//输入有效性判断结束,是符合条件的数
					else{//说明上面4个IP地址都对,且线程数正确,开始扫描IP地址
						OwnTCPScan.Result.append("线程数 "+OwnTCPScan.maxThread.getText()+"\n");
						PingTester tester = new PingTester(sip1,sip2,sip3,sip4,sip3,sip4);
						tester.startPing(maxThread);//读进来的最大线程数
						OwnTCPScan.Submit.setEnabled(true);
						OwnTCPScan.menu0Save.setEnabled(true);
						endTime=System.currentTimeMillis(); //获取结束时间
						System.out.println("扫描时长为:"+(double)(endTime-startTime)/1000+"s");
						OwnTCPScan.Result.append("扫描时长为:"+(double)(endTime-startTime)/1000+"s\n");
					}
				}//单个IP地址扫描结束
			}//根据IP地址扫描结束,最外层结束


			if(OwnTCPScan.radioHost.isSelected()){//根据主机名进行端口扫描
				try{//判断主机名称的有效性
					@SuppressWarnings("unused")
					InetAddress ia=InetAddress.getByName(OwnTCPScan.hostname.getText().trim());
				}
				catch(UnknownHostException e){
					noteDialog("主机名无效,网络不可达!");
					OwnTCPScan.Submit.setEnabled(true);
					return;
				}

				try{//判断线程数的有效性,整数
					maxThread=Integer.parseInt(OwnTCPScan.maxThread.getText().trim());
				}
				catch(NumberFormatException e){
					noteDialog("线程数必须存在,并且是整数!");
					OwnTCPScan.Submit.setEnabled(true);
					return;
				}
				if(maxThread<1 || maxThread>MAXTHREAD){//判断线程数量的有效范围判断条件:大于1且小于200
					noteDialog("线程数为1-"+MAXTHREAD+"之间的整数!");
					OwnTCPScan.Submit.setEnabled(true);
					return;
				}//常用端口的有效性判断完成

				if(OwnTCPScan.radioAll.isSelected()){//判断选中的常用端口还是指定端口
					//很简单,直接进行扫描端口
					hostname=OwnTCPScan.hostname.getText();
					List <Integer>portList = new LinkedList<Integer>();// 定义一个List容器表示扫描的端口的List集合
					//之所以选择LinkedList,因为进行增删操作,linkedList较为容易,只需要移动指针
					Integer[] ports = new Integer[]{21, 22, 23, 25, 26, 53,69, 80, 110, 143,
							443,465,69,161,162,135,995,1080,1158,1433,1521,2100, 3128, 3306, 3389,
							7001, 8080, 8081, 9080, 9090, 43958 ,135,445,1025,1026,1027,1028,1055,5357};
					portList.addAll(Arrays.asList(ports));
					//scanPorts为SubmitAction类的内部函数,调用该函数,该函数调用ScanMethod类
					scanPorts(hostname, portList,maxThread, 800);//将主机名,常用端口,线程数与超时时间800ms传参过去
					OwnTCPScan.Submit.setEnabled(true);
					OwnTCPScan.menu0Save.setEnabled(true);
					endTime=System.currentTimeMillis(); //获取结束时间
					System.out.println("\n扫描完成\n");
					OwnTCPScan.Result.append("\n扫描完成\n");
					System.out.println("扫描时长为:"+(double)(endTime-startTime)/1000+"s");
					OwnTCPScan.Result.append("扫描时长为:"+(double)(endTime-startTime)/1000+"s\n");
				}


				if(OwnTCPScan.radioPart.isSelected()){//指定端口
					//需要继续判断端口输入的有效性
					try{//判断端口号的有效性,整数
						minPort=Integer.parseInt(OwnTCPScan.minPort.getText().trim());
						maxPort=Integer.parseInt(OwnTCPScan.maxPort.getText().trim());

					}
					catch(NumberFormatException e){
						noteDialog("端口号必须存在,并且是整数!");
						OwnTCPScan.Submit.setEnabled(true);
						return;
					}
					//判断最小端口号的有效范围
					//判断条件:大于0且小于65535,最大端口应大于最小端口
					if(minPort<0 || minPort>65535 || minPort>maxPort){
						noteDialog("最小端口在0-65535之间,且小于最大端口数"+maxPort+"!");
						OwnTCPScan.Submit.setEnabled(true);
						return;
					}
					else{//最小端口有效,什么也不做
					}
					if(maxPort<0 || maxPort>65535){//判断最大端口号的有效范围;判断条件:大于0且小于65535,最大端口应大于最小端口
						noteDialog("最大端口在0-65535之间,且大于最小端口数"+minPort+"!");
						OwnTCPScan.Submit.setEnabled(true);
						return;
					}
					else{//最大端口号有效,进行端口扫描
						hostname=OwnTCPScan.hostname.getText().trim();
						List <Integer>portList = new LinkedList<Integer>();// 定义一个List容器表示扫描的团口的List集合
						int length_integer=maxPort-minPort+1;
						Integer[] ports = new Integer[length_integer];
						for (int i=0;i<maxPort-minPort+1;i++){
							ports[i]=minPort+i;
						}
						portList.addAll(Arrays.asList(ports));
						scanPorts(hostname, portList,maxThread, 800);//将主机名,端口范围,线程数与超时时间800ms传参过去
						OwnTCPScan.Submit.setEnabled(true);
						OwnTCPScan.menu0Save.setEnabled(true);
						System.out.println("\n扫描完成\n");
						OwnTCPScan.Result.append("\n扫描完成\n");
						endTime=System.currentTimeMillis(); //获取结束时间
						System.out.println("扫描时长为:"+(double)(endTime-startTime)/1000+"s");
						OwnTCPScan.Result.append("扫描时长为:"+(double)(endTime-startTime)/1000+"s\n");
					}
				}
			}//主机号端口判断结束
		}

		//扫描端口的方法实现
		public void scanPorts(String ip, List<Integer> portSet,int threadNumber, int timeout) {//扫描端口,用到ScanMethod类
			ExecutorService threadPool = Executors.newCachedThreadPool();//负责线程的使用和调度的根接口,异步执行机制
			//线程池
			for (int i = 0; i < threadNumber; i++) {
				//10个线程 加入到线程池里
				ScanMethod scanMethod2 = new ScanMethod(ip, portSet,threadNumber, i, timeout);
				//层层传参,传到ScanMethod里面进行端口扫描的实现
				threadPool.execute(scanMethod2);//异步执行
			}
			threadPool.shutdown();
			while (true) {
				if (threadPool.isTerminated()) {
					//如果所有任务都在关闭后完成,则返回true。注意,除非首先调用了shutdown或shutdownNow,否则isTerminated永远不会为真。
					break;
				}
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}// end of while
		}

	}

	//退出功能的提示对话框,使用两次
	private void exitDialog(){
		int n = JOptionPane.showConfirmDialog(null, "确认退出吗?", "退出系统", JOptionPane.YES_NO_OPTION);
		if (n == JOptionPane.YES_OPTION) {
			System.exit(0);
		} else if (n == JOptionPane.NO_OPTION) {//关闭对话框,什么都不做

		}
	}

	//扫描端口类,含run方法的实现
	private class ScanMethod implements Runnable {
		private String ip; // 目标IP
		private List<Integer> portList; // 待扫描的端口的List集合
		private int threadNumber, serial, timeout; // 线程数,这是第几个线程,超时时间
		public ScanMethod(String ip, List<Integer> portList, int threadNumber,int serial, int timeout) {
			this.ip = ip;//IP地址或主机号
			this.portList = portList;//待扫描端口的LIST集合
			this.threadNumber = threadNumber;
			this.serial = serial;//第几个线程
			this.timeout = timeout;//连接超时时间
		}
		public void run() {
			int port = 0;
			Integer[] ports = portList.toArray(new Integer[portList.size()]); // List转数组
			try {
				InetAddress address = InetAddress.getByName(ip); //InetAddress可以根据主机名获取主机的ip地址,也支持输入IP地址
				Socket socket;//定义套接字,调用connect函数查看端口的状态
				SocketAddress socketAddress;//SocketAddress是一个抽象类,传递ip和端口,其实真正实现的不是SocketAddress,而是其子类,这样声明是为了方便调用
				//必须使用SocketAddress的子类来建立SocketAddress对象
				if (ports.length < 1)
					return;//若数组没有元素,返回,不执行
				for (port = 0 + serial; port <= ports.length - 1; port += threadNumber) {//每次运行maxThread个线程
					socket = new Socket();
					socketAddress = new InetSocketAddress(address, ports[port]);
					//InetSocketAddress是SocketAddress的实现子类,此类实现 IP 套接字地址(IP 地址 + 端口号),不依赖任何协议
					try {
						socket.connect(socketAddress, timeout);
						//对目标主机的指定端口进行连接,超时后连接失败
						socket.close();
						//关闭端口
						System.out.println("端口 " + ports[port] + " :开放");
						OwnTCPScan.Result.append("端口 " + ports[port] + " :开放\n");
						//在文本区域里更新消息
					} catch (IOException e) {
						System.out.println("端口 " + ports[port] + " :关闭");
						//OwnTCPScan.Result.append("端口 " + ports[port] + " :关闭\n");//产生异常表示端口关闭
					}
				}
			} catch (UnknownHostException e) {
				e.printStackTrace();
			}
		}//end of run()

	}//end of ScanMethod


	//IP地址扫描类,含PingRunner内部类和startPing方法
	class PingTester {
		private Queue<String> allIp;
		private int fetchedNum = 0; // 已经取得的任务数量,每次从队列中取一个ip就加1

		public PingTester(int fromip1,int fromip2,int fromip3,int fromip4,int toip3,int toip4) {
			// 首先创建一个队列用于存储所有ip地址
			allIp = new LinkedList<String>();
			int finalip4=0;
			for (int i =fromip3; i <= toip3; i++) {
				if(i<toip3)
					finalip4=255;
				else
					finalip4=toip4;

				for (int j=fromip4; j <=finalip4; j++) {
					allIp.offer(fromip1+"."+fromip2+"."+i+"."+j);//插入到队列中
					//offer()方法是往队列尾部插入元素,如果越界直接返回false,与add方法类似,但是稍有不同
				}
			}
		}

		public void startPing(int threadNum) {
			// 创建一个线程池,多个线程同时跑
			ExecutorService executor = Executors.newFixedThreadPool(threadNum);//异步执行机制
			//提供用于管理终止的方法的执行程序,以及可以产生用于跟踪一个或多个异步任务进展的未来的方法。
			for (int i = 0; i < threadNum; i++) {
				executor.execute(new PingRunner());//异步执行,调用线程类,实现多线程
			}
			executor.shutdown();//必须先shutdown,否则isTerminated永远不会为真
			try {
				while (!executor.isTerminated()) {
					//如果所有任务都在关闭后完成,则返回true。注意,除非首先调用了shutdown或shutdownNow,否则isTerminated永远不会为真。
					Thread.sleep(100);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			//还需要将这个数字输出出来
			System.out.println("获取的地址总数是"+fetchedNum);
			OwnTCPScan.Result.append("获取的地址总数是"+fetchedNum+"\n");
			System.out.println("扫描完成");
			OwnTCPScan.Result.append("\n扫描完成\n");
		}
		//PingTester的内部类,有Runnable的接口
		private class PingRunner implements Runnable {
			private String taskIp = null;
			@Override
			public void run() {//抽象方法的实现
				try {
					while ((taskIp = getIp()) != null) {//调用getIp()方法得到IP地址
						InetAddress addr = InetAddress.getByName(taskIp);//获得IP地址
						if (addr.isReachable(5000)) {//测试该地址是否可到达。实现会尽最大努力尝试访问主机,访问超时时间为5s
							//说明可达,需要添加进去,显示出来
							System.out.println("IP地址 ["+taskIp+"]是可达的");
							OwnTCPScan.Result.append("IP地址 ["+taskIp+"]是可达的"+"\n");
						} else {
							System.out.println("IP地址 ["+taskIp+"]是不可达的");
							//OwnTCPScan.Result.append("IP地址 ["+taskIp+"]是不可达的"+"\n");
						}
					}
				} catch (SocketException e) {
					System.out.println("IP地址 ["+taskIp+"]没有访问权限");
					OwnTCPScan.Result.append("IP地址 ["+taskIp+"]没有访问权限"+"\n");
				} catch (Exception e) {
					System.out.println("---------------------------------------------"+taskIp);
					OwnTCPScan.Result.append("---------------------------------------------"+taskIp+"\n");
					e.printStackTrace();
				}
			}

			public String getIp() {
				String ip = null;
				synchronized (allIp) {//对象锁
					ip = allIp.poll();//从头部删除一个元素,poll() ,在队列元素为空的情况下,返回 null
				}
				if (ip != null) {
					fetchedNum++;//扫描的IP地址数增1
				}
				return ip;
			}
		}
	}
}

//登录界面类
@SuppressWarnings("serial")
class LoginFrame extends JFrame implements ActionListener{
	JTextField username=new JTextField(10);//用户编辑框,输入用户名
	JPasswordField pwd=new JPasswordField(10);//输入密码
	LoginFrame(){
		Font font1=new Font("标楷体",Font.BOLD,16);//提示语的字体
		Font font2=new Font("Times new Roman",Font.PLAIN,16);//用户输入的字体
		this.setTitle("系统登录");
		this.setResizable(false);//不允许缩放
		this.setSize(400,260);//界面大小
		this.setLocationRelativeTo(this.getOwner());//相对位置,居中
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//点击×则结束进程

		JLabel lb1=new JLabel("用户名");
		JLabel lb2=new JLabel("密 码");
		JButton btn=new JButton("登录");

		btn.addActionListener(this);//btn的点击事件
		Container c=this.getContentPane();//只有一个界面
		c.setLayout(null);//不使用任何现存布局
		lb1.setBounds(80, 40, 60, 30);//用户名提示
		lb1.setFont(font1);
		lb1.setForeground(Color.black);
		c.add(lb1);

		username.setBounds(150,40,150,30);//用户名输入框
		username.addActionListener(this);
		username.setFont(font2);
		username.setForeground(Color.black);
		c.add(username);

		lb2.setBounds(80,80,60,30);//密码提示
		lb2.setFont(font1);
		lb2.setForeground(Color.black);
		c.add(lb2);

		pwd.setBounds(150,80,150,30);//密码输入框
		pwd.addActionListener(this);
		pwd.setFont(font2);
		pwd.setForeground(Color.black);
		c.add(pwd);


		btn.setBounds(110,130,150,40);//登录按钮
		btn.setFont(font1);
		c.add(btn);
		this.setVisible(true);
		this.username.requestFocus();
	}

	public void actionPerformed(ActionEvent e) {
		if(e.getSource()==this.username){
			this.pwd.requestFocus();
			return;
		}
		try {
			FileInputStream fis;
			fis = new FileInputStream("./src/password.txt");
			InputStreamReader dis=new InputStreamReader(fis);
			BufferedReader reader=new BufferedReader(dis);
			String s;
			String clearText = 	"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
			String cipherText=	"UADKIy3FxgVkl5iZzWuGd1HNhOCtvjJ2pEn6Yw7PqrcQReB8Mfm0STsLX9a4ob";
			if((s=reader.readLine())!=null){
				if(username.getText().trim().equals("admin")){//用户名正确,比较密码
					boolean isCorrect=true;
					char[] ch1=pwd.getPassword();
					char[] ch2=s.toCharArray();
					if(ch1.length==ch2.length){//如果长度相等,再比较
						for(int i=0;i<ch1.length;i++){
							if(clearText.indexOf(ch1[i])!=cipherText.indexOf(ch2[i])){//只要有不等的,就为错
								isCorrect=false;
								break;
							}
						}
					}
					else{//长度不等,直接错误
						isCorrect=false;
					}
					//对结果做出判断
					if(isCorrect){
						this.setVisible(false);
						this.dispose();
						JOptionPane.showMessageDialog(null,"登录成功!","用户登录",JOptionPane.OK_CANCEL_OPTION);
						OwnTCPScan ownTCPThread=new OwnTCPScan();//创建一个对象
						ownTCPThread.setVisible(true);//显示该对象的界面
					}
					else{
						JOptionPane.showMessageDialog(null, "您填写的密码不正确", "用户登录", JOptionPane.WARNING_MESSAGE);
					}
				}else{//用户名不正确
					JOptionPane.showMessageDialog(null, "您填写的用户名不正确", "用户登录", JOptionPane.WARNING_MESSAGE);
					this.username.requestFocus();
				}
			}
			reader.close();
			dis.close();
			fis.close();
		}catch (IOException e1) {
			e1.printStackTrace();
		}
	}
}




  • 9
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值