练习TCP编程——端口编程与网游客户端
目录
- 一、TCP通讯协议简介
- 二、单线程TCP端口检测
- 三、多线程TCP端口检测
- 四、网游客户端
- 1.建立连接并显示
- 2.发送消息
- 3.播放背景音乐
- 4.变换背景图片
- 五、参考
一、TCP通讯协议简介
百度比我专业多了
主要就是三次握手建立连接,然后就开始收发消息。比UDP安全,但是还是有漏洞,运气好可以拆出包。而且在第二次握手时,客户端如果不再发送第三次握手,会导致服务端一直处于等待状态。(如果是攻击服务器不知如此)
二、单线程TCP端口检测
1.界面设计
程序界面如图
2.程序主要代码
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;}private void btnScan_Click(object sender, System.EventArgs e){//显示端口扫描的范围progressBar1.Minimum = Int32.Parse(txtStart.Text);progressBar1.Maximum = Int32.Parse(txtEnd.Text);//显示框初始化lbResult.Items.Clear();lbResult.Items.Add("端口扫描器 v1.0.");lbResult.Items.Add("");}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;不使用扫描线程Scan();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]");}}private void Scan(){int portnow = port;done[portnow] = true;//创建TcpClient对象,TcpClient用于为TCP网络服务提供客户端连接TcpClient objTCP = null;//扫描端口,成功则写入信息try{//用TcpClient对象扫描端口objTCP = new TcpClient(Addr, portnow);lbResult.Items.Add("端口 " + portnow.ToString() + " 开放!");}catch{}}
3.效果
运行起来非常的慢,还会卡顿,扫描100个端口都需要几十分钟甚至更久。
三、多线程TCP端口检测
1.界面
界面设计没有变化
2.程序主要代码
在上面代码的基础上加入了线程操作。设计思路主要是运用TCP去不断连接对方的各个端口,连接失败则不返回,说明对方此端口并未开放,反之则开放了。可以用来检测端口的状态。
注意:直接跨线程操作,编译器会报错,Windows这样设计是为了一些错误。解决的办法有两种:
(1)像我这样加一句Control.CheckForIllegalCrossThreadCalls = false;关闭跨线程检查。因为这个程序不是很复杂,不会出现严重的不安全现象,可以关闭跨线程检查。这种方法最简单。
(2)使用安全的跨线程调用。这种方法安全有效,比较复杂。(参考资料里有介绍)
static void Main(){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;}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("");}private void PortScan(){//关闭跨线程检查Control.CheckForIllegalCrossThreadCalls = false;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;//不使用扫描线程//Scan();//使用该端口的扫描线程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]");}}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{}}
3.运行效果
运行之后,通过TCP扫描100个端口只需要几分钟,比单线程快了很多。
四、网游客户端
1.建立连接并显示
首先做好图形界面,然后要求点击“进入游戏”,能够连接到网游服务器,点击“退出游戏”能够退出连接,并且在输入框内输入,点击回车,能够向服务器发送此信息。
程序主要代码
使用TCP连接到服务器,然后进行交互,也可以运用多线程来操作。
//接收数据函数多线程运用,注释部分/*private void ReceiveMsg(){while (true){try{//创建接受数据的字节流byte[] getData = new byte[1024];//从网络流中读取数据ns.Read(getData, 0, getData.Length);//将字节数组转换成文本形式string getMsg = Encoding.Default.GetString(getData);//将消息添加到richTextBox1中richTextBox1.Text += getMsg;}catch (ThreadAbortException){//捕捉到线程被终止异常则表示是人为的断开TCP连接//不弹出错误提示}catch (Exception e){//接受消息发生异常MessageBox.Show(e.Message);//并释放相关资源if (ns != null)ns.Dispose();break;}}}*/
private void button_entergame_Click(object sender, EventArgs e){//连接服务器进入游戏try{//初始化tcptcpclient = new TcpClient();richTextBox1.Text += "正在连接。。。";//开始连接,服务器IP和端口号tcpclient.Connect("10.160.52.106",3900);//获得绑定的网络数据流ns = tcpclient.GetStream();//实例化并启动接受消息线程/*receiveThread = new Thread(ReceiveMsg);receiveThread.Start();*///接收数据byte[] data = new byte[1024];//从网络流中读取数据ns.Read(data,0,data.Length);//将字节数组转换为文本string receive;receive = Encoding.Default.GetString(data);//显示在listbox中richTextBox1.AppendText(receive);}catch (Exception ex)//异常处理{ MessageBox.Show(ex.Message); }}private void button_exitgame_Click(object sender, EventArgs e){//退出游戏//断开TCP连接tcpclient.Close();//销毁绑定的网络数据流ns.Dispose();//销毁接受消息的线程//receiveThread.Abort();}
2.发送消息
private void textBox_input_KeyDown(object sender, KeyEventArgs e){//发送信息try{//按下enter发送信息if (e.KeyCode == Keys.Enter){//从textBox1中获得数据byte[] sendata = new byte[1024];sendata = Encoding.Default.GetBytes(textBox_input.Text + '\n');//将数据写入到网络数据流中ns.Write(sendata, 0, sendata.Length);richTextBox1.Text += Encoding.Default.GetString(sendata);textBox_input.Clear();}}catch (Exception ex){ MessageBox.Show(ex.Message); } }
3.播放背景音乐
播放音乐的方式有很多种,我使用的是较为简单的一种。
private void playmusic(){//播放音乐WMPLib.WindowsMediaPlayer player = new WMPLib.WindowsMediaPlayer();player.URL = @"D:\Musicdownload\Goose house - 光るなら.mp3";player.controls.play();//这种方式需要将.wav文件加入到项目资源中/*SoundPlayer sp = new SoundPlayer();sp.SoundLocation = @"music.wav";sp.PlayLooping();*/}
找到引用,一般在VS右边的解决方案资源管理器
然后如下操作
再敲写代码即可。
4.变换背景图片
实现图片的变换,可以在30s后变换以此背景图片。这需要使用到Timer容器。
用Timer布置在需要变换的pictureBox上,然后设置属性。
为了实验,我设置了3s(3000ms)的间隔。
下面是代码
private void timer1_Tick(object sender, EventArgs e){picno++;//设置图片路径string picturePath = @"D:\QQdownload\Picture\a洛天依0" + picno +".jpg";pictureBox1.Image = Image.FromFile(picturePath);if (picno == 9){picno = 0;}}
运行效果(部分)
五、参考
TCP编程又有同步和异步之分,这里只是使用了同步连接。
同步TCP客户端
异步TCP客户端
C#5种播放音乐的方式
微软关于跨线程问题的解答
如何用跨线程方式调用Windows窗体控件
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
