注册具有已知名称的通道,然后通过该已知名称检查并取消注册,而不终止其他应用程序通道

时间:2012-08-20 14:05:50

标签: c# .net tcp remoting

我遇到了应用程序消息传递的问题,...经过一些问答后,我在System.Runtime命名空间下使用了Remoting命名空间......

它工作得很好,但问题是当应用程序终止时有例外... 如果服务器以非方式停止,则通道i注册将保持注册状态,...

我对远程处理或其他相关事项知之甚少...... 但我检查了一些事情,并且没有工作......

我完成了这样注册的文章,并没有取消注册应用程序,我在服务中使用它,似乎服务应用程序主机不关闭只是服务beign停止...

这是我的客户端类,用于服务应用...

using System;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

namespace Remoting
{
    public class Client
    {
        private RemotableObject remoteObject;

        /// <summary>
        /// Configure Client Class
        /// </summary>
        /// <param name="url">Something like: tcp://localhost:8080/HelloWorld</param>
        public Client(string url)
        {
            TcpChannel chan = new TcpChannel();
            ChannelServices.RegisterChannel(chan);

            remoteObject = (RemotableObject)Activator.GetObject(typeof(RemotableObject), url);
        }


        public void SetMessage(string message)
        {
            remoteObject.SetMessage(message);
        }
    }
}

正如我注意到的那样,文章没有给频道提供任何信息,所以我很想知道它应该如何找到它.....

在服务器APP中,文章最后完成了givin主持帖

using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

namespace Remoting
{
    public abstract class Server:IObserver
    {
        private RemotableObject remotableObject;

        /// <summary>
        /// Configure Server Class
        /// </summary>
        /// <param name="port">port number like: 8080</param>
        /// <param name="url">Object url like: HelloWorld</param>
        public Server(int port, string url)
        {
            remotableObject = new RemotableObject();

            TcpChannel channel = new TcpChannel(port);
            ChannelServices.RegisterChannel(channel);
            RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemotableObject), url, WellKnownObjectMode.Singleton);

            Cache.Attach(this);
        }

        public abstract void Notify(string message);
    }
}

但是,即使知道我认为我在运行具有相同端口号的应用程序的服务器上启动我的应用程序,我也不想取消注册其他应用程序渠道......我该怎么办?

BTW大多数问题是关于注册频道的客户端,没有信息......我如何检测它?并在服务尝试执行此操作之前取消注册,并以异常终止?

如果有帮助,这就是我已经收到的错误:

  

事件类型:错误
  活动来源:活动阅读器服务
  活动类别:无
  事件编号:0
  日期:2012年8月20日
  时间:下午5:23:14
  用户:N / A
  电脑:HF-SERVER-PC
  说明:
  服务无法启动。   System.Runtime.Remoting.RemotingException:通道'tcp'是   已经登记了。在   System.Runtime.Remoting.Channels.ChannelServices.RegisterChannelInternal(IChannel   chnl,Boolean ensureSecurity)at   System.Runtime.Remoting.Channels.ChannelServices.RegisterChannel(IChannel   chnl)在Remoting.Client..ctor(String url)at   FileEventReaderService.Services.Logger.EventLogger..ctor(字符串   source,String logName,String url)at   FileEventReaderService.EventReader..ctor(String sqlServer,String   instance,String integratedSecurityType,String username,String   password,String dataBase)at   FileEventReaderService.EventReaderService.OnStart(String [] args)at   System.ServiceProcess.ServiceBase.ServiceQueuedMainCallback(对象   状态)

     

有关详细信息,请参阅位于的“帮助和支持中心”   go.microsoft.com/fwlink/...。

1 个答案:

答案 0 :(得分:1)

在我的情况下,问题在于多个注册tcp通道,在同一个实例中,所以我创建了一个单例类,只设置了一次客户端,所有其他时间我只是调用该实例....

using Remoting;

namespace FileEventReaderService.Services.Remotable
{
    class SingletonClient
    {
        private static SingletonClient _instance = new SingletonClient();
        private Client _client = null;

        public static SingletonClient GetSingletonClient()
        {
            return _instance;
        }

        public Client GetClient()
        {
            return _client;
        }

        public void SetClientConfiguration(string url)
        {
            _client=new Client(url);
        }
    }
}
顺便说一句,如果有人需要找到这个过程......他可以使用这篇文章: http://www.timvw.be/2007/09/09/build-your-own-netstatexe-with-c/下载演示源并使用它......

