TCP-端口扫描与网游客户端

TCP-端口扫描与网游客户端



前言


一、单线程端口

1.项目创建

打开vs,选择创建新项目;
在这里插入图片描述
选择窗体应用;
在这里插入图片描述
创建项目,自定义项目名称与路径;
在这里插入图片描述

2.控件设置

控件数量及名称设置;
table × 4个; textbox × 4;个 progressBar × 1 个; button × 1个
界面如下:
在这里插入图片描述
点击一下 textbox4 控件,将 ReadOnly 属性设置为 True ,用于显示结果;
在这里插入图片描述
其它属性可自定义设置

3.端口扫描

代码编写:
在窗口设计界面内,双击 button 按钮,可以转到代码编辑区;

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Threading;

namespace Port_Scanning
{
    
    
    public partial class Form1 : Form
    {
    
    
        public Form1()
        {
    
    
            InitializeComponent();
        }
        

        //主机地址
        private string hostAddress;
        //起始端口
        private int start;
        //终止端口
        private int end;
        //端口号
        private int port;
        //定义线程对象
        private Thread scanThread;
        

        private void button1_Click(object sender, EventArgs e)
        {
    
    
            try
            {
    
    
                //初始化
                textBox4.Clear();
                label5.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]!");
            }
        }

        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();
                //进度条值改变
                label5.Text = xian;
                label5.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
            {
    
    
                //未扫描到,则会抛出错误
            }
        }
    }
}

执行结果:
注意127.0.0.1为电脑个人用户的代ip地址;
在这里插入图片描述

二、多线程端口

单线程端口与多线程端口扫描前期准备工作相同,这里我们就直接开始多线称端口。
代码编写:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Threading;

namespace Port_Scanning
{
    
    
    public partial class Form1 : Form
    {
    
    
        public Form1()
        {
    
    
            InitializeComponent();
            //不进行跨线程检查
            CheckForIllegalCrossThreadCalls = false;
        }

        //主机地址
        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 button1_Click(object sender, EventArgs e)
        {
    
    
            try
            {
    
    
                //初始化
                textBox4.Clear();
                label5.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]!");
            }
        }

        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);
                //进度条值改变
                label5.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
            {
    
    
                //未扫描到,则会抛出错误
            }
        }
    }
}

执行结果:
在这里插入图片描述

至此,端口扫描就完成了;

三、网游端口

1.前期准备

新建项目,创建一个窗体应用;
在这里插入图片描述
添加 WindowsMediaPlayer 控件
首先需要添加 Windows Media Player 控件,后续播放背景音乐需要使用到。
右击 “ 工具箱 ” 内的 “ 常规 ” ,点击 “ 选择项 ” ;
在这里插入图片描述
选择 “ COM 组件 ” ,勾选上 “ Windows Media Player ” ,再点击 “ 确定 ” ;
在这里插入图片描述

2.界面设计

textbox —— 2个(输入框、显示框)
button —— 3个(发送、进入游戏、退出游戏)
picturebox —— 1个(图片显示)
trackbar —— 1个(音量调节)
label —— 1个(音量显示)
groupbox —— 2个(控件容器)
WindowsMediaPlayer —— 1个(媒体播放器)

在这里插入图片描述
设置控件属性:
右击控件,点击属性,即可进入到属性设置界面;
textBox2 属性设置:需要将 Multiline 属性设为 True ,表示为多行文本框;ScrollBars 属性设为 Vertical ,表示垂直滚动条;
在这里插入图片描述
trackBar1 属性设置:设置最大值为100,最小值为0,最小改变量为1,用于音量调节;
在这里插入图片描述
其它控件属性,按需求进行设置;
界面显示:
在这里插入图片描述

3.代码与数据

代码:
双击 “ 连接游戏 ” 按钮,转到代码编辑区。
在 button2_Click 函数体内,编写连接的代码,在函数体外定义两个全局变量,这里我简单写了个去除终端转义字符的函数 strDelete

//分别创建 TcpClient 和 NetworkStream 的对象
TcpClient tcpClient;
NetworkStream stream;

/*****************
 * 进入游戏
 *****************/
private void button2_Click(object sender, EventArgs e)
{
    
    
    /*
        * 连接服务器
        */
    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;
}

记得添加头文件。
using System.Net.Sockets
运行结果:
在这里插入图片描述
数据传输:
在界面设计文件中,双击 “ 发送 ” 按钮,转到编辑代码的文件中,在 button1_Click 函数中编写以下的代码;

private void button1_Click(object sender, EventArgs e)
{
    
    
    //获取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();
}

运行结果:
在这里插入图片描述

4.背景音乐

