第10周-TCP编程-端口扫描器与网游客户端

端口扫描器

准备

  • 创建一个新的项目
    在这里插入图片描述
    生成的项目名称为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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值