一、单线程&多线程编写端口扫描器
1、设置界面
vs2015创建窗口程序
找到解决方案资源管理器打开Forms1.cs[设计]进入设计界面
打开工具箱就可以开始设计了
2、单线程
单线程与多线程的区别
单线程:
每个正在运行的程序(即进程),至少包括一个线程,这个线程叫主线程
主线程在程序启动时被创建,用于执行main函数
只有一个主线程的程序,称作单线程程序
主线程负责执行程序的所有代码(UI展现以及刷新,网络请求,本地存储等等)。这些代码只能顺序执行,无法并发执行
多线程:
拥有多个线程的程序,称作多线程程序。
iOS允许用户自己开辟新的线程,相对于主线程来讲,这些线程,称为子线程
可以根据需要开辟若干子线程
子线程和主线程都是独立的运行单元,各自的执行互不影响,因此能够并发执行
**单线程、多线程的区别:
单线程程序:只有一个线程,代码顺序执行,容易出现代码阻塞(页面假死)
多线程程序:有多个线程,线程间独立运行,能有效地避免代码阻塞,并且提高程序的运行性能
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
{
//未扫描到,则会抛出错误
}
}
}
}
运行结果如下
3、端口扫描器(多线程)
第一步:编写代码
将单线程的代码稍微修改一下,加入多线程。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private int port;//记录当前扫描的端口号
private string Address;//记录扫描的系统地址
private bool[] done = new bool[65536];//记录端口的开放状态
private int start;//记录扫描的起始端口
private int end;//记录扫描的结束端口
private bool OK;
private Thread scanThread;
private void label4_TextChanged(object sender, EventArgs e)
{
label4.Text = textBox2.Text;
}
//将输入的结束地址放到进度条的结束位置
private void label6_TextChanged(object sender, EventArgs e)
{
label6.Text = textBox3.Text;
}
private void 扫描_Click(object sender, EventArgs e)
{
label4_TextChanged(sender, e);
label6_TextChanged(sender, e);
//创建线程,并创建ThreadStart委托对象
Thread procss = new Thread(new ThreadStart(WindowsFormsApp1));
procss.Start();
//显示端口扫描范围
progressBar1.Minimum = Int32.Parse(textBox2.Text);
progressBar1.Maximum = Int32.Parse(textBox3.Text);
listBox1.Items.Clear();
listBox1.Items.Add("端口扫描器v1.0.");
listBox1.Items.Add("");
WindowsFormsApp1();
}
private void WindowsFormsApp1()
{
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;
//对该端口进行扫描的线程
scanThread = new Thread(Scan);
scanThread.Start();
//使线程睡眠
System.Threading.Thread.Sleep(100);
progressBar1.Value = i;
label5.Text = i.ToString();
}
//未完成时情况
while (!OK)
{
OK = true;
for (int i = start; i <= end; i++)
{
if (!done[i])
{
OK = false;
break;
}
}
}
listBox1.Items.Add("扫描结束!");
System.Threading.Thread.Sleep(1000);
}
else
{
MessageBox.Show("输入错误,端口范围为[0,65536]");
}
}
//连接端口
private void Scan()
{
int portnow = port;
//创建线程变量
Thread Threadnow = scanThread;
done[portnow] = true;
//创建TcpClient对象,TcpClient用于TCP网络服务提供客户端连接
TcpClient objTCP = null;
//扫描端口,成功就写入信息
try
{
objTCP = new TcpClient(Address, portnow);
listBox1.Items.Add("端口" + portnow.ToString() + "开放!");
}
catch
{
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
}
}
运行结果如下
二、TCP连接网游客户端
1、准备工作
第一步:新建项目
新建一个窗体应用。
新建完毕后,会转到窗体设计界面。
第二步:添加 WindowsMediaPlayer 控件
首先需要添加 Windows Media Player 控件(已有,则忽略),后续播放背景音乐需要使用到。
右击 “ 工具箱 ” 内的 “ 常规 ” ,点击 “ 选择项 ” 。
选择 “ COM 组件 ” ,勾选上 “ Windows Media Player ” ,再点击 “ 确定 ” 。
第三步:界面设计
textbox —— 2个(输入框、显示框)
button —— 3个(发送、进入游戏、退出游戏)
picturebox —— 1个(图片显示)
trackbar —— 1个(音量调节)
label —— 1个(音量显示)
groupbox —— 2个(控件容器)
WindowsMediaPlayer —— 1个(媒体播放器)
2、核心代码实现
添加命名空间
using System.Net.Sockets;
using System.Net;
using System.Media;
建立TCP连接
Socket tcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ipaddress = IPAddress.Parse("10.160.52.106");
EndPoint point = new IPEndPoint(ipaddress, 3900);
tcpClient.Connect(point);
① 新建一个socket对象(IPV4协议,数据流传输、TCP模式)
② 设定目标IP
③ 设定目标端口
④ 调用connect函数连接
接收游戏服务器发送的消息,Receive()
byte[] data = new byte[2048];
//传递一个byte数组,用于接收数据。length表示接收了多少字节的数据
int length = tcpClient.Receive(data);
string message = Encoding.Default.GetString(data, 0, length);
richTextBox1.Text = message;
向游戏服务器发送消息,Send()
byte[] sendBytes = Encoding.Default.GetBytes(textBox1.Text+"\n");
tcpClient.Send(sendBytes);
使用 System.Windows.Forms.Timer定时器类,实现每隔30秒切换一张图片
//实列化
System.Windows.Forms.Timer mytimer = new System.Windows.Forms.Timer();
//给timer绑定一个事件
mytimer.Tick += new EventHandler(change_Pic);
mytimer.Enabled = true;
//设置30毫秒的时间间隔
mytimer.Interval = 30000;
使用 System.Media.SoundPlayer类,实现播放wav
SoundPlayer sp = new SoundPlayer();
sp.SoundLocation = @"music.wav";
sp.PlayLooping();