方法一:将侦听套接字强行关掉,这样会使Accept引发异常,从而达到退出阻塞的目的。
方法二:先拆除循环条件,再给监听端口发送一条自定义命令,解析成功后,Accept自然退出阻塞。
后台代码:
- using System;
- using System.Text;
- using System.Windows;
- using System.Threading;
- using System.Net;
- using System.Net.Sockets;
-
- namespace SocketBlockingInterrupt
- {
- public partial class MainWindow : Window
- {
- bool bIsExecute;
- TcpListener listener;//监听套接字
- SynchronizationContext synContext;
-
- public MainWindow()
- {
- InitializeComponent();
- synContext = SynchronizationContext.Current;
- btnStop.IsEnabled = false;
- }
-
- private void btnStart_Click(object sender, RoutedEventArgs e)
- {
- bIsExecute = true; //建立循环条件
- btnStart.IsEnabled = false;
- btnStop.IsEnabled = true;
-
- //开启监听线程
- Thread t = new Thread(new ThreadStart(ListenThread));
- t.IsBackground = true;
- t.Start();
- }
-
- void ListenThread()
- {
- IPEndPoint localEP = new IPEndPoint(IPAddress.Any, 9000);
- listener = new TcpListener(localEP);
- listener.Start(); //启动监听,非阻塞
-
- synContext.Post(updateUI, "监听线程:正在监听中...");
-
- while (bIsExecute) //循环条件
- {
- byte[] recvBuff = new byte[512];
-
- //捕获异常,强行退出Accept阻塞
- try
- {
- synContext.Post(updateUI, "监听线程:Accept正在阻塞中...");
-
- TcpClient client = listener.AcceptTcpClient(); // 等待连接(阻塞)
- synContext.Post(updateUI, "监听线程:收到连接请求,已退出Accept阻塞");
-
- int recvByte = client.Client.Receive(recvBuff);// 建立连接
-
- // 解析命令
- byte[] buff = new byte[recvByte];
- for (int i = 0; i < recvByte; i++ ) { buff[i] = recvBuff[i]; }
- string exitByt = Encoding.ASCII.GetString(buff);
- if (exitByt == "Exit")
- {
- synContext.Post(updateUI, "监听线程:收到数据" + exitByt);
- break;
- }
- }
- catch (SocketException ex)
- {
- synContext.Post(updateUI, "监听线程:发生异常,Accept阻塞被强行退出:" + ex.Message);
- break;
- }
- }
- synContext.Post(updateUI, "监听线程:已成功退出监听");
- }
-
- private void btnStop_Click(object sender, RoutedEventArgs e)
- {
- bIsExecute = false; //此处拆除循环条件
-
- //方法1:直接停止监听套接字,引发异常从而强行使Accept退出阻塞。
- //---------------------------------------------
- //if (listener != null)
- //{
- // listener.Stop();
- //}
- //---------------------------------------------
-
-
- //方法2:主动发送一条数据,使Accept自然地退出阻塞。
- //---------------------------------------------
- TcpClient tcpClient = new TcpClient();
- tcpClient.Connect("127.0.0.1",9000);
-
- NetworkStream ns = tcpClient.GetStream();
- if (ns.CanWrite)
- {
- Byte[] sendBytes = Encoding.ASCII.GetBytes("Exit");
- ns.Write(sendBytes, 0, sendBytes.Length);
- lbMsg.Items.Add("发送退出命令成功!");
- }
- else
- {
- lbMsg.Items.Add("发送退出命令失败!");
- return;
- }
- ns.Close();
- tcpClient.Close();
- //---------------------------------------------
-
- btnStart.IsEnabled = true;
- btnStop.IsEnabled = false;
- }
-
- void updateUI(object o)
- {
- string str = (string)o;
- lbMsg.Items.Add(str);
- }
- }
- }
WPF前台代码:
- <Window x:Class="SocketBlockingInterrupt.MainWindow"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- Title="MainWindow" Height="350" Width="525">
- <Grid>
- <Button Content="开始侦听" Height="23" HorizontalAlignment="Left" Margin="12,12,0,0" Name="btnStart" VerticalAlignment="Top" Width="75" Click="btnStart_Click" />
- <Button Content="结束侦听" Height="23" HorizontalAlignment="Left" Margin="108,12,0,0" Name="btnStop" VerticalAlignment="Top" Width="75" Click="btnStop_Click" />
- <ListBox Height="258" HorizontalAlignment="Left" Margin="12,41,0,0" Name="lbMsg" VerticalAlignment="Top" Width="479" />
- </Grid>
- </Window>
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。