套接字断开并正常重新连接C#

时间:2015-04-21 18:26:49

标签: c# sockets

我正在构建一个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小时后客户端突然从远程端口突然断开连接。如何优雅地重新连接客户端,以便客户端代码没有变化?

1 个答案:

答案 0 :(得分:0)

为什么不通过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

有关MSDN上提供的netsh的更多信息。