Ví dụ tối thiểu đường ống có tên WCF


90

Tôi đang tìm kiếm ví dụ tối thiểu về WCF Named Pipes (Tôi mong đợi hai ứng dụng tối thiểu, máy chủ và máy khách, có thể giao tiếp thông qua một đường ống được đặt tên.)

Microsoft có một bài viết hay về Hướng dẫn bắt đầu mô tả WCF qua HTTP và tôi đang tìm kiếm một cái gì đó tương tự về WCF và các đường ống được đặt tên.

Tôi đã tìm thấy một số bài đăng trên Internet, nhưng chúng hơi "nâng cao". Tôi cần một cái gì đó tối thiểu, chỉ có chức năng bắt buộc, vì vậy tôi có thể thêm mã của mình và làm cho ứng dụng hoạt động.

Làm cách nào để thay thế nó để sử dụng một đường ống đã đặt tên?

<endpoint address="http://localhost:8000/ServiceModelSamples/Service/CalculatorService"
    binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ICalculator"
    contract="ICalculator" name="WSHttpBinding_ICalculator">
    <identity>
        <userPrincipalName value="OlegPc\Oleg" />
    </identity>
</endpoint>

Làm cách nào để thay thế nó để sử dụng một đường ống đã đặt tên?

// Step 1 of the address configuration procedure: Create a URI to serve as the base address.
Uri baseAddress = new Uri("http://localhost:8000/ServiceModelSamples/Service");

// Step 2 of the hosting procedure: Create ServiceHost
ServiceHost selfHost = new ServiceHost(typeof(CalculatorService), baseAddress);

try
{
    // Step 3 of the hosting procedure: Add a service endpoint.
    selfHost.AddServiceEndpoint(
        typeof(ICalculator),
        new WSHttpBinding(),
        "CalculatorService");

    // Step 4 of the hosting procedure: Enable metadata exchange.
    ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
    smb.HttpGetEnabled = true;
    selfHost.Description.Behaviors.Add(smb);

    // Step 5 of the hosting procedure: Start (and then stop) the service.
    selfHost.Open();
    Console.WriteLine("The service is ready.");
    Console.WriteLine("Press <ENTER> to terminate service.");
    Console.WriteLine();
    Console.ReadLine();

    // Close the ServiceHostBase to shutdown the service.
    selfHost.Close();
}
catch (CommunicationException ce)
{
    Console.WriteLine("An exception occurred: {0}", ce.Message);
    selfHost.Abort();
}

Làm cách nào để tạo một khách hàng để sử dụng một đường ống được đặt tên?


Câu trả lời:


80

Tôi vừa tìm thấy hướng dẫn nhỏ tuyệt vời này . liên kết bị hỏng ( Phiên bản lưu trong bộ nhớ cache )

Tôi cũng đã làm theo hướng dẫn của Microsoft, rất hay, nhưng tôi cũng chỉ cần ống dẫn.

Như bạn thấy, bạn không cần tệp cấu hình và tất cả những thứ lộn xộn đó.

Nhân tiện, anh ấy sử dụng cả HTTP và đường ống. Chỉ cần xóa tất cả các dòng mã liên quan đến HTTP và bạn sẽ nhận được một ví dụ về đường ống thuần túy.


2
Cảm ơn! Ngoài ra, khi cố gắng xây dựng một dịch vụ có sử dụng web.config cho cấu hình của nó thay vì cấu hình mã hóa cứng, xem ví dụ microsoft này: msdn.microsoft.com/en-us/library/ms752253.aspx
nullius

3
Liên kết không hoạt động, hướng dẫn có ở đâu khác không?
user1069816

Chỉ cần dành một thời gian để cố gắng tìm ra lý do tại sao "đường ống đã được kết thúc". Đây là giải pháp của tôi về vấn đề đó, hy vọng sẽ hữu ích: stackoverflow.com/a/49075797/385273
Ben

62

Thử cái này.

Đây là phần dịch vụ.

[ServiceContract]
public interface IService
{
    [OperationContract]
    void  HelloWorld();
}

public class Service : IService
{
    public void HelloWorld()
    {
        //Hello World
    }
}

Đây là Proxy

