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

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


方法一:将侦听套接字强行关掉,这样会使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>



  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值