2015-12-22 10 views
2

Я нахожусь в процессе написания службы WCF Duplex для приложения чата с клиентом WPF. Код сервиса нижеУдаленная конечная точка запросила адрес для подтверждений, который не совпадает с адресом для сообщений приложения

IChatCallback

public interface IChatCallback 
{ 
    #region Public Methods and Operators 

    [OperationContract(IsOneWay = true)] 
    void Receive(Person sender, string message); 

    [OperationContract(IsOneWay = true)] 
    void ReceiveWhisper(Person sender, string message); 

    [OperationContract(IsOneWay = true)] 
    void UserEnter(Person person); 

    [OperationContract(IsOneWay = true)] 
    void UserLeave(Person person); 

    #endregion 
} 

IChatService

[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IChatCallback))] 
public interface IChatService 
{ 
    #region Public Methods and Operators 

    [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)] 
    void Say(string message); 

    [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)] 
    void Whisper(string to, string message); 

    [OperationContract(IsOneWay = false, IsInitiating = true, IsTerminating = false)] 
    Person[] Join(Person person); 

    [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = true)] 
    void Leave(); 

    #endregion 
} 

ChatService

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Multiple)] 
public class ChatService : IChatService 
{ 
    #region Static Fields 

    private static object _syncObj = new object(); 

    private static Dictionary<Person, ChatEventHandler> _chatters = new Dictionary<Person, ChatEventHandler>(); 

    #endregion 

    #region Fields 

    private IChatCallback _callback = null; 

    private ChatEventHandler _myEventHandler; 

    private Person _person; 

    #endregion 

    #region Delegates 

    public delegate void ChatEventHandler(object sender, ChatEventArgs e); 

    #endregion 

    #region Public Events 

    public static event ChatEventHandler ChatEvent; 

    #endregion 

    #region Public Methods and Operators 

    public void Say(string message) 
    { 
     ChatEventArgs e = new ChatEventArgs(MessageType.Receive, this._person, message); 
     this.BroadcastMessage(e); 
    } 

    public void Whisper(string to, string message) 
    { 
     ChatEventArgs e = new ChatEventArgs(MessageType.ReceiveWhisper, this._person, message); 
     try 
     { 
      ChatEventHandler chatterTo; 
      lock (_syncObj) 
      { 
       chatterTo = this.GetPersonHandler(to); 
       if (chatterTo == null) 
       { 
        throw new KeyNotFoundException(
         string.Format(
          CultureInfo.InvariantCulture, 
          "The person with name [{0}] could not be found", 
          to)); 
       } 
      } 

      chatterTo.BeginInvoke(this, e, new AsyncCallback(EndAsync), null); 
     } 
     catch (KeyNotFoundException) 
     { 
     } 
    } 

    public Person[] Join(Person person) 
    { 
     bool userAdded = false; 
     this._myEventHandler = new ChatEventHandler(this.MyEventHandler); 

     lock (_syncObj) 
     { 
      if (!this.CheckIfPersonExists(person.Name) && person != null) 
      { 
       this._person = person; 
       _chatters.Add(person, this.MyEventHandler); 
       userAdded = true; 
      } 
     } 

     if (userAdded) 
     { 
      this._callback = OperationContext.Current.GetCallbackChannel<IChatCallback>(); 
      ChatEventArgs e = new ChatEventArgs(MessageType.UserEnter, this._person); 
      this.BroadcastMessage(e); 
      ChatEvent += this._myEventHandler; 
      Person[] list = new Person[_chatters.Count]; 

      lock (_syncObj) 
      { 
       _chatters.Keys.CopyTo(list, 0); 
      } 

      return list; 
     } 
     else 
     { 
      return null; 
     } 
    } 

    public void Leave() 
    { 
     if (this._person == null) 
     { 
      return; 
     } 

     ChatEventHandler chatterToRemove = this.GetPersonHandler(this._person.Name); 

     lock (_syncObj) 
     { 
      _chatters.Remove(this._person); 
     } 

     ChatEvent -= chatterToRemove; 
     ChatEventArgs e = new ChatEventArgs(MessageType.UserLeave, this._person); 
     this.BroadcastMessage(e); 
    } 

    #endregion 