public class ServiceProxy : ClientBase<IService>
{
    public ServiceProxy()
        : base(new ServiceEndpoint(ContractDescription.GetContract(typeof(IService)),
            new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/MyAppNameThatNobodyElseWillUse/helloservice")))
    {

    }
    public void InvokeHelloWorld()
    {
        Channel.HelloWorld();
    }
}

Và đây là phần dịch vụ lưu trữ.

var serviceHost = new ServiceHost
        (typeof(Service), new Uri[] { new Uri("net.pipe://localhost/MyAppNameThatNobodyElseWillUse") });
    serviceHost.AddServiceEndpoint(typeof(IService), new NetNamedPipeBinding(), "helloservice");
    serviceHost.Open();

    Console.WriteLine("Service started. Available in following endpoints");
    foreach (var serviceEndpoint in serviceHost.Description.Endpoints)
    {
        Console.WriteLine(serviceEndpoint.ListenUri.AbsoluteUri);
    }

Điều này có thể làm việc, nhưng nó không linh động như chỉ chỉnh sửa các tập tin App.config cho client và server ...
Alan S

9
Tuyệt vời, vì việc hiển thị chi tiết ứng dụng thông qua tệp app.config thường không được mong muốn.
Frank Hileman

14
Đây là một ví dụ tuyệt vời, tuy nhiên, không bao giờ sử dụng địa chỉ cơ sở chỉ là net.pipe: // localhost /. Nếu bạn làm như vậy và máy có bất kỳ chương trình nào khác cũng sử dụng net.pipe: // localhost / thì ServiceHost sẽ đưa ra một ngoại lệ khi bạn mở nó. Thay vào đó, hãy sử dụng một cái gì đó độc đáo như net.pipe: // localhost / MyAppNameThatNobodyElseWillUse. Hy vọng điều này sẽ giúp người khác tiết kiệm thời gian và sự thất vọng!
Doug Clutter

Giải pháp này hoạt động tốt. Đặc biệt đối với các điểm cuối nội bộ nơi không cần thiết phải có tham chiếu dịch vụ trong cấu hình. Chỉ cần giữ các hợp đồng - đơn giản là các định nghĩa giao diện - trong assembly riêng của chúng và có lẽ là địa chỉ trong cấu hình. Không có khả năng ràng buộc sẽ thay đổi.
Rob Von Nesselrode

2
Tôi cần thêm /helloservicevào cuối địa chỉ điểm cuối trong proxy.
Mormegil

14

Hãy xem ví dụ về Echo được đơn giản hóa cao của tôi : Nó được thiết kế để sử dụng giao tiếp HTTP cơ bản, nhưng nó có thể dễ dàng được sửa đổi để sử dụng các đường ống được đặt tên bằng cách chỉnh sửatệp app.config cho máy khách và máy chủ. Thực hiện các thay đổi sau:

Chỉnh sửa tệp app.config của máy chủ , xóa hoặc nhận xét mục nhập http baseAddress và thêm mục nhập baseAddress mới cho đường ống được đặt tên (gọi là net.pipe ). Ngoài ra, nếu bạn không có ý định sử dụng HTTP cho một giao thức truyền thông, hãy đảm bảo rằng serviceMetadataserviceDebug được nhận xét hoặc bị xóa:

<configuration>
    <system.serviceModel>
        <services>
            <service name="com.aschneider.examples.wcf.services.EchoService">
                <host>
                    <baseAddresses>
                        <add baseAddress="net.pipe://localhost/EchoService"/>
                    </baseAddresses>
                </host>
            </service>
        </services>
        <behaviors>
            <serviceBehaviors></serviceBehaviors>
        </behaviors>
    </system.serviceModel>
</configuration>

Chỉnh sửa tệp app.config của khách hàng sao cho basicHttpBinding được nhận xét hoặc bị xóa và mục nhập netNamedPipeBinding được thêm vào. Bạn cũng sẽ cần thay đổi mục nhập điểm cuối để sử dụng đường ống:

<configuration>
    <system.serviceModel>
        <bindings>
            <netNamedPipeBinding>
                <binding name="NetNamedPipeBinding_IEchoService"/>
            </netNamedPipeBinding>
        </bindings>
        <client>
            <endpoint address              = "net.pipe://localhost/EchoService"
                      binding              = "netNamedPipeBinding"
                      bindingConfiguration = "NetNamedPipeBinding_IEchoService"
                      contract             = "EchoServiceReference.IEchoService"
                      name                 = "NetNamedPipeBinding_IEchoService"/>
        </client>
    </system.serviceModel>
</configuration>

Ví dụ trên sẽ chỉ chạy với các đường ống được đặt tên, nhưng không có gì ngăn cản bạn sử dụng nhiều giao thức để chạy dịch vụ của mình. AFAIK, bạn sẽ có thể có một máy chủ chạy một dịch vụ bằng cách sử dụng cả đường ống được đặt tên và HTTP (cũng như các giao thức khác).

Ngoài ra, ràng buộc trong tệp app.config của khách hàng được đơn giản hóa rất nhiều. Có nhiều thông số khác nhau mà bạn có thể điều chỉnh, ngoài việc chỉ định baseAddress ...


5
Các liên kết hiện đã chết.
Chris Weber

2

Tôi đã tạo ví dụ đơn giản này từ các kết quả tìm kiếm khác nhau trên internet.

public static ServiceHost CreateServiceHost(Type serviceInterface, Type implementation)
{
  //Create base address
  string baseAddress = "net.pipe://localhost/MyService";

  ServiceHost serviceHost = new ServiceHost(implementation, new Uri(baseAddress));

  //Net named pipe
  NetNamedPipeBinding binding = new NetNamedPipeBinding { MaxReceivedMessageSize = 2147483647 };
  serviceHost.AddServiceEndpoint(serviceInterface, binding, baseAddress);

  //MEX - Meta data exchange
  ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
  serviceHost.Description.Behaviors.Add(behavior);
  serviceHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexNamedPipeBinding(), baseAddress + "/mex/");

  return serviceHost;
}

Sử dụng URI ở trên, tôi có thể thêm một tham chiếu trong ứng dụng khách của mình vào dịch vụ web.


-2

Tôi thấy trang web này thực sự hữu ích và dự án mẫu chạy mà không cần chỉnh sửa gì: https://dotnet-experience.blogspot.com/2012/02/inter-process-duplex-communication-with.html

Đừng quên bật hỗ trợ Named Pipe trong Tính năng của Windows. Bài viết này có một số ảnh chụp màn hình tốt cho hiệu ứng đó trong câu trả lời hàng đầu: WCF Named Pipe trong Windows Service sử dụng App.Config

Dự án được tham chiếu trong giải pháp được chấp nhận không chạy như hiện tại trên PC của tôi. Tôi đã thử một số bản sửa lỗi trong app.config nhưng vẫn nhận được ngoại lệ sau:

System.InvalidOperationException: 'Dịch vụ' WpfWcfNamedPipeBinding.NamedPipeBindingService 'không có điểm cuối ứng dụng (không phải cơ sở hạ tầng). Điều này có thể là do không tìm thấy tệp cấu hình nào cho ứng dụng của bạn hoặc vì không tìm thấy phần tử dịch vụ nào khớp với tên dịch vụ trong tệp cấu hình hoặc vì không có điểm cuối nào được xác định trong phần tử dịch vụ. '

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.