簡體   English   中英

套接字斷開連接並正常重新連接C#

[英]Socket disconnections and gracefully reconnect C#

我正在構建一個TCP端口轉發應用程序。 客戶端通過特定端口連接到服務器,並且在內部將請求在服務器中路由到遠程端口,並將響應傳遞回客戶端。 下面是我的代碼。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace BBGRouter
{
    class Router
    {
        #region log4net
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        #endregion //log4net
        bool isShutdown = false;
        private Socket router = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        public event EventHandler OnRestartNeeded;
        //only one time

        Thread thRouterTh;
        public Router()
        {

            thRouterTh = new Thread(new ParameterizedThreadStart(RouterProc));
        }
        IPEndPoint local, remote;
        public void Start(IPEndPoint local, IPEndPoint remote)
        {
            if (log.IsInfoEnabled) { log.Info("Listening on " + local); }
            this.local = local;
            this.remote = remote;
            router.Bind(local);
            router.Listen(10);
            thRouterTh.Name = "router thread";
            thRouterTh.Start();
        }

        void RouterProc(object obj)
        {
            while (!isShutdown)
            {
                try
                {
                    var source = router.Accept();
                    if (log.IsInfoEnabled) { log.Info("Creating new session...."); }
                    var destination = new Router();
                    var state = new State(source, destination.router);
                    destination.Connect(remote, source);
                    source.BeginReceive(state.Buffer, 0, state.Buffer.Length, 0, OnDataReceive, state);
                }
                catch (Exception ex)
                {
                    if (log.IsErrorEnabled) { log.Error("Exception in Router thread", ex); }
                    if (isShutdown) { if (log.IsInfoEnabled) { log.Info("Shutting down..."); } }
                }
            }
        }

        public void Join()
        {
            if (thRouterTh != null)
                thRouterTh.Join();
        }

        private void StopAndFireRestart(EventArgs e)
        {
            Stop();

           log.Info("Stopped router");

            EventHandler handler = OnRestartNeeded;
            if (handler != null)
            {
                log.Info("Firing the restart event now");
                handler(this, e);
            }
        }

        public void Stop()
        {
            try
            {
                isShutdown = true;
                if (log.IsInfoEnabled) { log.Info("Stopping router thread"); }
                router.Shutdown(SocketShutdown.Both);
                //router.Shutdown(SocketShutdown.Receive);
            }
            catch (Exception ex)
            {
                if (log.IsErrorEnabled) { log.Error("Exception while stopping", ex); }
            }
            finally
            {
                thRouterTh.Interrupt();
                router.Dispose();
            }
        }

        private void Connect(EndPoint remoteEndpoint, Socket destination)
        {

            if (log.IsInfoEnabled) { log.InfoFormat("connecting session at {0}", remoteEndpoint.ToString()); }
            var state = new State(router, destination);

            try
            {
                router.Connect(remoteEndpoint);
                router.BeginReceive(state.Buffer, 0, state.Buffer.Length, SocketFlags.None, OnDataReceive, state);
            }
            catch (SocketException e)
            {
                if (log.IsErrorEnabled) { log.Error(string.Format("SocketException while connect: Exception: {0}, ErrorCode: {1}", e, e.ErrorCode)); }

                // Stop the service
                StopAndFireRestart(new EventArgs());
            }
            catch (Exception ex)
            {
                if (log.IsErrorEnabled) { log.Error("exception while connect {0}", ex); }
            }
        }

        private void OnDataReceive(IAsyncResult result)
        {
            var state = (State)result.AsyncState;
            try
            {
                var bytesRead = state.SourceSocket.EndReceive(result);
                if (bytesRead > 0)
                {
                    log.Info(string.Format("Bytes read: {0}", bytesRead));
                    state.DestinationSocket.Send(state.Buffer, bytesRead, SocketFlags.None);
                    state.SourceSocket.BeginReceive(state.Buffer, 0, state.Buffer.Length, 0, OnDataReceive, state);
                }
            }
            catch (Exception e)
            {
                if (log.IsErrorEnabled) { log.Error("Exception receiving the data, Closing source/destination sockets", e); }
                //state.DestinationSocket.Close();

                //state.SourceSocket.Close();
                //StopAndFireRestart(new EventArgs());
            }
        }

        private class State
        {
            public Socket SourceSocket { get; private set; }
            public Socket DestinationSocket { get; private set; }
            public byte[] Buffer { get; private set; }

            public State(Socket source, Socket destination)
            {
                SourceSocket = source;
                DestinationSocket = destination;
                Buffer = new byte[8192];
            }
        }
    }
}

當客戶端在4-5小時后突然突然隨機斷開與遠程端口的連接時,就會發生此問題。 我如何才能優雅地重新連接客戶端,以使客戶端代碼沒有變化?

您為什么不使用netsh解決此問題?

netsh interface portproxy add v4tov4 listenport=LOCALPORT listenaddress=localhost connectport=REMOTEPORT connectaddress=REMOTEADDRESS

要么

netsh interface portproxy add v4tov4 listenport=LOCALPORT connectport=REMOTEPORT connectaddress=REMOTEADDRESS

有關netsh更多信息,請參見MSDN

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM