TCP编程端口扫描器和网游客户端(网络编程)

本文介绍了如何使用TCP编程实现一个端口扫描器,包括单线程和多线程版本,并详细讲解了如何在VS2017中创建网游客户端,包括连接服务器、收发消息、播放背景音乐和变换背景图片的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本次实验,博主将使用TCP来编写一个端口扫描器以及制作一个网游的客户端

1. 编写端口扫描器程序

1.1编程一个单线程端口扫描器

首先,打开VS2017,点击文件–>新建–>项目,选择Windows窗口应用,创建一个带界面的应用程序。
在这里插入图片描述
其次,进入窗口设计页面,现在的窗口应该是空白的一片,从工具栏中选择Label,TextBox,ProgressBar这三个类型的工具若干(如果没有工具箱,可以从视图-- >工具箱召唤出工具栏),在此介绍一下所用各工具的用处。

Label:为控件提供运行时的信息或者信息说明
TextBox:允许用户输入文本,或者输出文本(用作输入密码时可用字符掩码功能)
ProgressBar:显示一个向用户显示操作进程的填充条,俗称进度条。

按照以前所用的应用的大致界面,歪歪扭扭拼凑了一个简易的端口扫描器界面出来。
在这里插入图片描述
拼凑好后,将老师所给的代码经过修饰后加入进程序中(可双击控件召唤出编程界面)

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
            {
                //未扫描到,则会抛出错误
            }
        }
    }
}

如果直接使用代码的话,Program.cs中该行可能会报错
在这里插入图片描述
原因是因为它找不到Form1程序
在这里插入图片描述可在前面加上命名空间名(我的是Port_Scanning),此程序就不会报错了
在这里插入图片描述
填充好代码后,点击启动,让其运行。

可以看到单线程下程序扫描20个端口,缓慢的完成了扫描任务

1.2编译完成一个多线程端口扫描器

由于单线程端口扫描器有点慢,所以接下来编程一个多线程的端口扫描器。

由于外壳不变,只需要改变其内核,所以还是可以使用上面所拼凑的窗口,在窗口函数中做一点小小的修改。修改完毕后,点击运行。

可以看到,使用多线程的端口扫描器明显快于单线程端口扫描器.

2.编写网游客户端

2.1考古20年前的游戏

要求:游戏服务器的校园内网IP地址为 10.160.52.106,端口为3900,采用TCP连接。

首先,为了保证能够连接到这个游戏,先尝试ping通此IP
在这里插入图片描述
可以看到,能够ping通该IP,则进入下一步,输入telnet,输入以下代码

open 10.160.52.106 3900

成功进入金庸梦这款游戏(后悔知道的有点晚)
在这里插入图片描述

2.2使用VS2017实现网游客户端

接下来将要在VS2017中编程,将模板函数略微修改一下
在这里插入图片描述
由于是空头函数,于是点进去看了看效果
在这里插入图片描述
接下来,我们镶嵌一点函数进去
首先,需要建立TCP连接,使用如下函数(如有不懂可以查看以下博客)
C# tcpClient发送和接收

private void button10_Click(object sender, EventArgs e)
        {
            Socket tcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPAddress ipaddress = IPAddress.Parse("10.1.230.41");
            EndPoint point = new IPEndPoint(ipaddress, 3900);
           tcpClient.Connect(point)}

总的来说就是:新建一个socket对象–>设定目标的IP–>设定目标的端口–>调用connect函数.

连接成功后,理所应当的可以进行收发消息了,其中,接受消息的函数如下

byte[] data = new byte[1024];
  //传递一个byte数组,用于接收数据。length表示接收了多少字节的数据
            int length = tcpClient.Receive(data);
            string message = Encoding.Default.GetString(data, 0, length);//只将接收到的数据进行转化
            textBox2.Text += message;//textBox2是我接收消息的文本框

发消息选择使用另一个文本框textBox1,再配上发送按钮button12.

private void button12_Click(object sender, EventArgs e)
        {
            Socket tcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPAddress ipaddress = IPAddress.Parse("10.1.230.41");
            EndPoint point = new IPEndPoint(ipaddress, 3900);
            tcpClient.Connect(point);
            string message2 = textBox1.Text;//读取用户的输入
                                            //将字符串转化为字节数组,然后发送到服务器端
            byte[] data = new byte[1024];
            //传递一个byte数组,用于接收数据。length表示接收了多少字节的数据
      
        }

就能够简易的完成简单的端口消息收发了。

2.3来点音乐!

做完它的消息收发后,总感觉跟平时的网游不太一样,想了半天才想起来,别人的登录界面还有音乐可以听,于是准备播放一下背景音乐。
首先,去某网站找了首黑凤梨,下载到了F盘里,记住它的地址(博主下载的是wav格式的音乐)
在这里插入图片描述
然后,在代码中插入播放wav后缀音乐的函数

System.Media.SoundPlayer sp = new SoundPlayer();
            sp.SoundLocation = @"F:\我的学习\2020-2021\邓紫棋 - 喜欢你.wav";
            sp.PlayLooping(); 

再次点开客户端,悦儿的歌声就有了(不知道该怎么给大家听,反正懂的都懂)

2.4变换背景图片

假如真的是个网游客户端,那么他的宣传画就应该不断变化,点进去就是各种各样的活动了,那么怎么设置图片的变换呢,在这里慢慢摸索.
首先运用到的就是刚刚在用的picturebox,将其SizeMode调整为StretchImage
在这里插入图片描述
接下来拖出一个新工具timer,将timer的Enabled改为true,Interval改为3000(意为3000ms、即3S触发一次)
在这里插入图片描述
以下为picturebox中的函数

private void pictureBox1_Click(object sender, EventArgs e)
        {
            System.Windows.Forms.Timer mytimer = new System.Windows.Forms.Timer();

            mytimer.Tick += new EventHandler(change);
            mytimer.Enabled = true;

            mytimer.Interval = 3000;
        }

其中,change为博主自己所写的函数,核心内容为(我的四张图片取名很简单)

private void change(object sender, EventArgs e)

        {

            //i++,实现第i张;
            int i = 0;
            i++;

            string filePath = Application.StartupPath + "\\hello" + i.ToString() + ".jpg";

            this.pictureBox1.Image = Image.FromFile(filePath);

            //当i=4时,i变为0,然后重新开始;

            if (i == 4)

            {

                i = 0;

            }

        }

我将需要轮换的图片与启动器放在了一起.
在这里插入图片描述
最终再点进去一次
在这里插入图片描述
过了3秒在这里插入图片描述
此次作业大功告成!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值