Подключение к WCF, работающему как Windows Сервис на другом компьютере - PullRequest
0 голосов
/ 29 января 2020

У меня есть клиентское приложение WinForms. У меня сервер WCF работает на другом компьютере как часть службы Windows, которую я написал. Сначала я попробовал NetPipeBinding, а теперь NetTcpBinding. Я открыл 2 порта в Windows Firewall с расширенной безопасностью . Операционная система сервера: Windows Сервер 2016 .

. Вот код сервера:

public Boolean CreatePipeServer(out string logEntry)
{
    try
    {
        NetTcpBinding ipcBinding = new NetTcpBinding()
        {
            Security = new NetTcpSecurity()
            {
                Mode = SecurityMode.None,
                Transport = new TcpTransportSecurity()
                {
                    ClientCredentialType = TcpClientCredentialType.None,
                    ProtectionLevel = System.Net.Security.ProtectionLevel.None,
                },
            },
            MaxBufferPoolSize = 6553600,
            MaxBufferSize = 6553600,
            MaxReceivedMessageSize = 6553600,
            MaxConnections = 1000,
            ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
            {
                MaxArrayLength = 2147483647,
                MaxBytesPerRead = 2147483647,
                MaxDepth = 2147483647,
                MaxNameTableCharCount = 2147483647,
                MaxStringContentLength = 2147483647,
            },
        };

        // Instantiate: Host Service
        Uri uriMex = new Uri("http://localhost:8000");
        this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService = new ServiceHost(typeof(IpcAppToService), uriMex);

        // Instantiate: Endpoint
        Uri uriService = new Uri("net.tcp://localhost:8004/StampIpcAppToService");
        this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService.AddServiceEndpoint(typeof(StampIpc.IIpcAppToService), ipcBinding, uriService);

        // Instantiate: Service Meta Behavior
        ServiceMetadataBehavior ipcSmb = this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService.Description.Behaviors.Find<ServiceMetadataBehavior>();
        if (null == ipcSmb)
        {
            ipcSmb = new ServiceMetadataBehavior()
            {
                HttpGetEnabled = true,
            };
            this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService.Description.Behaviors.Add(ipcSmb);
            ServiceDescription serviceDescription = this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService.Description;
        }

        // Instantiate: MEX Biding
        Binding ipcMexBinding = MetadataExchangeBindings.CreateMexHttpBinding();
        this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService.AddServiceEndpoint(typeof(IMetadataExchange), ipcMexBinding, "MEX");

        // Capture events.
        ...

        // Start the service.
        this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService.Open();

        return true;
    }

    catch (Exception) { }

return false;
}

Я пытаюсь проверить действующий канал связи, перейдя к Add > Service Reference... в Visual Studio 2019. Независимо от того, что я печатаю, я получаю ошибки того или иного рода. В настоящее время я разместил:

net.tcp://10.10.70.134:8004/StampIpcAppToService

Это выдает ошибку:

Префикс URI не распознан. Метаданные содержат ссылку, которая не может быть разрешена: 'net .tcp: //10.10.70.134: 8004 / StampIpcAppToService'. Метаданные содержат ссылку, которая не может быть разрешена: 'net .tcp: //10.10.70.134: 8004 / StampIpcAppToService'. Если служба определена в текущем решении, попробуйте создать решение и снова добавить ссылку на службу.

У меня уже есть код клиента, но если я не могу заставить работать Add Service Reference, тогда код клиента определенно не будет работать.

Приведенный выше код начинается как часть события OnStart для Windows Service.

Что я делаю не так?

ОБНОВЛЕНИЕ

Ответ разрешил прямой вопрос выше, однако мой реальный код использует код, похожий на серверный, и я получаю ошибку. Я изменил код, основываясь на ответе и немного отладки. Текущий код:

Исключение:

