登山-C#-关于TcpListener的AcceptTcpClient()方法造成线程阻塞,进而程序无法彻底关闭的问题
2016-03-05 16:05
651 查看
在《C#高级编程》第7版第24章,有提到使用TCP类。
书中写了一个实例,两个winform,其中一个点击按钮发送字符串,另一个winform进行接收。这个实例有个缺点,只能接收一次。
我将这个实例进行了改造。第一版做好后,可以进行接收和发送,但是出现一个问题,就是在关闭程序后,在电脑的任务管理器中看到还有进程在跑。
进行了一些尝试后改了第二版,终于解决了这个问题。
看一眼这个程序
![](http://img.blog.csdn.net/20160305155144017?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
在两台电脑上分别运行此程序,注意要设置对方的IP地址。
![](http://img.blog.csdn.net/20160305155506052?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
我直接贴上第二版的代码,然后在标明修改的哪儿。
相对于第一版,主要是添加了变量boolStop,用于控制线程中while循环结束的时机。第二点就是在while循环中增加了一个判断,if (!tcpListener.Pending()),这样在对方没有发送消息时,是不会执行到tcpListener.AcceptTcpClient();的。这样就不会造成线程的阻塞了。这样直接关闭了winform,线程thread也会相应的结束。
否则就会造成如下的情况,关闭了程序,但是任务管理器中,仍然能够看到进程。
![](http://img.blog.csdn.net/20160305160354954?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
这个程序还有很多地方可以改进,后续再写。
书中写了一个实例,两个winform,其中一个点击按钮发送字符串,另一个winform进行接收。这个实例有个缺点,只能接收一次。
我将这个实例进行了改造。第一版做好后,可以进行接收和发送,但是出现一个问题,就是在关闭程序后,在电脑的任务管理器中看到还有进程在跑。
进行了一些尝试后改了第二版,终于解决了这个问题。
看一眼这个程序
在两台电脑上分别运行此程序,注意要设置对方的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.IO; using System.Net; using System.Net.Sockets; using System.Threading; namespace TCPSend { public partial class Form1 : Form { //定义一个委托,用于更新Form1上控件。 protected delegate void UpdateDisplayDelegate(string text); public Thread thread = null; public TcpClient tcpClientReceiver = null; TcpListener tcpListener = null; public Boolean boolStop = false; public Form1() { InitializeComponent(); thread = new Thread(new ThreadStart(Listen)); thread.Start(); } public void Listen() { string LocalIp = GetSelfIp(); if (LocalIp == null) { return; } IPAddress localAddr = IPAddress.Parse(LocalIp); Int32 port = 2112; tcpListener = new TcpListener(localAddr, port); tcpClientReceiver = new TcpClient(); tcpListener.Start(); while (true) { if (!tcpListener.Pending()) { //为了避免每次都被tcpListener.AcceptTcpClient()阻塞线程,添加了此判断, //no connection requests have arrived。 //当没有连接请求时,什么也不做,有了请求再执行到tcpListener.AcceptTcpClient() } else { tcpClientReceiver = tcpListener.AcceptTcpClient(); NetworkStream ns = tcpClientReceiver.GetStream(); StreamReader sr = new StreamReader(ns); string result = sr.ReadToEnd(); Invoke(new UpdateDisplayDelegate(UpdateDisplay), new object[] { result }); } if (boolStop) { break; } } } public void UpdateDisplay(string text) { string currentContents = textBox4.Text; currentContents += text+"\r\n"; //必须用"\r\n"在窗口中才能体现出换行 textBox4.Text = currentContents; } //send message private void button1_Click(object sender, EventArgs e) { SendMessage(); } public void SendMessage() { TcpClient tcpClient = new TcpClient(textBox1.Text, Int32.Parse(textBox2.Text)); NetworkStream ns = tcpClient.GetStream(); string message = textBox3.Text; byte[] contentBytes = Encoding.GetEncoding("utf-8").GetBytes(message); //将string类型转换为byte[] for (int i = 0; i < contentBytes.Length; i++) { ns.WriteByte(contentBytes[i]); } ns.Close(); tcpClient.Close(); textBox3.Text = ""; } //获得本地的IP地址 public string GetSelfIp() { System.Net.IPAddress[] addressList = Dns.GetHostByName(Dns.GetHostName()).AddressList; if (addressList.Length == 1) { return addressList[0].ToString(); } else { MessageBox.Show("当前只支持设置一个IP的电脑,您的电脑设有多个IP地址"); } return null; } //在关闭之前,将boolStop设置为true,thread既可以结束了。 private void Form1_FormClosing(object sender, FormClosingEventArgs e) { boolStop = true; } } }
相对于第一版,主要是添加了变量boolStop,用于控制线程中while循环结束的时机。第二点就是在while循环中增加了一个判断,if (!tcpListener.Pending()),这样在对方没有发送消息时,是不会执行到tcpListener.AcceptTcpClient();的。这样就不会造成线程的阻塞了。这样直接关闭了winform,线程thread也会相应的结束。
否则就会造成如下的情况,关闭了程序,但是任务管理器中,仍然能够看到进程。
这个程序还有很多地方可以改进,后续再写。
相关文章推荐
- Web缓存基础:术语、HTTP报头和缓存策略
- tcp数据发送过快的处理
- 【翻译+原创】Deep Learning Face Representation from Predicting 10,000 Classes 论文笔记
- Linux TCP/IP 协议栈调优
- Linux TCP/IP 协议栈调优
- TCP/IP 相关知识点与面试题集(转)
- 简单的 winsocket TCP通信
- Linux(Centos)中tcpdump参数用法详解(转)
- OkHttp的使用
- TCP面向连接中的“连接”究竟是什么,可靠与不可靠(转)
- TCp/IP实验一
- 自写网络流24题总结
- AFNetworking使用
- TCP/IP四层模型
- 网络端口
- Linux学习之路——网络基础知识点汇总
- 自定义BroadcastReceiver使用监听网络状态变化
- javax.servlet.http.HttpSession session用法详解
- HttpSession详解
- IHttpModule在webconfig中的注册