    private void MyEventHandler(object sender, ChatEventArgs e) 
    { 
     try 
     { 
      switch (e.MessageType) 
      { 
       case MessageType.Receive: 
        this._callback.Receive(e.Person, e.Message); 
        break; 

       case MessageType.ReceiveWhisper: 
        this._callback.ReceiveWhisper(e.Person, e.Message); 
        break; 

       case MessageType.UserEnter: 
        this._callback.UserEnter(e.Person); 
        break; 

       case MessageType.UserLeave: 
        this._callback.UserLeave(e.Person); 
        break; 
      } 
     } 
     catch 
     { 
      this.Leave(); 
     } 
    } 

    private void BroadcastMessage(ChatEventArgs e) 
    { 
     ChatEventHandler temp = ChatEvent; 
     if (temp != null) 
     { 
      foreach (ChatEventHandler handler in temp.GetInvocationList()) 
      { 
       handler.BeginInvoke(this, e, new AsyncCallback(this.EndAsync), null); 
      } 
     } 
    } 

    private bool CheckIfPersonExists(string name) 
    { 
     foreach (Person p in _chatters.Keys) 
     { 
      if (p.Name.Equals(name, StringComparison.OrdinalIgnoreCase)) 
      { 
       return true; 
      } 
     } 

     return false; 
    } 

    private void EndAsync(IAsyncResult ar) 
    { 
     ChatEventHandler d = null; 

     try 
     { 
      AsyncResult asres = (AsyncResult)ar; 
      d = (ChatEventHandler)asres.AsyncDelegate; 
      d.EndInvoke(ar); 
     } 
     catch 
     { 
      ChatEvent -= d; 
     } 
    } 

    private ChatEventHandler GetPersonHandler(string name) 
    { 
     foreach (Person p in _chatters.Keys) 
     { 
      if (p.Name.Equals(name, StringComparison.OrdinalIgnoreCase)) 
      { 
       ChatEventHandler chatTo = null; 
       _chatters.TryGetValue(p, out chatTo); 
       return chatTo; 
      } 
     } 

     return null; 
    } 
} 

Это размещается в консольного приложения с конечной net.tcp: // localhost: 33333/chatservice с использованием netTcpBinding со следующей конфигурацией связывания

<system.serviceModel> 
    <services> 
    <service name="Cleo.Services.Chat.ChatService" behaviorConfiguration="CleoChatBehavior"> 
     <host> 
     <baseAddresses> 
      <add baseAddress="net.tcp://localhost:33333/chatservice"/> 
     </baseAddresses> 
     </host> 
     <endpoint address="" binding="netTcpBinding" bindingConfiguration="DuplexBinding" contract="Cleo.Services.Chat.IChatService"/> 
    </service> 
    </services> 

    <behaviors> 
    <serviceBehaviors> 
     <behavior name="CleoChatBehavior"> 
     <serviceThrottling maxConcurrentSessions="10000"/> 
     <serviceDebug includeExceptionDetailInFaults="true"/> 
     </behavior> 
    </serviceBehaviors> 
    </behaviors> 

    <bindings> 
    <netTcpBinding> 
     <binding name="DuplexBinding" maxBufferSize="67108864" maxReceivedMessageSize="67108864" maxBufferPoolSize="67108864" transferMode="Buffered" closeTimeout="00:00:10" openTimeout="00:00:10" receiveTimeout="00:20:00" sendTimeout="00:01:00" maxConnections="100"> 
     <reliableSession enabled="true" inactivityTimeout="00:20:00" /> 
     <security mode="None" /> 
     <readerQuotas maxArrayLength="67108864" maxBytesPerRead="67108864" maxStringContentLength="67108864" /> 
     </binding> 
    </netTcpBinding> 
    </bindings> 
</system.serviceModel> 

В моем WPF клиент я реализовал прокси к сервису с помощью SvcUtil, который находится ниже:

IChatServiceCallback

[GeneratedCode("System.ServiceModel", "4.0.0.0")] 
public interface IChatServiceCallback 
{ 
    #region Public Methods and Operators 

    [OperationContract(IsOneWay = true, Action = "http://tempuri.org/IChatService/Receive")] 
    void Receive(Person sender, string message); 

    [OperationContract(IsOneWay = true, AsyncPattern = true, Action = "http://tempuri.org/IChatService/Receive")] 
    IAsyncResult BeginReceive(Person sender, string message, AsyncCallback callback, object asyncState); 

    void EndReceive(IAsyncResult result); 

    [OperationContract(IsOneWay = true, Action = "http://tempuri.org/IChatService/ReceiveWhisper")] 
    void ReceiveWhisper(Person sender, string message); 