InnerException = {"Сообщение с действием '

http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequence' не может быть обработано в получателе, из-за несоответствия ContractFilter в EndpointDispatcher. Это может быть связано либо с несоответствием контракта (несоответствующие действия между ...

ОБНОВЛЕНИЕ 2 (отражает обновленный ответ)

Использование NetTcpBinding создает эту ошибку:

Использование URI:

Uri ipcUri = new Uri($"net.tcp://10.10.70.134:8004");

Создание

Message = "There was no endpoint listening at net.tcp://jmr-engineering:8004/ that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details."

Использование URI:

Uri ipcUri = new Uri($"net.tcp://10.10.70.134:8000");

Генерирует

Message = "You have tried to create a channel to a service that does not support .Net Framing. It is possible that you are encountering an HTTP endpoint."

InnerException = {"Expected record type 'PreambleAck', found '72'."}

ОТВЕТ:

Принятый ответ нуждается в модификации. У Авраама не было правильного URI, однако он указал мне на SvcUtil.exe, который дал мне это.

URI:

net.tcp://10.10.70.134:8004/StampIpcAppToService

Мне нужно NetTcpBinding, поэтому окончательный код на стороне клиента:

Здесь вывод output.config из SvcUtil.exe. Файл IpcAppToService.cs был бесполезен, но файл конфигурации определенно был полезен.

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
        <system.serviceModel>
        <bindings>
            <netTcpBinding>
            <binding name="NetTcpBinding_IIpcAppToService">
                <security mode="None" />
            </binding>
            </netTcpBinding>
        </bindings>
        <client>
            <endpoint address="net.tcp://localhost:8004/StampIpcAppToService"
            binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IIpcAppToService"
            contract="IIpcAppToService" name="NetTcpBinding_IIpcAppToService" />
        </client>
        </system.serviceModel>
    </configuration>

1 Ответ

1 голос
/ 29 января 2020

Добавление ссылки на службу основывается на адресе метаданных службы, а не на адресе службы. В соответствии с указанными выше настройками значение Uri в диалоговом окне «Добавление службы» должно быть следующим:

http://10.10.70.134: 8000 / мекс

В общем мы должны предоставить метаданные либо путем добавления конечной точки Mex, либо с помощью свойства HttpGetEnabled ServiceMetedataBehavior. Впоследствии на стороне клиента можно сгенерировать клиентский прокси с помощью инструмента SVCUtil.
https://docs.microsoft.com/en-us/dotnet/framework/wcf/accessing-services-using-a-wcf-client
В Visual Studio диалоговое окно Adding Service reference представляет собой ярлык для создания клиента прокси. Он опирается на конечную точку службы Mex. Для быстрого доступа необходим адрес конечной точки Mex.
Не стесняйтесь, дайте мне знать, если есть что-то, с чем я могу помочь.
Обновлено.
Дуплексная связь означает, что мы должны использовать Nettcpbinding (поддерживает дуплекс) на стороне клиента.

class Program
    {
        static void Main(string[] args)
        {
            NetTcpBinding binding = new NetTcpBinding()
            {
                Security = new NetTcpSecurity
                {
                    Mode = SecurityMode.None
                },
                MaxBufferPoolSize = 6553600,
                MaxBufferSize = 6553600,
                MaxReceivedMessageSize = 6553600,
                MaxConnections = 1000,
                ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
                {
                    MaxArrayLength = 2147483647,
                    MaxBytesPerRead = 2147483647,
                    MaxDepth = 2147483647,
                    MaxNameTableCharCount = 2147483647,
                    MaxStringContentLength = 2147483647,
                },
            };
            //replace it with your practical service address.
            Uri uri = new Uri("net.tcp://10.157.13.69:8004");
            ChannelFactory<IService> factory = new ChannelFactory<IService>(binding, new EndpointAddress(uri));
            IService service = factory.CreateChannel();
            var result = service.Test();
            Console.WriteLine(result);

        }

    }

    //the service contract shared between the client-side and the server-side.
    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        string Test();

    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...