我也以自己的方式编辑它,你可以使用它:(我没有更改2个主要类'TcpTable'和'IpHelper')

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Net.NetworkInformation;
using System.Net;
using System.Diagnostics;
using System.Collections;
using System.IO;

namespace FileEventReaderUI.Services.Network
{
    class NetworkInformation
    {
        public ListenerProcessInformation GetListenerProcessInformationByPort(int port)
        {
            string fileName;
            List<string> processModules=new List<string>();

            foreach (TcpRow tcpRow in ManagedIpHelper.GetExtendedTcpTable(true))
            {
                if (tcpRow.LocalEndPoint.Port.ToString(CultureInfo.InvariantCulture).Equals(
                        port.ToString(CultureInfo.InvariantCulture))
                    && tcpRow.State==TcpState.Listen)
                {
                    Process process = Process.GetProcessById(tcpRow.ProcessId);
                    if (process.ProcessName != "System")
                    {
                        foreach (ProcessModule processModule in process.Modules)
                        {
                            processModules.Add(processModule.FileName);
                        }

                        fileName = Path.GetFileName(process.MainModule.FileName);
                    }
                    else
                    {
                        //Console.WriteLine("  -- unknown component(s) --"); ProcessModules count=0
                        //Console.WriteLine("  [{0}]", "System");
                        fileName = "[System]";
                    }

                    return new ListenerProcessInformation(fileName
                                                          , processModules.ToArray()
                                                          , new IPEndPoint(tcpRow.LocalEndPoint.Address,
                                                                         tcpRow.LocalEndPoint.Port)
                                                          , new IPEndPoint(tcpRow.RemoteEndPoint.Address,
                                                                         tcpRow.RemoteEndPoint.Port)
                                                          , tcpRow.ProcessId
                                                          , tcpRow.State);
                }
            }
            return null;
        }
    }

    #region Managed IP Helper API

    public class TcpTable : IEnumerable<TcpRow>
    {
        #region Private Fields

        private IEnumerable<TcpRow> tcpRows;

        #endregion

        #region Constructors

        public TcpTable(IEnumerable<TcpRow> tcpRows)
        {
            this.tcpRows = tcpRows;
        }

        #endregion

        #region Public Properties

        public IEnumerable<TcpRow> Rows
        {
            get { return this.tcpRows; }
        }

        #endregion

        #region IEnumerable<TcpRow> Members

        public IEnumerator<TcpRow> GetEnumerator()
        {
            return this.tcpRows.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.tcpRows.GetEnumerator();
        }

        #endregion
    }

    public class TcpRow
    {
        #region Private Fields

        private IPEndPoint localEndPoint;
        private IPEndPoint remoteEndPoint;
        private TcpState state;
        private int processId;

        #endregion

        #region Constructors

        public TcpRow(IpHelper.TcpRow tcpRow)
        {
            this.state = tcpRow.state;
            this.processId = tcpRow.owningPid;

            int localPort = (tcpRow.localPort1 << 8) + (tcpRow.localPort2) + (tcpRow.localPort3 << 24) + (tcpRow.localPort4 << 16);
            long localAddress = tcpRow.localAddr;
            this.localEndPoint = new IPEndPoint(localAddress, localPort);

            int remotePort = (tcpRow.remotePort1 << 8) + (tcpRow.remotePort2) + (tcpRow.remotePort3 << 24) + (tcpRow.remotePort4 << 16);
            long remoteAddress = tcpRow.remoteAddr;
            this.remoteEndPoint = new IPEndPoint(remoteAddress, remotePort);
        }

        #endregion

        #region Public Properties

        public IPEndPoint LocalEndPoint
        {
            get { return this.localEndPoint; }
        }

        public IPEndPoint RemoteEndPoint
        {
            get { return this.remoteEndPoint; }
        }

        public TcpState State
        {
            get { return this.state; }
        }

        public int ProcessId
        {
            get { return this.processId; }
        }

        #endregion
    }

    public static class ManagedIpHelper
    {
        #region Public Methods