在构造函数中添加以下的代码,在程序运行之后,设置音量调节器的初始值(50),并将 WindownsMediaPlayer 控件隐藏起来;

public Form1()
{
    
    
    InitializeComponent();

    //设置音量调节器的初始位置
    trackBar1.Value = 50;
    label1.Text = "50";
    axWindowsMediaPlayer1.Hide();
}

在 button1_Click 函数内添加后半部分的代码;

private void button2_Click(object sender, EventArgs e)
{
    
    
    /*
        * 连接服务器
        */
    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);
    }

    /******************
     * 播放背景音乐
     ******************/
    //设置音量键值
    trackBar1.Value = 50;
    label1.Text = "50";
    //字符串存储音乐路径
    string s = @"C:\Users\ASUS\Music\damian.mp3";
    //设置为循环播放
    axWindowsMediaPlayer1.settings.setMode("loop", true);
    //设置初始音乐的音量大小(范围:0——100)
    axWindowsMediaPlayer1.settings.volume = 50;
    //设置播放歌曲的路径
    axWindowsMediaPlayer1.URL = s;
}

双击 trackBar1 控件,转到代码编辑区,编写如下的代码;

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

运行结果:
在这里插入图片描述

5.背景图片

加入一个 timer 控件。
要拖动到窗体上,而不是控件上,使其父类为Forms;
设置 Enabled 为 True ②设置 Interval 为 3000 ,意为 3000 ms = 3 s;
在这里插入图片描述
双击 timer1 控件,转到代码编辑区。
在 timer1_Tick 函数内添加如下代码

//定义flag变量
private int flag = 0;

/*****************
 * 自动换图
 *****************/
private void timer1_Tick(object sender, EventArgs e)
{
    
    
    flag++;
    string picturePath = @"C:\Users\ASUS\Pictures\" + flag + ".jpg";
    //设置图片填充
    pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
    pictureBox1.Image = Image.FromFile(picturePath);
    if (flag == 5)
    {
    
    
        flag = 0;
    }
}

运行结果:
在这里插入图片描述
下面为总代码:

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.Tasks;
using System.Windows.Forms;

namespace GameClient
{
    
    
    public partial class Form1 : Form
    {
    
    
        private int flag = 0;
        TcpClient tcpClient;
        NetworkStream stream;

        public Form1()
        {
    
    
            InitializeComponent();

            //设置音量调节器的初始位置
            trackBar1.Value = 0;
            label1.Text = "0";
            axWindowsMediaPlayer1.Hide();
        }

        /*****************
         * 进入游戏
         *****************/
        private void button2_Click(object sender, EventArgs e)
        {
    
    
            /*
                * 连接服务器
                */
            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);
            }

            /******************
             * 播放背景音乐
             ******************/
            //设置音量键值
            trackBar1.Value = 50;
            label1.Text = "50";
            //字符串存储音乐路径
            string s = @"C:\Users\ASUS\Music\damian.mp3";
            //设置为循环播放
            axWindowsMediaPlayer1.settings.setMode("loop", true);
            //设置初始音乐的音量大小(范围:0——100)
            axWindowsMediaPlayer1.settings.volume = 50;
            //设置播放歌曲的路径
            axWindowsMediaPlayer1.URL = s;
        }

        /*****************
         * 去除终端转移字符
         *****************/
        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;
        }

        /*****************
         * 发送数据
         *****************/
        private void button1_Click(object sender, EventArgs e)
        {
    
    
            //获取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 timer1_Tick(object sender, EventArgs e)
        {
    
    
            flag++;
            string picturePath = @"C:\Users\ASUS\Pictures\" + flag + ".jpg";
            //设置图片填充
            pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
            pictureBox1.Image = Image.FromFile(picturePath);
            if (flag == 5)
            {
    
    
                flag = 0;
            }
        }

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

        /*****************
         * 退出游戏
         *****************/
        private void button3_Click(object sender, EventArgs e)
        {
    
    
            if(stream != null)
            {
    
    
                stream.Close();
                tcpClient.Close();
            }
            textBox2.Clear();
            //停止播放背景音乐
            axWindowsMediaPlayer1.Ctlcontrols.stop();
        }
    }
}

总结与参考资料

1.总结

单线程与多线程的区别在于单线程是单一的,而多线程就是多个单一线程,在效率方面比单线更高;对于网游端口控件代码就参考资料来的,不会的就百度或者找的同学解决。

2.参考资料

1: 创建控件的线程访问.
2: AxWindowsMediaPlayer控件的属性.
3: C#winform怎样设计定时更换图片.
4: visual studio2010中C#怎么播放MP3背景音乐.

猜你喜欢

转载自blog.csdn.net/QWERTYzxw/article/details/109816766
今日推荐