    [OperationContract(IsOneWay = true, AsyncPattern = true, 
     Action = "http://tempuri.org/IChatService/ReceiveWhisper")] 
    IAsyncResult BeginReceiveWhisper(Person sender, string message, AsyncCallback callback, object asyncState); 

    void EndReceiveWhisper(IAsyncResult result); 

    [OperationContract(IsOneWay = true, Action = "http://tempuri.org/IChatService/UserEnter")] 
    void UserEnter(Person person); 

    [OperationContract(IsOneWay = true, AsyncPattern = true, Action = "http://tempuri.org/IChatService/UserEnter")] 
    IAsyncResult BeginUserEnter(Person person, AsyncCallback callback, object asyncState); 

    void EndUserEnter(IAsyncResult result); 

    [OperationContract(IsOneWay = true, Action = "http://tempuri.org/IChatService/UserLeave")] 
    void UserLeave(Person person); 

    [OperationContract(IsOneWay = true, AsyncPattern = true, Action = "http://tempuri.org/IChatService/UserLeave")] 
    IAsyncResult BeginUserLeave(Person person, AsyncCallback callback, object asyncState); 

    void EndUserLeave(IAsyncResult result); 

    #endregion 
} 

IChatService

[GeneratedCode("System.ServiceModel", "4.0.0.0")] 
[ServiceContract(ConfigurationName = "IChatService", CallbackContract = typeof(IChatServiceCallback), 
    SessionMode = SessionMode.Required)] 
public interface IChatService 
{ 
    #region Public Methods and Operators 

    [OperationContract(IsOneWay = true, IsInitiating = false, Action = "http://tempuri.org/IChatService/Say")] 
    void Say(string message); 

    [OperationContract(IsOneWay = true, IsInitiating = false, AsyncPattern = true, 
     Action = "http://tempuri.org/IChatService/Say")] 
    IAsyncResult BeginSay(string message, AsyncCallback callback, object asyncState); 

    void EndSay(IAsyncResult result); 

    [OperationContract(IsOneWay = true, IsInitiating = false, Action = "http://tempuri.org/IChatService/Whisper")] 
    void Whisper(string to, string message); 

    [OperationContract(IsOneWay = true, IsInitiating = false, AsyncPattern = true, 
     Action = "http://tempuri.org/IChatService/Whisper")] 
    IAsyncResult BeginWhisper(string to, string message, AsyncCallback callback, object asyncState); 

    void EndWhisper(IAsyncResult result); 

    [OperationContract(Action = "http://tempuri.org/IChatService/Join", 
     ReplyAction = "http://tempuri.org/IChatService/JoinResponse")] 
    Person[] Join(Person person); 

    [OperationContract(AsyncPattern = true, Action = "http://tempuri.org/IChatService/Join", 
     ReplyAction = "http://tempuri.org/IChatService/JoinResponse")] 
    IAsyncResult BeginJoin(Person person, AsyncCallback callback, object asyncState); 

    Person[] EndJoin(IAsyncResult result); 

    [OperationContract(IsOneWay = true, IsTerminating = true, IsInitiating = false, 
     Action = "http://tempuri.org/IChatService/Leave")] 
    void Leave(); 

    [OperationContract(IsOneWay = true, IsTerminating = true, IsInitiating = false, AsyncPattern = true, 
     Action = "http://tempuri.org/IChatService/Leave")] 
    IAsyncResult BeginLeave(AsyncCallback callback, object asyncState); 

    void EndLeave(IAsyncResult result); 

    #endregion 
} 

IChatServiceChannel

[GeneratedCode("System.ServiceModel", "4.0.0.0")] 
public interface IChatServiceChannel : IChatService, IClientChannel 
{ 
} 

и ChatProxy

[DebuggerStepThrough] 
[GeneratedCode("System.ServiceModel", "4.0.0.0")] 
public class ChatProxy : DuplexClientBase<IChatService>, IChatService 
{ 
    #region Constructors and Destructors 

    public ChatProxy(InstanceContext callbackInstance) 
     : base(callbackInstance) 
    { 
    } 

    public ChatProxy(InstanceContext callbackInstance, string endpointConfigurationName) 
     : base(callbackInstance, endpointConfigurationName) 
    { 
    } 

