精华内容
下载资源
问答
  • 三、端口扫描器视图 6 1、工作窗口 6 2、异常窗口 6 3、窗口核心代码 6 四、线程快速扫描 7 1、线程机制 7 2、线程核心代码 8 五、用户使用方法 9 1、页面说明 9 2、按主机名扫描 9 3、按IP地址扫描 9 六、...
  • 设计通过端口扫描器的研究来提高对计算机安全的认识。利用TCPconnect扫描原理,扫描主机通过TCP/IP协议的三次握手目标主机的指定端口建立一次完整的连接,如果目标主机该端口有回复,则说明该端口开放。利用...
  • linux线程端口扫描器原理与实现

    千次阅读 2009-04-17 09:42:00
    linux线程端口扫描器原理与实现进程与线程 进程的概念是操作系统结构的基础。Multics的设计者在20世纪60年代首次使用了这个术语。从本质上来说,一个进程就是一个正在执行的程序。进程是由程序代码和相关数据还有...

    linux多线程端口扫描器原理与实现

    进程与线程
       进程的概念是操作系统结构的基础。Multics的设计者在20世纪60年代首次使用了这个术语。从本质上来说,

    一个进程就是一个正在执行的程序。进程是由程序代码和相关数据还有进程控制块组成。从概念上说,进程包

    含了一下两个方面的内容:资源所有权和调度/执行。对于基本进程概念的两点进行区分。就形成了线程的概念。

    线程是进程中的一个实体,是被系统独立调度和分派的基本单位,进程中的所有线程共享该进程的状态和资源,

    它们驻留在同一块地址空间中,并且可以访问到相同的数据。

    Linux下多线程库
       Linux系统下的多线程遵循POSIX线程接口,称为pthread。编写Linux下的多线程程序,
     需要使用头文件pthread.h,连接时需要使用库libpthread.a。
     端口扫描器的原理
        扫描器通过选用远程TCP/IP不同的端口的服务,并记录目标给予的回答,通过这种
    方法,可以搜集到很多关于目标主机的各种有用的信息。最基本的扫描技术是TCPconnect()
    扫描技术。操作系统提供的connect()系统调用,用来与每一个感兴趣
    的目标计算机的端口进行连接。如果端口处于侦听状态,那么connect()就能成功返回
    。否则,这个端口是不能用的,即没有提供服务。

     

    端口扫描基本原理图

     

    实现:

     

    实现效果图:

     

     

    该程序实现了多线程的端口扫描,刚刚开始,路还在继续!

     

     

     

    展开全文
  • 设计通过端口扫描器的研究来提高对计算机安全的认识。利用TCPconnect扫描原理,扫描主机通过TCP/IP协议的三次握手目标主机的指定端口建立一次完整的连接,如果目标主机该端口有回复,则说明该端口开放。利用...
  • 本次项目实习任务是设计实现一个简单的端口扫描器,它通过目标主机 TCP/IP端口建立连接并请求某些服务,记录目标主机应答,分析目标主机相关信息,从而发现目标主机某些内在安全弱点。即实现一个端口扫描...

    这次是大学期间第四次项目实习,主要是利用C#技术设计一个简单的多线程端口扫描器,能够扫描网段内的各端口信息。

    设计任务及目标

    本次项目实习的任务是设计并实现一个简单的端口扫描器,它通过与目标主机 TCP/IP端口建立连接并请求某些服务,记录目标主机的应答,分析目标主机相关信息,从而发现目标主机某些内在的安全弱点。即实现一个端口扫描程序,判断指定的主机有哪些端口可以提供服务, 并把扫描得知的结果记录下来并显示出来。

    需求分析

    二十一世纪是信息化、网络化的世纪,信息是社会发展的重要资源。信息安全保障能力是一个国家综合国力、经济竞争实力和生存能力的重要组成部分,是世界各国在奋力攀登的制高点。国际标准化组织(ISO)对计算机系统安全的定义是:为数据处理系统建立和采用的技术和管理的安全保护,保护计算机硬件,软件和数据不因偶然和恶意的原因遭到破坏,更改和泄露。由此可以将计算机网络的安全理解为:通过采用各种技术和管理措施,使网络系统正常运行,从而确保网络数据的可用性、完整性和保密性。所以,建立网络安全保护措施的目的是确保经过网络传输和交换的数据不会发生增加、修改、丢失和泄露等。网络安全包括技术领域和非技术领域两大部分:非技术领域包括一些制度,政策,管理,安全意识,实体安全等方面的内容;技术领域包括隐患扫描,防火墙,入侵检测,访问控制,虚拟专用网,CA认证,操作系统等方面的内容。这些技术的目标是保证信息的可控性,可用性,保密性,完整性,和不可抵赖性。其中端口扫描属于安全探测技术范畴,对应于网络攻击技术中的网络信息收集技术。

    基本介绍

    1. 端口定义
      首先先明确端口的定义。端口是由计算通信协议TCP/IP协议定义的。其中规定,用IP地址和端口作为套接字,它代表TCP链接的一个连接端,一般称为socket,具体来说,就是用[ip:端口]来定位一台主机中的进程。可以做这样的比喻,端口相当于两台计算机进程间的大门,可随便定义,其目的只是为了让两台计算机能找到对方的进程。计算机就想一座大楼,这个大楼有好多入口(端口),进到不同的入口中就可以找到不同的公司(进程)。我们这里所说的端口,不是计算机硬件的 i/o端口,而是软件形式上的概念。服务器可以向外提供多种服务,比如,一台服务器可以同时是 web服务器,也可以是 ftp服务器,同时,它也可以是邮件服务器。为什么一台服务器可以同时提供那么多的服务呢?其中一个很主要的方面,就是各种服务采用不同的端口分别提供不同的服务。根据提供服务类型的不同,端口分为两种,一种是 tcp端口,一种是 udp端口。计算机之间相互通信的时候,分为两种方式:一种是发送信息以后, 可以确认信息是否到达,也就是有应答的方式,这种方式大多采用tcp 协议;一种是发送以后就不管了,不去确认信息是否到达,这种方式大多采用 udp协议。对应这两种协议的服务提供的端口,也就分为 tcp端口和 udp端口。这样,入侵者可以通过扫描器对目标主机的端口进行扫描,即可确定哪些端口是开放的,包括网络协议和各种应用监听的窗口。从开放的端口,入侵者可以知道目标主机大致提供了哪些服务,进而猜测可能存在的漏洞,进而进行攻击。
    2. 常见端口介绍
      端口:21。服务:FTP
      说明:FTP服务器所开放的端口,用于上传,下载。最常见的攻击者用于寻找打开 anonymous的FTP 服务器的方法。这些服务器带有可读写的目录。
      端口:23。服务:Telnet
      说明:远程登录,入侵者在搜索远程登录 UNIX 的服务。大多数情况下扫描这一端口是为了找到机器运行的操作系统。还有使用其他技术,入侵者也会找到密码。
      端口:25。服务:SMTP
      说明:SMTP服务器所开放的端口,用于发送邮件。入侵者寻找 SMTP 服务器是为了传递他们的 SPAM。入侵者的帐户被关闭,他们需要连接到高带宽的 E-MAIL 服务器上,将简单的信息传递到不同的地址。
      端口:53。服务:DNS
      说明:DNS服务器所开放的端口,入侵者可能是试图进行区域传递(TCP),欺骗DNS(UDP)或隐藏其他的通信。因此防火墙常常过滤或记录此端口。
      端口:80。服务:HTTP
      说明:用于网页浏览。
      端口:110。服务:POP3
      说明:POP3 用于客户端访问服务器端的邮件服务。POP3服务有许多公认的弱点。关于用户名和密码交换缓冲区溢出的弱点至少 有20个(这意味着Hacker可以在真正登陆前进入系统)。成功登陆后还有其它缓冲区溢出错误。
      端口:443。服务:HTTPS
      说明:443端口即网页浏览端口,主要是用于HTTPS服务,是提供加密和通过安全端口传输的另一种HTTP。在一些对安全性要求较高的网站,比如银行、证券、购物等,都采用HTTPS服务,这样在这些网站上的交换信息其他人都无法看到,保证了交易的安全性。
    3. 扫描技术
      随着 Internet 的不断发展,信息技术已成为促进经济发展,社会进步的巨大推动力。端口扫描技术是网络安全扫描技术一个重要的网络安全技术。与防火墙,入侵检测系统互相配合,能够有效提高网络的安全性。通过扫描能自动检测远端或本地主机系统信息,包括主机的基本信息(如计算机名、域名、组名、操作系统型等),服务信息,用户信息以及漏洞信息,它的重要性在于能够对网络进行安全评估,及时发现安全隐患,防患于未然。网络的安全状况取决于网络中最薄弱的环节,任何疏忽都有可能引入不安全的因素,最有效的方法是定期对网络系统进行安全分析,及时发现并修正存在的脆弱,保证系统安全。国内的扫描技术是在国外的扫描器基础上发展起来的。其中有一些专门从事安全技术的公司。这些公司的扫描器以硬件为主,其特点是执行速度快,不像软件一样受到安装主机系统的限制。然而对于更多的基于主机的端口扫描而言,简单,实用,可靠才是它们的长处。扫描器是一种自动检测远程或本地主机安全性弱点的程序,通过使用扫描器你可以不留痕迹的发现远程服务器的各种 TCP 端口的分配。这就能让我们间接的或直观的了解到远程主机所存在的安全问题。为了保证网络中计算机的安全性,必须采取主动策略,快速,及时,准确,安全的检测出网络中计算机及防火墙开放的和未开放的端口。计算机端口扫描技术就是这种主动防御策略实现的重要技术手段。扫描器采用模拟攻击的形式对目标可能存在的已知安全漏洞进行逐项检查。目标可以是工作站、服务器、交换机、数据库应用等各种对象。然后根据扫描结果向系统管理员提供周密可靠的安全性分析报告,为提高网络安全整体水平产生重要依据。在网络安全体系的建设中,安全扫描工具花费低、效果好、见效快、与网络的运行相对对立、安装运行简单,可以大规模减少安全管理员的手工劳动,有利于保持全网安全政策的统一和稳定。
    4. 扫描原理
      端口扫描的原理也不复杂,简单来说,就是通过向目的端口发送探测数据包,根据收到的响应来判断端口的状态。
    5. 扫描类型
      端口扫描的类型也有很多,常见的就有TCP SYN扫描,TCP connect扫描,秘密扫描,其他扫描。此次我选择的是第二种扫描方式:TCP connect扫描。我们可以利用系统提供的connect()用来与每一个目标计算机的端口进行连接。该扫描的优点:实现简单,对操作者的权限没有严格要求。另一优点是扫描速度快。如果对每个目标端口以线性的方式,使用单独的connect()调用,可以通过同时打开多个套接字,从而加速扫描。缺点就是会在目标主机的日志记录中留下痕迹,易被发现,并且数据包会被过滤掉。目标主机的logs文件会显示一连串的连接和连接出错的服务信息,并且能很快地使它关闭。
    6. 多线程技术
      每个正在系统上运行的程序都是一个进程。每个进程包含一到多个线程。进程也可能是整个程序或者是部分程序的动态执行。线程是一组指令的集合,或者是程序的特殊段,它可以在程序里独立执行。也可以把它理解为代码运行的上下文。所以线程基本上是轻量级的进程,它负责在单个程序里执行多任务。通常由操作系统负责多个线程的调度和执行。线程是程序中一个单一的顺序控制流程。在单个程序中同时运行多个线程完成不同的工作,称为多线程。线程和进程的区别在于,子进程和父进程有不同的代码和数据空间,而多个线程则共享数据空间,每个线程有自己的执行堆栈和程序计数器为其执行上下文。多线程主要是为了节约CPU时间,发挥利用,根据具体情况而定。线程的运行中需要使用计算机的内存资源和CPU。多线程是为了同步完成多项任务,不是为了提高运行效率,而是为了提高资源使用效率来提高系统的效率。线程是在同一时间需要完成多项任务的时候实现的。

    系统分析

    本次课设设计的是一个简单的端口扫描器,该扫描器应具备的基本功能有:
    (1)支持多线程模式扫描端口;
    (2)能对单个指定主机进行扫描或扫描指定网段内的主机;
    (3)能扫描特定的部分端口或对指定的端口段内的端口进行逐个扫描;
    (4)能够显示所开放端口的服务名称。所使用的扫描方法为TCP connect扫描,该扫描的具体实现过程为:TCP connect端口扫描服务端与客户端建立连接成功(目标端口开放)的过程如下: ① Client端发送SYN;② Server端返回SYN/ACK,表明端口开放;③ Client端返回ACK,表明连接已建立;④ Client端主动断开连接。
    该扫描器工作流程为:
    (1)先确定扫描范围。即扫描目的主机的IP地址和需要扫描的端口范围;
    (2)确定好后给扫描器分配好线程数;
    (3)开始扫描端口,结束后将扫描结果显示出来,包括开放和未开放的端口,若端口开放则还可显示该端口提供的服务。
    (4)扫描结束。

    总体设计

    1. 主界面设计
      该端口扫描器是在VS2015环境下开发的,并使用C#创建主要界面和编写主要功能函数。
      端口扫描器主界面如下:
      主界面设计
      主界面布局主要有:IP地址设置,端口范围选择,线程数设置(默认20),扫描进度条,扫描过程显示以及扫描结果显示,底部的当前扫描时间显示,还有开始扫描按钮和停止扫描按钮。此外还有三个重要选项框,分别是单主机扫描模式选择,单端口扫描模式选择,只显示开放端口选择。
      当选中单主机扫描模式时,IP地址设置的第二个编辑框消失:
      单主机扫描
      当选中单端口扫描模式时,端口范围设置的第二个编辑框消失:
      单端口扫描
    2. 扫描器工作流程图
      流程图
      说明:该扫描器可以对单个主机单个端口进行扫描也可以对网段内主机和范围内端口进行逐个扫描,确定扫描IP和扫描端口后点击开始扫描按钮即可对相应IP下的端口进行侦听,并返回端口状态,如果端口开放则同时返回端口服务,扫描结束后线程停止。

    详细设计

    1. 主要数据结构
    private string ipStart; //起始IP地址
    private string ipEnd; //结束IP地址
    private int portStart; //开始端口
    private int portEnd; //结束端口
    private int numThread=20; //分配线程数,默认为20
    private int overtime=20; //超时限制20ms
    private Thread t; //定义一个线程
    rivate Thread scanthread; //端口扫描线程
    private bool[] done = new bool[65536];  
    List<string> str; //扫描结果集
    
    1. 主要函数说明
    private void Form1_Load(object sender, EventArgs e)//主界面加载函数
    private void checkBox1_CheckedChanged(object sender, EventArgs e)
    //单主机扫描模式选择函数
    private void checkBox2_CheckedChanged(object sender, EventArgs e)
    //单端口扫描模式选择函数
    private void button1_Click(object sender, EventArgs e)
    //开始扫描按钮函数
    private void button2_Click(object sender, EventArgs e)
    //停止扫描按钮函数
    public void wait()//扫描IP地址函数
    public string State(int i)//判断端口状态函数
    public string Service(int i)//返回开放端口服务函数
    public void Scan(object Point)//扫描端口函数
    
    1. 扫描IP函数
      利用PingReply对象试探目标主机,如果超时则表示不可达,否则连通
    //利用PingReply对象试探目标主机
                    Ping ping = new Ping();  //初始化一个Ping类实例
                    PingReply reply = ping.Send(IPAddress.Parse(ip + q), overTime);  //调用同步Send方法发送消息,将返回结果保存至PingReply实例
                    if (reply.Status == IPStatus.Success)  //如果能够Ping通,则说明远端主机开放
                    {
                        richTextBox1.Text += "   IP地址: " + ip + q + "\n";   
                        IPHostEntry host = Dns.GetHostEntry(ip + q);  //取得该IP主机信息
                        richTextBox1.Text += "   主机名: "+ host.HostName + "\n";
                    }
                    else
                    {
                        listBox1.Items.Add(ip + q + "          " + "-" + "       " + "-" + "   " + "              - \n");
                        richTextBox1.Text += ip + q + "   不可达\n";
                        continue;
                    }
    //Ping结束
    
    1. 扫描端口函数
      利用系统提供的connect()函数用来与每一个目标计算机的端口进行连接。
    public void Scan(object Point)
            {
                IPEndPoint IPPoint = (IPEndPoint)Point; //使用IPEndPoint类对象获取终结点的IP地址和端口号
                try
                {
                    TcpClient tcp = new TcpClient(); //创建一个TcpClient类
                    tcp.Connect(IPPoint); //调用Connect方法,使用指定的IP地址将客户端连接到TCP主机上
                    if (tcp.Connected)  //如果连接上,证明此端口为开放状态
                        str.Add(Convert.ToString(IPPoint.Port));
                }
                catch
                {
                    ;
                }
            }
    
    1. 多线程函数
    //IP存在,则开子线程开始端口扫描,端口数由textbox1,textbox2的差值决定
                    Thread[] tharr;  //创建多线程
                    if (numThread < (portEnd - portStart + 1))
                    {
                        tharr = new Thread[portEnd - portStart + 1];
                    }
                    else
                    {
                        tharr = new Thread[numThread];
                    }
    bool iscon = true;  //第一个线程等待时间
                    for (int i = 0; i < tharr.Length; i++)
                    {
                        if (tharr[i] == null)  //如果端口扫不到,说明未开放,跳过继续
                            continue;
                        while (tharr[i].IsAlive && iscon)  //端口存在,对端口超时设置时间(目前200毫秒),一直等待此ip所有线程执行完毕才扫描下个ip
                        {
                            Thread.Sleep(200);
                            iscon = false;  //第一个线程给200ms等待时间,其他线程由于同步执行的,所以没等待时间了,如果线程还没执行完,说明此端口不可达
                        }
                    }
    

    使用说明

    运行程序启动端口扫描器,进入扫描器主界面:
    主界面
    (1)IP段端口扫描
    当需要扫描的是IP地址段时,按界面提示输入IP地址段范围以及需要扫描的端口范围,然后可以选择只显示开放端口,完成后点击开始扫描按钮,测试结果如下:
    扫描成功
    测试的IP段为10.21.123.226-10.21.123.228,扫描的端口范围是0-300号端口,分配线程数为20,点击开始扫描按钮后等待数秒扫描完成。可以看到扫描各IP地址的端口的具体过程,以及扫描结果显示的端口状态和它们提供的服务。

    (2)单主机单端口扫描模式
    当需要扫描的是单主机时,选择单主机模式选项,端口范围也选择单端口模式,完成后点击开始扫描按钮,测试结果如下:
    扫描成功
    测试的IP地址为10.21.123.226,端口选择139端口,分配线程数为20.点击开始扫描按钮后等待数秒扫描完成。可以看到扫描结果为139端口状态为open,该端口提供的是NetBIOS/SMB服务。

    (3)只显示开放端口
    该扫描器还可以只显示开放端口以及它们所提供的服务,测试结果如下:
    扫描成功
    可以看到10.21.123.226的0-300端口中开放的只有80,135,139端口,提供的服务分别是HTTP协议代理服务,RPC(远程过程调用)服务,NetBIOS/SMB服务。

    (4)错误提示
    当不按照要求输入相应的IP地址和端口范围时,扫描器将出现错误提示,如下所示:

    扫描失败

    总结

    1. 任务完成情况
      本次设计任务的基本要求已经完成,即实现了一个简单的端口扫描器,能对单IP地址或IP地址段的单端口或端口范围进行扫描,并对开放端口显示它们所提供的服务。
    2. 特色与不足
      该端口扫描器具有以下几个特色:
      (1)扫描器底部有当前的扫描时间;
      (2)可以切换单主机扫描模式和单端口扫描模式;
      (3)可以设置只显示开放端口;
      (4)有扫描进度条较为直观的展示当前的扫描进度;
      (5)有错误提示。
      不足的地方也有不少,比如界面有点简单,可以说是简陋,没有太多自己的设计。还有由于采用的是TCP connect扫描方式,所以不可避免的有它自身带有的缺陷,即容易被防火墙过滤掉。
    3. 所遇到的问题
      本次课程设计中自己也遇到了不少问题,比如一开始只是设想采用TCP connect这种扫描方式,但具体代码方面如何实现却是没有头绪。还比如多线程的实现又是具体怎么操作。等等这些,自己只能通过网上跟参考书上的资料一点一点摸索。

    参考文献

    [1] 谢希仁.《计算机网络》[M].电子工业出版社,2013.6第6版
    [2] 明日科技.《C#从入门到精通》[M].清华大学出版社,2012.9第3版
    [3] 邓宇军.《C# 2.0程序设计教程》[M].清华大学出版社,2005.12第3版
    [4] 肖微.《端口扫描技术的原理》[J].网络安全技术及应用,2006,(7):32-41

    展开全文
  • 老师提供了一个完整的线程版本的端口扫描器,于是我就自己写了一个单线程版本的端口扫描器,图形界面模仿了老师的给出的设计 老师的版本在progerssbox下方还用了三个隐藏的lable来显示端口号和当前扫描的端口,...

    一、创建工程

    Visual Studio 2015中新建一个工程,选择windows窗体应用程序。
    在这里插入图片描述

    二、图形界面设计

    老师提供了一个完整的多线程版本的端口扫描器,于是我就自己写了一个单线程版本的端口扫描器,图形界面模仿了老师的给出的设计

    在这里插入图片描述
    老师的版本在progerssbox下方还用了三个隐藏的lable来显示端口号和当前扫描的端口,我这里没有放。

    三、单线程端口扫描

    代码如下

    using System;
    using System.Windows.Forms;
    using System.Net.Sockets;
    
    namespace singlesanapp4
    {
        public partial class Form1 : Form
        { //自定义变量
            
            private int port;//记录当前扫描的端口号
            private string Address;//记录扫描的系统地址
            private bool[] done = new bool[65536];//记录端口的开放状态
            private int start;//记录扫描的起始端口
            private int end;//记录扫描的结束端口
            private bool OK;
            public Form1()
            {
                InitializeComponent();
                listBox1.Items.Add("欢迎使用端口扫描器 v1.0(单线程)");
                this.Text = "端口扫描器 v1.0";
            }
           
    
            private void button1_Click(object sender, EventArgs e)
            {
               
                progressBar1.Minimum = Int32.Parse(textBox2.Text);
                progressBar1.Maximum = Int32.Parse(textBox3.Text);
                listBox1.Items.Clear();
                listBox1.Items.Add("端口扫描器v1.0.(单线程)");
                listBox1.Items.Add("");
                PortScan();
    
            }
            private void PortScan()
            {
                start = Int32.Parse(textBox2.Text);
                end = Int32.Parse(textBox3.Text);
                //判断输入端口是否合法
                if ((start >= 0 && start <= 65536) && (end >= 0 && end <= 65536) && (start <= end))
                {
                    listBox1.Items.Add("开始扫描:这个过程可能需要等待几分钟!");
                    Address = textBox1.Text;
                    for (int i = start; i <= end; i++)
                    {
                        port = i;
                        Scan();
                        progressBar1.Value = i;
                       
                    }
                    while (!OK)
                    {
                        OK = true;
                        for (int i = start; i <= end; i++)
                        {
                            if (!done[i])
                            {
                                OK = false;
                                break;
                            }
                        }
                    }
                    listBox1.Items.Add("扫描结束!");
                }
                else
                {
                    MessageBox.Show("输入错误,端口范围为[0,65536]");
                }
            }
            //连接端口
            private void Scan()
            {
                int portnow = port;
                done[portnow] = true;
                TcpClient objTCP = null;
                try
                {
                    objTCP = new TcpClient(Address, portnow);
                    listBox1.Items.Add("端口" + portnow.ToString() + "开放");
                }
                catch
                {
    
                }
    
            }
        }
    }
    

    运行效果如下
    在这里插入图片描述
    在这里插入图片描述

    可以看到是很慢的,我特意只扫描了五个端口,花了七秒左右的时间。

    四、多线程说明和方法

    线程(Thread)是进程中的基本执行单元,是操作系统分配CPU时间的基本单位,一个进程可以包含若干个线程,在进程入口执行的第一个线程被视为这个进程的主线程。

    多线程编程的第一步,创建线程。创建线程其实是增加了一个控制流程,使得同一进程中存在多个控制流程并发或者并行执行。有时候我们需要多个线程相互协作来执行,这时需要线程间同步。详见多线程编程

    创建多线程的步骤:
    1、编写线程所要执行的方法
    2、实例化Thread类,并传入一个指向线程所要执行方法的委托。(这时线程已经产生,但还没有运行)
    3、调用Thread实例的Start方法,标记该线程可以被CPU执行了,但具体执行时间由CPU决定,详见c#多线程

                 //创建无参的线程
                Thread thread1 = new Thread(new ThreadStart(Thread1));
                 //调用Start方法执行线程
                 thread1.Start();
    
    /// 创建无参的方法
             /// </summary>
             static void Thread1()
             {
                 Console.WriteLine("这是无参的方法");
             }
    

    五、多线程端口扫描

    老师给的代码是用老版本的VS写的,自动生成的代码 放在了program.cs里,使代码显得冗长,我这里就放各部分核心代码展示一下。

    在这里插入图片描述

    这里有三个隐藏的lable,用来在运行后显示数字

    1、窗口初始化

           private void lbResult_SelectedIndexChanged(object sender, EventArgs e)
            {
                throw new NotImplementedException();
            }
    
            [STAThread]
            static void Main()
            {
               // Control.CheckForIllegalCrossThreadCalls = false;
                Application.Run(new Form1());
            }
    
            private void txtStart_TextChanged(object sender, System.EventArgs e)
            {
                //获取输入的起始端口值
                lblStart.Text = txtStart.Text;
            }
            private void txtEnd_TextChanged(object sender, System.EventArgs e)
            {
                //获取输入的接受端口值
                lblStop.Text = txtEnd.Text;
            }
    

    2、button 按钮 click 事件(创建线程,并创建ThreadStart委托对象)

     private void btnScan_Click(object sender, System.EventArgs e)
            {
                //创建线程,并创建ThreadStart委托对象
                Thread process = new Thread(new ThreadStart(PortScan));
                process.Start();
                //显示端口扫描的范围
                progressBar1.Minimum = Int32.Parse(txtStart.Text);
                progressBar1.Maximum = Int32.Parse(txtEnd.Text);
                //显示框初始化
                lbResult.Items.Clear();
                lbResult.Items.Add("端口扫描器 v1.0.");
                lbResult.Items.Add("");
            }
    

    3、线程委托对象的无参数方法Portscan

     private void PortScan()
            {
                start = Int32.Parse(txtStart.Text);
                end = Int32.Parse(txtEnd.Text);
                //检查输入范围合法性
                if ((start >= 0 && start <= 65536) && (end >= 0 && end <= 65536) && (start <= end))
                {
                    lbResult.Items.Add("开始扫描... (可能需要请您等待几分钟)");
                    Addr = txtAddr.Text;
                    for (int i = start; i <= end; i++)
                    {
                        port = i;
                        //使用该端口的扫描线程
                        scanThread = new Thread(new ThreadStart(Scan));
                        scanThread.Start();
                        //使线程睡眠
                        System.Threading.Thread.Sleep(100);
                        progressBar1.Value = i;
                        lblNow.Text = i.ToString();
                    }
                    //未完成时情况
                    while (!OK)
                    {
                        OK = true;
                        for (int i = start; i <= end; i++)
                        {
                            if (!done[i])
                            {
                                OK = false;
                                break;
                            }
                        }
                        System.Threading.Thread.Sleep(1000);
                    }
                    lbResult.Items.Add("扫描结束!");
                }
                else
                {
                    MessageBox.Show("输入错误,端口范围为[0-65536]");
                }
            }
    

    4、线程委托对象的无参方法Scan

     private void Scan()
            {
                int portnow = port;
                //创建线程变量
                Thread Threadnow = scanThread;
                done[portnow] = true;
                //创建TcpClient对象,TcpClient用于为TCP网络服务提供客户端连接
                TcpClient objTCP = null;
                //扫描端口,成功则写入信息
                try
                {
                    //用TcpClient对象扫描端口
                    objTCP = new TcpClient(Addr, portnow);
                    lbResult.Items.Add("端口 " + portnow.ToString() + " 开放!");
                }
                catch
                {
                }
            }
    

    就这样自运行会中断,原因是未允许跨线程调用,Vs直接提供了微软官方的问题说明
    那么解决办法之一就是不再捕获对错误线程的调用,不安全但是比较简单(主要是我们这个程序简单,没那么容易出安全性问题)
    向public Form1()中添加一句

     CheckForIllegalCrossThreadCalls = false;
    

    官方推荐的解决办法是Invoke方法:将Invoke方法与委托一起使用,如果线程ID不同,它将使用主线程的委托来调用Control.Invoke方法,从而对控件进行实际调用。

    this.Invoke(new EventHandler(delegate
    	{
    	
    	}));
    

    运行情况如下
    在这里插入图片描述
    可以看到运行起来快了很多。

    六、总结

    多线程是一个程序员的基本功吧,还要多练习运用。程序员应该追求用各种方法优化代码。

    展开全文
  • TCP编程-端口扫描器与网游客户端端口扫描器准备端口扫描单线程线程总结参考网游客户端创建新项目界面及代码实现显示图片参考 端口扫描器 准备 创建一个新项目 生成项目名称为Port_Test 界面设计 端口扫描...

    端口扫描器

    准备

    • 创建一个新的项目
      在这里插入图片描述
      生成的项目名称为Port_Test
      在这里插入图片描述
    • 界面设计

    在这里插入图片描述

    端口扫描

    单线程

    • 代码
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace Port_Test
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void label1_Click(object sender, EventArgs e)
            {
    
            }
            //主机地址
            private string hostAddress;
            //起始端口
            private int start;
            //终止端口
            private int end;
            //端口号
            private int port;
            //定义线程对象
            private Thread scanThread;
    
            private void textBox1_TextChanged(object sender, EventArgs e)
            {
    
            }
    
            private void textBox4_TextChanged(object sender, EventArgs e)
            {
    
            }
    
            private void label4_Click(object sender, EventArgs e)
            {
    
            }
            private bool decideAddress()
            {
                //判断端口号是否合理
                if ((start >= 0 && start <= 65536) && (end >= 0 && end <= 65536) && (start <= end))
                    return true;
                else
                    return false;
            }
            private void PortScan()
            {
                double x;
                string xian;
                //显示扫描状态
                textBox4.AppendText("开始扫描...(可能需要请您等待几分钟)" + Environment.NewLine + Environment.NewLine);
                //循环抛出线程扫描端口
                for (int i = start; i <= end; i++)
                {
                    x = (double)(i - start + 1) / (end - start + 1);
                    xian = x.ToString("0%");
                    port = i;
                    //调用端口i的扫描操作
                    Scan();
                    //进度条值改变
                    label4.Text = xian;
                    label4.Refresh();
                    progressBar1.Value = i;
                }
                textBox4.AppendText(Environment.NewLine + "扫描结束!" + Environment.NewLine);
                //输入框textbox只读属性取消
                textBox1.ReadOnly = false;
                textBox2.ReadOnly = false;
                textBox3.ReadOnly = false;
            }
            private void Scan()
            {
                int portnow = port;
                //创建TcpClient对象,TcpClient用于为TCP网络服务提供客户端连接
                TcpClient objTCP = null;
                try
                {
                    //用于TcpClient对象扫描端口
                    objTCP = new TcpClient(hostAddress, portnow);
                    //扫描到则显示到显示框
                    textBox4.AppendText("端口 " + port + " 开放!" + Environment.NewLine);
                }
                catch
                {
                    //未扫描到,则会抛出错误
                }
            }
            private void button1_Click(object sender, EventArgs e)
            {
                try
                {
                    //初始化
                    textBox4.Clear();
                    label4.Text = "0%";
                    //获取ip地址和始末端口号
                    hostAddress = textBox1.Text;
                    start = Int32.Parse(textBox2.Text);
                    end = Int32.Parse(textBox3.Text);
                    if (decideAddress())
                    {
                        //让输入的textbox只读,无法改变
                        textBox1.ReadOnly = true;
                        textBox2.ReadOnly = true;
                        textBox3.ReadOnly = true;
                        //设置进度条的范围
                        progressBar1.Minimum = start;
                        progressBar1.Maximum = end;
                        //显示框显示
                        textBox4.AppendText("端口扫描器 v1.0.0" + Environment.NewLine + Environment.NewLine);
                        //调用端口扫描函数
                        PortScan();
                    }
                    else
                    {
                        //若端口号不合理,弹窗报错
                        MessageBox.Show("输入错误,端口范围为[0-65536]!");
                    }
                }
                catch
                {
                    //若输入的端口号为非整型,则弹窗报错
                    MessageBox.Show("输入错误,端口范围为[0-65536]!");
                }
            }
        }
    }
    
    
    • 运行结果
      在这里插入图片描述

    多线程

    • 代码
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace Port_Test
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
                CheckForIllegalCrossThreadCalls = false;
            }
    
            private void label1_Click(object sender, EventArgs e)
            {
    
            }
            //主机地址
            private string hostAddress;
            //起始端口
            private int start;
            //终止端口
            private int end;
            //端口号
            private int port;
            //定义线程对象
            private Thread scanThread;
            //定义端口状态数据(开放则为true,否则为false)
            private bool[] done = new bool[65526];
            private bool OK;
            private void textBox1_TextChanged(object sender, EventArgs e)
            {
    
            }
    
            private void textBox4_TextChanged(object sender, EventArgs e)
            {
    
            }
    
            private void label4_Click(object sender, EventArgs e)
            {
    
            }
            private bool decideAddress()
            {
                //判断端口号是否合理
                if ((start >= 0 && start <= 65536) && (end >= 0 && end <= 65536) && (start <= end))
                    return true;
                else
                    return false;
            }
            private void PortScan()
            {
                double x;
                string xian;
                //显示扫描状态
                textBox4.AppendText("开始扫描...(可能需要请您等待几分钟)" + Environment.NewLine + Environment.NewLine);
                //循环抛出线程扫描端口
                for (int i = start; i <= end; i++)
                {
                    x = (double)(i - start + 1) / (end - start + 1);
                    xian = x.ToString("0%");
                    port = i;
                    //使用该端口的扫描线程
                    scanThread = new Thread(new ThreadStart(Scan));
                    scanThread.Start();
                    //使线程睡眠
                    System.Threading.Thread.Sleep(100);
                    //进度条值改变
                    label4.Text = xian;
                    progressBar1.Value = i;
                }
                while (!OK)
                {
                    OK = true;
                    for (int i = start; i <= end; i++)
                    {
                        if (!done[i])
                        {
                            OK = false;
                            break;
                        }
                    }
                    System.Threading.Thread.Sleep(1000);
                }
                textBox4.AppendText(Environment.NewLine + "扫描结束!" + Environment.NewLine);
                textBox1.ReadOnly = false;
                textBox2.ReadOnly = false;
                textBox3.ReadOnly = false;
            }
            private void Scan()
            {
                int portnow = port;
                //创建线程变量
                Thread Threadnow = scanThread;
                //扫描端口,成功则写入信息
                done[portnow] = true;
                //创建TcpClient对象,TcpClient用于为TCP网络服务提供客户端连接
                TcpClient objTCP = null;
                try
                {
                    //用于TcpClient对象扫描端口
                    objTCP = new TcpClient(hostAddress, portnow);
                    //扫描到则显示到显示框
                    textBox4.AppendText("端口 " + port + " 开放!" + Environment.NewLine);
                }
                catch
                {
                    //未扫描到,则会抛出错误
                }
            }
            private void button1_Click(object sender, EventArgs e)
            {
                try
                {
                    //初始化
                    textBox4.Clear();
                    label4.Text = "0%";
                    //获取ip地址和始末端口号
                    hostAddress = textBox1.Text;
                    start = Int32.Parse(textBox2.Text);
                    end = Int32.Parse(textBox3.Text);
                    if (decideAddress())
                    {
                        textBox1.ReadOnly = true;
                        textBox2.ReadOnly = true;
                        textBox3.ReadOnly = true;
                        //创建线程,并创建ThreadStart委托对象
                        Thread process = new Thread(new ThreadStart(PortScan));
                        process.Start();
                        //设置进度条的范围
                        progressBar1.Minimum = start;
                        progressBar1.Maximum = end;
                        //显示框显示
                        textBox4.AppendText("端口扫描器 v1.0.0" + Environment.NewLine + Environment.NewLine);
                    }
                    else
                    {
                        //若端口号不合理,弹窗报错
                        MessageBox.Show("输入错误,端口范围为[0-65536]!");
                    }
                }
                catch
                {
                    //若输入的端口号为非整型,则弹窗报错
                    MessageBox.Show("输入错误,端口范围为[0-65536]!");
                }
            }
        }
    
    }
    
    • 结果
      在这里插入图片描述

    总结

    • 虽然两者执行结果一模一样,但是多线程的执行速度远远大于单线程

    参考

    https://blog.csdn.net/ssj925319/article/details/109688125

    网游客户端

    创建新项目

    • 新建一个新的项目

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

    界面及代码实现

    • 界面
      在这里插入图片描述
    • 编辑button进入游戏的方法
      源码
    try
                {
                    //实例化
                    tcpClient = new TcpClient();
                    //向指定的IP地址的服务器发出连接请求
                    tcpClient.Connect("10.160.52.106", 3900);
                    //获取网络传输流
                    stream = tcpClient.GetStream();
                    //接受数据并转化为字符串
                    byte[] data = new byte[1024];
                    int receive = stream.Read(data, 0, 1024);
                    string msg = Encoding.Default.GetString(data, 0, receive);
                    //去除字符串中的终端转义字符
                    //msg = strDelete(msg);
                    //显示出来
                    textBox2.AppendText(msg);
                }
                catch
                {
                    textBox2.AppendText("服务器未启动" + Environment.NewLine);
                }
            }
    
            /*****************
             * 去除终端转移字符
             *****************/
            private string strDelete(string str)
            {
                int flag = -1, de = 0;
                for (int i = 0; i < str.Length; i++)
                {
                    if (str[i] == ' ')
                    {
                        flag = i;
                    }
                    if (flag != -1)
                    {
                        de++;
                    }
                    if (str[i] == 'm' && flag != -1)
                    {
                        str = str.Remove(flag, de);
                        i = flag - 1;
                        flag = -1;
                        de = 0;
                    }
                }
                return str;
            }
    
    • 结果
      在这里插入图片描述
    • 信息交互

    实现功能:客户端要发给服务器的数据,通过 textbox 输入,然后点击 button 发送出去,并将服务器端返回结果显示在 textbox 中。

    源码

     //获取textBox1内的文本内容
        string msg = textBox1.Text + "\n";
        //将文本内容转化成比特流并发送给服务器
        byte[] data = new byte[1024];
        data = Encoding.Default.GetBytes(msg);
        stream.Write(data, 0, data.Length);
        //接收服务器端传来的数据流并转化为字符串
        byte[] data1 = new byte[1024];
        int receive = stream.Read(data1, 0, 1024);
        msg = Encoding.Default.GetString(data1, 0, receive);
        //去除字符串中的终端转义字符
        msg = strDelete(msg);
        //清除显示框之前的内容
        textBox2.Clear();
        //显示数据
        textBox2.AppendText(msg);
        //刷新输入框
        textBox1.Clear();
        //将光标集中到输入框中
        textBox1.Focus();
    
    • 结果
      在这里插入图片描述
      在这里插入图片描述
    • 背景音乐添加

    音量控制代码

    private void trackBar1_Scroll(object sender, EventArgs e)
            {
                //控制音量大小
                axWindowsMediaPlayer1.settings.volume = trackBar1.Value;
                //控制音量显示
                label1.Text = trackBar1.Value.ToString();
            }
    

    此段带代码添加在button_2功能实现里

    trackBar1.Value = 50;
                label1.Text = "50";
                //字符串存储音乐路径
                string s = @"C:\Users\11784\source\repos\GameClient\Music\TaylorSwift-HowYouGetTheGirl.mp3";
                //设置为循环播放
                axWindowsMediaPlayer1.settings.setMode("loop", true);
                //设置初始音乐的音量大小(范围:0——100)
                axWindowsMediaPlayer1.settings.volume = 50;
                //设置播放歌曲的路径
                axWindowsMediaPlayer1.URL = s;
    

    显示图片

    • 在初始化函数中添加如下代码
    			tring picturePath = @"C:\Users\11784\source\repos\GameClient\picture\2.jpg";
                //设置图片填充
                pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
                pictureBox1.Image = Image.FromFile(picturePath);
    
    • 结果
      在这里插入图片描述

    参考

    https://blog.csdn.net/ssj925319/article/details/109746267

    展开全文
  •  cc实例196 隐藏IE浏览器的右键关联菜单   cc实例197 设置IE的默认主页   cc实例198 清空上网历史记录   7.3 文件控制   cc实例199 如何建立文件关联   cc实例200 控制光驱的自动运行功能   7.4...
  • 13.3.2 扫描服务器打开的端口 331 13.3.3 发送和接收数据 333 13.3.4 获得无线路由分配给手机IP地址 334 13.3.5 设置Socket选项 335 13.4 服务端Socket 339 13.4.1 手机服务器的实现 339 13.4.2 利用...
  • 同时,该天线可通过频率变化实现波束扫描与多波束功能。设计了波导缝隙单元结构、19单元线阵及19×12面阵。为了抑制栅瓣产生,利用介电常数为2.3聚四氟乙烯部分填充于波导腔中。根据天线结构特殊性设计了波导/...
  • 包括开放式通信模型、TCP/IP通信模型、IP网络中命名和寻址机制、地址解析及反向地址解析协议、DNS域字服务器、WINS、地址发现协议、IPv6、IP网络中路由协议(RIP、OSPF等)、互联网打印协议、LDAP目录服务、远程...
  • 5.11 用DS18B20MAX6951驱动数码管设计的温度报警 5.12 用1602LCDDS18B20设计的温度报警 5.13 温控电机在L298驱动下改变速度方向运行 5.14 PG160128中文显示日期时间及带刻度显示当前温度 5.15 液晶屏...
  • 评价一台交換系统的设计水平和服务能力的一个章要指标 BICA的估算: 通常用一个线性模型怗算处理机的时间开销t t=ALBaN 上式中:A:是话务量无关的开销,而系统容量等固定参数有关 B:是处理一次呼叫的平均时间开销: ...
  • 你可以下面加一层 reed solomon 纠删码做 FEC,上面加一层类 RC4/Salsa20 做流加密,握手处再设计一套非对称密钥交换,底层 UDP 传输层再做一套动态路由系统,同时探测条路径,选最好路径进行传输。这些不同 ...
  • JAVA程序设计教程

    热门讨论 2013-09-07 21:15:19
    小课题:程序设计语言历史.....................................................................................13 第二章基本数据类型 ....................................................................
  • S091: 模拟单片机真实PC通信,通过SerialNull虚拟串口实现 S092: 通过USART发送字母例子 S093: MCU双机通信(基于自定通信协议) answer: 习题编程题答案 E091:编程题1答案 E092:编程题2答案 chapter10:第10...
  • 外,还增强了对更的32 位微处理器的支持,可以使嵌入式软件设计在软处理 器, FPGA 内部嵌入的硬处理器, 分立处理器之间无缝的迁移。使用了 Wishbone 开放总线连接器允许在FPGA 上实现的逻辑模块可以透明的连接到...
  • 第1章 窗体界面设计 1 1.1 菜单应用实例 2 实例001 带历史信息菜单 2 实例002 菜单动态合并 3 实例003 像开始菜单一样漂亮菜单 4 实例004 任务栏托盘菜单 5 实例005 可以拉伸菜单界面 5 实例...
  • 3.2 基于FPGA的Host与单片机并行通信系统的设计与实现 3.3 智能仪表与微型机的新型通信接口 3.4 80C51系列单片机波特率自动检测的通用程序 3.5 高性能双口RAM及其应用 3.6 双CPU系统中应用双端口...
  • 智能扫地机VHDL FPGA

    2012-07-12 19:02:40
    这次数字系统的用VHDL语言设计因工作量较以前的小系统以及大系统的设计难度都大得,故在将近半个学期的设计中,自己的体会非常深。 在刚拿到题目时,不能像设计大系统样立即就有思路,一开始想到的只有先将键盘上...
  • Visual.C#.编程精彩百例

    热门讨论 2013-01-07 12:09:39
    实例80 网络端口扫描器 实例81 深入WinForms-地址簿应用(1) 实例82 深入WinForms--Image Viewer应用程序(2) 实例83 开饭时间提醒器(Meal Reminder) 实例84 服务器端C#实例 实例85 数字时钟设计技术 实例...
  • vc++ 应用源码包_1

    热门讨论 2012-09-15 14:22:12
    RangeScan扫描器源代码 ip地址扫描,发送邮箱。 ResizableLib 测试开源界面库Resizable。 RsPicture 自定义了一个图片库,然后引用测试。 SimplePlayer 简单媒体播放源码。 Skin_Combo_Box_demo 自绘Combox...
  • PCI.EXPRESS系统体系结构标准教材.pdf

    热门讨论 2013-02-17 16:21:16
    3.1.2 多端口设备承担路由负荷 3.1.3 端点路由能力有限 3.1.4 系统路由策略是可编程 3.2 两种类型本地链路流量 3.2.1 有序集 3.2.2 数据链路层数据包(dllp) 3.3 处理层数据包路由基础 3.3.1 用于访问4种地址...
  • 5.13 用驱动IC并联法倍增单片微机显示接口驱动功率的设计与应用 第六章 电源技术 6.1 Maxim直流直流变换特点及选用 6.2 电池组供电的电源系统芯片MAX714/715/716 6.3 由220V市电直接供电...
  • vc++ 应用源码包_6

    热门讨论 2012-09-15 14:59:46
    RangeScan扫描器源代码 ip地址扫描,发送邮箱。 ResizableLib 测试开源界面库Resizable。 RsPicture 自定义了一个图片库,然后引用测试。 SimplePlayer 简单媒体播放源码。 Skin_Combo_Box_demo 自绘Combox...
  • vc++ 应用源码包_2

    热门讨论 2012-09-15 14:27:40
    RangeScan扫描器源代码 ip地址扫描,发送邮箱。 ResizableLib 测试开源界面库Resizable。 RsPicture 自定义了一个图片库,然后引用测试。 SimplePlayer 简单媒体播放源码。 Skin_Combo_Box_demo 自绘Combox...
  • vc++ 应用源码包_5

    热门讨论 2012-09-15 14:45:16
    RangeScan扫描器源代码 ip地址扫描,发送邮箱。 ResizableLib 测试开源界面库Resizable。 RsPicture 自定义了一个图片库,然后引用测试。 SimplePlayer 简单媒体播放源码。 Skin_Combo_Box_demo 自绘Combox...
  • vc++ 应用源码包_4

    热门讨论 2012-09-15 14:38:35
    RangeScan扫描器源代码 ip地址扫描,发送邮箱。 ResizableLib 测试开源界面库Resizable。 RsPicture 自定义了一个图片库,然后引用测试。 SimplePlayer 简单媒体播放源码。 Skin_Combo_Box_demo 自绘Combox...
  • vc++ 应用源码包_3

    热门讨论 2012-09-15 14:33:15
    RangeScan扫描器源代码 ip地址扫描,发送邮箱。 ResizableLib 测试开源界面库Resizable。 RsPicture 自定义了一个图片库,然后引用测试。 SimplePlayer 简单媒体播放源码。 Skin_Combo_Box_demo 自绘Combox...
  • 本书从工程应用角度出发,通过8个典型应用实例,包括PCPC、PC单片机、PCPLC、PC远程I/O模块、PC智能仪器、PC无线数传模块、PcUSB数据采集模块等组成测控系统,利用SerialPort控件和MSComm控件...

空空如也

空空如也

1 2 3 4 5 6
收藏数 109
精华内容 43
关键字:

多端口扫描器的设计与实现