        public static TcpTable GetExtendedTcpTable(bool sorted)
        {
            List<TcpRow> tcpRows = new List<TcpRow>();

            IntPtr tcpTable = IntPtr.Zero;
            int tcpTableLength = 0;

            if (IpHelper.GetExtendedTcpTable(tcpTable, ref tcpTableLength, sorted, IpHelper.AfInet, IpHelper.TcpTableType.OwnerPidAll, 0) != 0)
            {
                try
                {
                    tcpTable = Marshal.AllocHGlobal(tcpTableLength);
                    if (IpHelper.GetExtendedTcpTable(tcpTable, ref tcpTableLength, true, IpHelper.AfInet, IpHelper.TcpTableType.OwnerPidAll, 0) == 0)
                    {
                        IpHelper.TcpTable table = (IpHelper.TcpTable)Marshal.PtrToStructure(tcpTable, typeof(IpHelper.TcpTable));

                        IntPtr rowPtr = (IntPtr)((long)tcpTable + Marshal.SizeOf(table.length));
                        for (int i = 0; i < table.length; ++i)
                        {
                            tcpRows.Add(new TcpRow((IpHelper.TcpRow)Marshal.PtrToStructure(rowPtr, typeof(IpHelper.TcpRow))));
                            rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(typeof(IpHelper.TcpRow)));
                        }
                    }
                }
                finally
                {
                    if (tcpTable != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(tcpTable);
                    }
                }
            }

            return new TcpTable(tcpRows);
        }

        #endregion
    }

    #endregion

    #region P/Invoke IP Helper API

    /// <summary>
    /// <see cref="http://msdn2.microsoft.com/en-us/library/aa366073.aspx"/>
    /// </summary>
    public static class IpHelper
    {
        #region Public Fields

        public const string DllName = "iphlpapi.dll";
        public const int AfInet = 2;

        #endregion

        #region Public Methods

        /// <summary>
        /// <see cref="http://msdn2.microsoft.com/en-us/library/aa365928.aspx"/>
        /// </summary>
        [DllImport(IpHelper.DllName, SetLastError = true)]
        public static extern uint GetExtendedTcpTable(IntPtr tcpTable, ref int tcpTableLength, bool sort, int ipVersion, TcpTableType tcpTableType, int reserved);

        #endregion

        #region Public Enums

        /// <summary>
        /// <see cref="http://msdn2.microsoft.com/en-us/library/aa366386.aspx"/>
        /// </summary>
        public enum TcpTableType
        {
            BasicListener,
            BasicConnections,
            BasicAll,
            OwnerPidListener,
            OwnerPidConnections,
            OwnerPidAll,
            OwnerModuleListener,
            OwnerModuleConnections,
            OwnerModuleAll,
        }

        #endregion

        #region Public Structs

        /// <summary>
        /// <see cref="http://msdn2.microsoft.com/en-us/library/aa366921.aspx"/>
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct TcpTable
        {
            public uint length;
            public TcpRow row;
        }

        /// <summary>
        /// <see cref="http://msdn2.microsoft.com/en-us/library/aa366913.aspx"/>
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct TcpRow
        {
            public TcpState state;
            public uint localAddr;
            public byte localPort1;
            public byte localPort2;
            public byte localPort3;
            public byte localPort4;
            public uint remoteAddr;
            public byte remotePort1;
            public byte remotePort2;
            public byte remotePort3;
            public byte remotePort4;
            public int owningPid;
        }

        #endregion
    }

    #endregion
}

和我用来填充的实体类......

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.NetworkInformation;
using System.Text;

namespace FileEventReaderUI.Services.Network
{
    class ListenerProcessInformation
    {
        private string _fileName;
        private string[] _processModules;
        private IPEndPoint _localEndPoint;
        private IPEndPoint _remoteEndPoint;
        private int _processId;
        private TcpState _state;

        public ListenerProcessInformation(string fileName, string[] processModules, IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, int processId, TcpState state)
        {
            _fileName = fileName;
            _processModules = processModules;
            _localEndPoint = localEndPoint;
            _remoteEndPoint = remoteEndPoint;
            _processId = processId;
            _state = state;
        }

        public string FileName
        {
            get { return _fileName; }
        }

        public string[] ProcessModules
        {
            get { return _processModules; }
        }

        public IPEndPoint LocalEndPoint
        {
            get { return _localEndPoint; }
        }

        public IPEndPoint RemoteEndPoint
        {
            get { return _remoteEndPoint; }
        }

        public int ProcessId
        {
            get { return _processId; }
        }

        public TcpState State
        {
            get { return _state; }
        }
    }
}