    public ChatProxy(InstanceContext callbackInstance, string endpointConfigurationName, string remoteAddress) 
     : base(callbackInstance, endpointConfigurationName, remoteAddress) 
    { 
    } 

    public ChatProxy(
     InstanceContext callbackInstance, 
     string endpointConfigurationName, 
     EndpointAddress remoteAddress) 
     : base(callbackInstance, endpointConfigurationName, remoteAddress) 
    { 
    } 

    public ChatProxy(InstanceContext callbackInstance, Binding binding, EndpointAddress remoteAddress) 
     : base(callbackInstance, binding, remoteAddress) 
    { 
    } 

    #endregion 

    #region Public Methods and Operators 

    public void Say(string message) 
    { 
     this.Channel.Say(message); 
    } 

    public IAsyncResult BeginSay(string message, AsyncCallback callback, object asyncState) 
    { 
     return this.Channel.BeginSay(message, callback, asyncState); 
    } 

    public void EndSay(IAsyncResult result) 
    { 
     this.Channel.EndSay(result); 
    } 

    public void Whisper(string to, string message) 
    { 
     this.Channel.Whisper(to, message); 
    } 

    public IAsyncResult BeginWhisper(string to, string message, AsyncCallback callback, object asyncState) 
    { 
     return this.Channel.BeginWhisper(to, message, callback, asyncState); 
    } 

    public void EndWhisper(IAsyncResult result) 
    { 
     this.Channel.EndWhisper(result); 
    } 

    public Person[] Join(Person person) 
    { 
     return this.Channel.Join(person); 
    } 

    public IAsyncResult BeginJoin(Person person, AsyncCallback callback, object asyncState) 
    { 
     return this.Channel.BeginJoin(person, callback, asyncState); 
    } 

    public Person[] EndJoin(IAsyncResult result) 
    { 
     return this.Channel.EndJoin(result); 
    } 

    public void Leave() 
    { 
     this.Channel.Leave(); 
    } 

    public IAsyncResult BeginLeave(AsyncCallback callback, object asyncState) 
    { 
     return this.Channel.BeginLeave(callback, asyncState); 
    } 

    public void EndLeave(IAsyncResult result) 
    { 
     this.Channel.EndLeave(result); 
    } 

    #endregion 
} 

При конфигурации клиента в главном приложении:

<system.serviceModel> 
    <bindings> 
    <wsHttpBinding> 
     <binding name="CleoDefaultBinding" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="33554432" maxReceivedMessageSize="4194304" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false"> 
     <readerQuotas maxDepth="32" maxStringContentLength="4194304" maxArrayLength="32768" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> 
     <security mode="Transport"> 
      <transport clientCredentialType="Certificate" /> 
     </security> 
     </binding> 
    </wsHttpBinding> 
    <netTcpBinding> 
     <binding name="DuplexBinding" sendTimeout="00:00:30"> 
     <reliableSession enabled="true"/> 
     <security mode="None"/> 
     </binding> 
    </netTcpBinding> 
    </bindings> 
    <client> 
    <!-- Cleo Chat Client --> 
    <endpoint name="CleoChatWcfServiceClient" address="net.tcp://localhost:33333/chatservice" binding="netTcpBinding" bindingConfiguration="DuplexBinding" contract="IChatService"/> 
    <endpoint address="net.tcp://localhost:51638/services/chat/wcf" binding="netTcpBinding" bindingConfiguration="DuplexBinding" contract="CleoChatClient.ICleoChatWcfService" name="chatWcfService" /> 
    </client> 
</system.serviceModel> 

Ok, все хорошо, за исключением какой-то причине я получаю сообщение об ошибке при выполнении следующего кода для подключения к услуге, код:

public class ProxySingleton : IChatServiceCallback 
{ 
... 
    public void Connect(Person p) 
    { 
     var site = new InstanceContext(this); 
     this._proxy = new ChatProxy(site); 
     var iar = this._proxy.BeginJoin(p, this.OnEndJoin, null); 
    } 

    private void OnEndJoin(IAsyncResult ar) 
    { 
     try 
     { 
      var list = this._proxy.EndJoin(ar); --> Errors here!! 
      this.HandleEndJoin(list); 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); 
     } 
    } 

... 
} 

Ошибка, которую я получаю:

Удаленная конечная точка запросила адрес для подтверждений, который не совпадает с адресом для сообщений приложения. Не удалось открыть канал, потому что он не поддерживается. Убедитесь, что адрес конечной точки, используемый для создания канала, идентичен адресу, который был настроен для удаленной конечной точки.

