打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
C# TCP退出Accept阻塞的两种方法


方法一:将侦听套接字强行关掉,这样会使Accept引发异常,从而达到退出阻塞的目的。

方法二:先拆除循环条件,再给监听端口发送一条自定义命令,解析成功后,Accept自然退出阻塞


后台代码:

  1. using System;  
  2. using System.Text;  
  3. using System.Windows;  
  4. using System.Threading;  
  5. using System.Net;  
  6. using System.Net.Sockets;  
  7.   
  8. namespace SocketBlockingInterrupt  
  9. {  
  10.     public partial class MainWindow : Window  
  11.     {  
  12.         bool bIsExecute;  
  13.         TcpListener listener;//监听套接字  
  14.         SynchronizationContext synContext;  
  15.   
  16.         public MainWindow()  
  17.         {  
  18.             InitializeComponent();  
  19.             synContext = SynchronizationContext.Current;  
  20.             btnStop.IsEnabled = false;  
  21.         }  
  22.   
  23.         private void btnStart_Click(object sender, RoutedEventArgs e)  
  24.         {  
  25.             bIsExecute = true; //建立循环条件  
  26.             btnStart.IsEnabled = false;  
  27.             btnStop.IsEnabled = true;  
  28.   
  29.             //开启监听线程  
  30.             Thread t = new Thread(new ThreadStart(ListenThread));  
  31.             t.IsBackground = true;  
  32.             t.Start();  
  33.         }  
  34.   
  35.         void ListenThread()  
  36.         {  
  37.             IPEndPoint localEP = new IPEndPoint(IPAddress.Any, 9000);  
  38.             listener = new TcpListener(localEP);  
  39.             listener.Start();         //启动监听,非阻塞  
  40.   
  41.             synContext.Post(updateUI, "监听线程:正在监听中...");  
  42.   
  43.             while (bIsExecute) //循环条件  
  44.             {  
  45.                 byte[] recvBuff = new byte[512];  
  46.   
  47.                 //捕获异常,强行退出Accept阻塞  
  48.                 try  
  49.                 {  
  50.                     synContext.Post(updateUI, "监听线程:Accept正在阻塞中...");  
  51.   
  52.                     TcpClient client = listener.AcceptTcpClient();     // 等待连接(阻塞)  
  53.                     synContext.Post(updateUI, "监听线程:收到连接请求,已退出Accept阻塞");  
  54.   
  55.                     int recvByte = client.Client.Receive(recvBuff);// 建立连接  
  56.   
  57.                     // 解析命令  
  58.                     byte[] buff = new byte[recvByte];  
  59.                     for (int i = 0; i < recvByte; i++ ) { buff[i] = recvBuff[i]; }  
  60.                     string exitByt = Encoding.ASCII.GetString(buff);  
  61.                     if (exitByt == "Exit")  
  62.                     {  
  63.                         synContext.Post(updateUI, "监听线程:收到数据" + exitByt);  
  64.                         break;  
  65.                     }  
  66.                 }  
  67.                 catch (SocketException ex)  
  68.                 {  
  69.                     synContext.Post(updateUI, "监听线程:发生异常,Accept阻塞被强行退出:" + ex.Message);  
  70.                     break;  
  71.                 }  
  72.             }  
  73.             synContext.Post(updateUI, "监听线程:已成功退出监听");  
  74.         }  
  75.   
  76.         private void btnStop_Click(object sender, RoutedEventArgs e)  
  77.         {  
  78.             bIsExecute = false; //此处拆除循环条件  
  79.   
  80.             //方法1:直接停止监听套接字,引发异常从而强行使Accept退出阻塞。  
  81.             //---------------------------------------------  
  82.             //if (listener != null)  
  83.             //{  
  84.             //    listener.Stop();  
  85.             //}  
  86.             //---------------------------------------------  
  87.   
  88.               
  89.             //方法2:主动发送一条数据,使Accept自然地退出阻塞。  
  90.             //---------------------------------------------  
  91.             TcpClient tcpClient = new TcpClient();  
  92.             tcpClient.Connect("127.0.0.1",9000);  
  93.   
  94.             NetworkStream ns = tcpClient.GetStream();  
  95.             if (ns.CanWrite)  
  96.             {  
  97.                 Byte[] sendBytes = Encoding.ASCII.GetBytes("Exit");  
  98.                 ns.Write(sendBytes, 0, sendBytes.Length);  
  99.                 lbMsg.Items.Add("发送退出命令成功!");  
  100.             }  
  101.             else  
  102.             {  
  103.                 lbMsg.Items.Add("发送退出命令失败!");  
  104.                 return;  
  105.             }  
  106.             ns.Close();  
  107.             tcpClient.Close();  
  108.             //---------------------------------------------  
  109.   
  110.             btnStart.IsEnabled = true;  
  111.             btnStop.IsEnabled = false;  
  112.         }  
  113.   
  114.         void updateUI(object o)  
  115.         {  
  116.             string str = (string)o;  
  117.             lbMsg.Items.Add(str);  
  118.         }  
  119.     }  
  120. }  


WPF前台代码:

  1. <Window x:Class="SocketBlockingInterrupt.MainWindow"  
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  4.         Title="MainWindow" Height="350" Width="525">  
  5.     <Grid>  
  6.         <Button Content="开始侦听" Height="23" HorizontalAlignment="Left" Margin="12,12,0,0" Name="btnStart" VerticalAlignment="Top" Width="75" Click="btnStart_Click" />  
  7.         <Button Content="结束侦听" Height="23" HorizontalAlignment="Left" Margin="108,12,0,0" Name="btnStop" VerticalAlignment="Top" Width="75" Click="btnStop_Click" />  
  8.         <ListBox Height="258" HorizontalAlignment="Left" Margin="12,41,0,0" Name="lbMsg" VerticalAlignment="Top" Width="479" />  
  9.     </Grid>  
  10. </Window>  



本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
Kafka 服务端 网络层 架构
高性能大容量SOCKET并发
Redis网络模型有多强?
Ceph网络通信
不可不知的socket和TCP连接过程
Redis使用单线程却快到飞起的原因,全在这里了
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服