Мой вопрос (и извините за очень длинный пост, но я полностью застрял на этом), просто ли кто-нибудь еще встретил это и мог бы указать мне на ответ, пожалуйста?

EDIT: Я обновлен, чтобы включить полные разделы ServiceModel с сервера и клиента, а также обновил ProxySingleton, чтобы показать, что он реализует интерфейс обратного вызова

+0

Прежде всего, было бы намного лучше, если бы вы разместили весь раздел '' вашего конфигурационного файла. В вашем 'ProxySingleton' вы передаете' this' в качестве параметра 'InstanceContext'. Использует ли 'ProxySingleton'' IChatServiceCallback'? Кроме того, по какой-либо причине, по-видимому, вы не выполнили стандартную процедуру ** Add-> Service Reference ... ** и вручную создаете свой прокси-клиент службы? – jsanalytics

+0

Сообщения об ошибках WCF могут оказаться сложными для выяснения. Включение трассировки может быть очень полезно: [MSDN - настройка трассировки] (https://msdn.microsoft.com/en-us/library/ms733025%28v=vs.110%29.aspx) – jsanalytics

+0

Создание клиента прокси-сервера службы самостоятельно это смелая задача. Ты сделал это? Если бы вы это сделали, я бы также предложил создать служебный прокси по стандартной процедуре (Add -> Service Reference) от вашего клиента. И в '' для узла приложения App.config вы можете добавить базовый адрес http, чтобы помочь создать прокси для вас из этого порта: ''. Обратите внимание на дополнительный '' – Ian

ответ

2

Вот полнофункциональная настройка для ChatService:

Ведущий:

class ProgramHost 
{ 
    static void Main(string[] args) 
    { 
     try 
     { 
      ServiceHost host = new ServiceHost(typeof(ChatLib.ChatService)); 

      host.Open(); 

      Console.WriteLine(string.Format("WCF {0} host is running...", host.Description.ServiceType)); 

      Console.WriteLine("Endpoints:"); 
      foreach (ServiceEndpoint se in host.Description.Endpoints) 
      { 
       Console.WriteLine("***********************************************"); 
       Console.WriteLine(string.Format("Address = {0}", se.Address)); 
       Console.WriteLine(string.Format("Binding = {0}", se.Binding)); 
       Console.WriteLine(string.Format("Contract = {0}", se.Contract.Name)); 
      } 

      Console.WriteLine(string.Empty); 
      Console.WriteLine("Press <ENTER> to terminate."); 

      Console.ReadLine(); 

      host.Close(); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.ToString()); 
     } 
    } 
} 

Клиент:

class ProgramClient 
{ 
    static void Main(string[] args) 
    { 
     try 
     { 
      if (args.Length != 1) 
       Console.WriteLine("usage: clientconsole username"); 
      else 
      { 
       Person user = new Person(args[0]); 

       IChatServiceCallback callback = new SimpleChatCallback(); 

       InstanceContext instanceContext = new InstanceContext(callback); 
       ChatServiceClient serviceProxy = new ChatServiceClient(instanceContext); 

       Console.WriteLine("Endpoint:"); 
       Console.WriteLine("***********************************************"); 
       Console.WriteLine(string.Format("Address = {0}", serviceProxy.Endpoint.Address)); 
       Console.WriteLine(string.Format("Binding = {0}", serviceProxy.Endpoint.Binding)); 
       Console.WriteLine(string.Format("Contract = {0}", serviceProxy.Endpoint.Contract.Name)); 

       Person[] people = serviceProxy.Join(user); 

       Console.WriteLine("***********************************************"); 
       Console.WriteLine("Connected !"); 
       Console.WriteLine("Online users:"); 

       foreach (Person p in people) 
        Console.WriteLine(p.Name); 

       string msg; 
       while ((msg = Console.ReadLine()) != "exit") 
        serviceProxy.Say(msg); 

       serviceProxy.Leave(); 

       if (serviceProxy.State != CommunicationState.Faulted) 
        serviceProxy.Close(); 
      } 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message); 
     } 
    } 
} 

Клиент обратного вызова:

public class SimpleChatCallback : IChatServiceCallback 
{ 
    public void Receive(Person sender, string message) 
    { 
     Console.WriteLine("{0}: {1}", sender.Name, message); 
    } 

    public void ReceiveWhisper(Person sender, string message) 
    { 
     Console.WriteLine("{0}: {1}", sender.Name, message); 
    } 

    public void UserEnter(Person person) 
    { 
     Console.WriteLine("{0} has entered", person.Name); 
    } 

    public void UserLeave(Person person) 
    { 
     Console.WriteLine("{0} has left", person.Name); 
    } 
} 

Хост конфигурации:

<system.serviceModel> 
    <services> 
     <service behaviorConfiguration="mexBehavior" name="ChatLib.ChatService"> 
     <clear /> 
     <endpoint address="ChatService.svc" binding="netTcpBinding" bindingConfiguration="" 
      name="netTcpEndpoint" bindingName="NonSecureTcpBinding" contract="Common.IChatService" /> 
     <endpoint binding="mexHttpBinding" bindingConfiguration="mexHttpBinding" 
      name="mexHttpEndpoint" contract="IMetadataExchange" /> 
     <host> 
      <baseAddresses> 
      <add baseAddress="http://localhost:33334/chatservice" /> 
      <add baseAddress="net.tcp://localhost:33333/chatservice" /> 
      </baseAddresses> 
      <timeouts openTimeout="00:10:00" /> 
     </host> 
     </service> 
    </services> 
    <bindings> 
     <netTcpBinding> 
     <binding name="NonSecureTcpBinding"> 
      <security mode="None"> 
      <transport clientCredentialType="None" protectionLevel="None" /> 
      <message clientCredentialType="None" /> 
      </security> 
     </binding> 
     </netTcpBinding> 
     <mexHttpBinding> 
     <binding name="mexHttpBinding" /> 
     </mexHttpBinding> 
    </bindings> 
    <behaviors> 
     <serviceBehaviors> 
     <behavior name="mexBehavior"> 
      <serviceDebug includeExceptionDetailInFaults="true" /> 
      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" /> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <protocolMapping> 
     <remove scheme="net.tcp" /> 
     <add scheme="net.tcp" binding="netTcpBinding" bindingConfiguration="NonSecureTcpBinding" /> 
     <add scheme="https" binding="basicHttpsBinding" /> 
    </protocolMapping> 
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" /> 
    </system.serviceModel> 

Клиент конфигурации:

<system.serviceModel> 
    <bindings> 
     <netTcpBinding> 
      <binding name="netTcpEndpoint" /> 
     </netTcpBinding> 
    </bindings> 
    <client> 
     <endpoint address="net.tcp://localhost:33333/chatservice/ChatService.svc" 
      binding="netTcpBinding" bindingConfiguration="netTcpEndpoint" 
      contract="ServiceReference1.IChatService" name="netTcpEndpoint"> 
      <identity> 
       <userPrincipalName value="ComputerName\UserName" /> 
      </identity> 
     </endpoint> 
    </client> 
</system.serviceModel> 

выход Ведущий:

enter image description here

Client 1 выход:

enter image description here

Client 2 Выход:

enter image description here

Примечания:

ServiceReference1 является пространством имен по умолчанию, присвоенный Visual Studio для сгенерированного прокси-клиента ChatServiceClient ,

ChatLib - это локально назначенное пространство имен для вашей реализации ChatService.

+0

Я реализовал выше, и добавление ссылки на службу действительно работает, это все еще не отвечает на вопрос относительно сообщения об ошибке, которое я получаю. Я считаю, что сообщение об ошибке, которое я получаю, связано с различием между svcutil и Add -> Service Reference. Клиент, сгенерированный с использованием svcutil, добавляет BeginJoin и EndJoin для методов async, тогда как Add -> Service Reference добавляет JoinAsync, я считаю, что ошибка указывает на то, что вызов для BeginJoin и EndJoin недействителен, было бы более полезно, если бы ошибка была меньше общий !! Я думаю, что svcutil использует среду .NET 4.0. –

+0

Также, поскольку это разрешило мою проблему, я чувствую, что справедливо награждать награду –

+0

Спасибо! Я создал прокси-клиент как через VS, так и svcutil. В обоих случаях все методы генерируются парами ** MethodName/MethodNameAsync **, например, ** Join/JoinAsync **. Нет ** BeginJoin/EndJoin **. Таким образом, разница должна быть либо в вашей командной строке svcutil, либо в вашем файле конфигурации. – jsanalytics

 Смежные вопросы

  • Нет связанных вопросов^_^