Việt Anh Đinh Ответов: 0

Дуплексная связь между Python 2.7 и WCF


Всем привет,

Я новичок в WCF. Я могу создать автономный сервис WCF и 4 .Сетевые приложения, подключенные к нему с помощью NetTcpBindings. Теперь мне нужен еще один клиент, написанный в скрипте Python2.7, чтобы подключиться к этому сервису WCF, обеспечивающему дуплексную связь.

Что я уже пробовал:

Насколько я погуглил, Элементов wsdualhttpbinding с Мыло 1.2 должны использовать.

Вот мой сервисный интерфейс

namespace GPH_QuickMessageServiceLib
    {
        /// <summary>
        /// GPH Quick Message Service Operations
        /// </summary>
        [ServiceContract(
            Name = "GPH_QuickMessageService",
            Namespace = "GPH_QuickMessageServiceLib",
            SessionMode = SessionMode.Required,
            CallbackContract = typeof(IMessageServiceCallback))]

        public interface IMessageServiceInbound
        {
            [OperationContract]
            [WebInvoke]
            int JoinTheConversation(string userName);
            [OperationContract]
            [WebInvoke]
            int LeaveTheConversation(string userName);
        }

        public interface IMessageServiceCallback
        {
            [OperationContract(IsOneWay = true)]
            [WebInvoke]
            void NotifyUserJoinedTheConversation(string userName, List<string> SubscriberList);
            [OperationContract(IsOneWay = true)]
            [WebInvoke]
            void NotifyUserLeftTheConversation(string userName, List<string> SubscriberList);
        }
    }

Вот мой поведение служб

namespace GPH_QuickMessageServiceLib
    {
        /// <summary>
        /// GPH Quick Message Service behaviour
        /// </summary>
        [ServiceBehavior(
            ConcurrencyMode = ConcurrencyMode.Single,
            InstanceContextMode = InstanceContextMode.PerCall)]

        public class GPH_QuickMessageService : IMessageServiceInbound
        {
            private static List<IMessageServiceCallback> _callbackList = new List<IMessageServiceCallback>();
            //  number of current users - 0 to begin with
            private static int _registeredUsers = 0;
            private static List<string> SubscriberList = new List<string>();
            private static Dictionary<string, IMessageServiceCallback> NotifyList = new Dictionary<string, IMessageServiceCallback>();  // Default Constructor

            // Default Constructor
            public GPH_QuickMessageService() { }
    
            public int JoinTheConversation(string userName)
            {
                // Subscribe the user to the conversation
                IMessageServiceCallback registeredUser = OperationContext.Current.GetCallbackChannel<IMessageServiceCallback>();
    
                if (!_callbackList.Contains(registeredUser))
                {
                    _callbackList.Add(registeredUser);
                    SubscriberList.Add(userName);//Note the callback list is just a list of channels.
                    NotifyList.Add(userName, registeredUser);//Bind the username to the callback channel ID
                }
    
                _callbackList.ForEach(
                    delegate (IMessageServiceCallback callback)
                    {
                        callback.NotifyUserJoinedTheConversation(userName, SubscriberList);
                        _registeredUsers++;
                    });
    
                return _registeredUsers;
            }
    
            public int LeaveTheConversation(string userName)
            {
                // Unsubscribe the user from the conversation.      
                IMessageServiceCallback registeredUser = OperationContext.Current.GetCallbackChannel<IMessageServiceCallback>();
    
                if (_callbackList.Contains(registeredUser))
                {
                    _callbackList.Remove(registeredUser);
                    NotifyList.Remove(userName);
                    SubscriberList.Remove(userName);
                    _registeredUsers--;
                }
    
                // Notify everyone that user has arrived.
                // Use an anonymous delegate and generics to do our dirty work.
                _callbackList.ForEach(
                    delegate (IMessageServiceCallback callback)
                    {
                        callback.NotifyUserLeftTheConversation(userName, SubscriberList);
                    });
    
                return _registeredUsers;
            }
        }
    }


Вот мой Приложение.конфиг в сервис-ведущее приложение

<?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
      </startup>
      <system.serviceModel>
        <services>
          <service name="GPH_QuickMessageServiceLib.GPH_QuickMessageService"

            behaviorConfiguration = "QuickMessageServiceMEXBehavior">
            <endpoint address ="soap"

                      binding="wsDualHttpBinding"

                      contract="GPH_QuickMessageServiceLib.IMessageServiceInbound" />
            <endpoint address ="service"

                      binding="netTcpBinding"

                      contract="GPH_QuickMessageServiceLib.IMessageServiceInbound" />
            <!-- Enable the MEX endpoint -->
            <endpoint address="mex"

                      binding="mexTcpBinding"

                      contract="IMetadataExchange" />
    
            <!-- Need to add this so MEX knows the address of our service -->
            <host>
              <baseAddresses>
                <add baseAddress="http://localhost:2709/GPH_QuickMessageService/soap"/>
                <add baseAddress="net.tcp://localhost:8868/GPH_QuickMessageService"/>
              </baseAddresses>
            </host>
    
          </service>
        </services>
        <!-- A behavior definition for MEX -->
        <behaviors>
          <serviceBehaviors>
            <behavior name="QuickMessageServiceMEXBehavior" >
              <serviceMetadata httpGetEnabled="true" />
            </behavior>
          </serviceBehaviors>
        </behaviors>
      </system.serviceModel>
    </configuration>


А вот что у меня есть в скрипте Python2.7 (я использую пена-Юрко 0,6 с собой рубить чтобы использовать SOAP 1.2 в качестве .NET wsDualHttpBinding поддерживает только SOAP 1.2)

from suds.client import Client
    from suds.bindings import binding
    import logging
    
    # Just for debugging purposes.
    logging.basicConfig(level=logging.INFO)
    logging.getLogger('suds.client').setLevel(logging.DEBUG)
    
    # Telnic's SOAP server expects a SOAP 1.2 envelope, not a SOAP 1.1 envelope
    # and will complain if this hack isn't done.
    binding.envns = ('SOAP-ENV', 'http://www.w3.org/2003/05/soap-envelope')
    client = Client('http://localhost:2709/GPH_QuickMessageService/soap?wsdl',
        headers={'Content-Type': 'application/soap+xml'})
    
    # This will now work just fine.
    result = client.service.JoinTheConversation('RIDE')
    
    print client
    print 'result = %s' % result


Как я предполагаю, мой клиент python уже привязан к серверу и получает список доступных операций, но он не может получить результат от этих операций. Он всегда возвращает None

C:\Python27\python.exe C:/Users/sev_user/PycharmProjects/WcfInteration/venv/Scripts/suds_client.py
    DEBUG:suds.client:sending to (http://localhost:2709/GPH_QuickMessageService/soap/soap)
    message:
    <?xml version="1.0" encoding="UTF-8"?>
    <SOAP-ENV:Envelope xmlns:ns0="GPH_QuickMessageServiceLib" xmlns:ns1="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope">
       <SOAP-ENV:Header/>
       <ns1:Body>
          <ns0:JoinTheConversation>
             <ns0:userName>RIDE</ns0:userName>
          </ns0:JoinTheConversation>
       </ns1:Body>
    </SOAP-ENV:Envelope>
    DEBUG:suds.client:headers = {'SOAPAction': '"GPH_QuickMessageServiceLib/GPH_QuickMessageService/JoinTheConversation"', 'Content-Type': 'application/soap+xml'}
    
    Suds ( https://fedorahosted.org/suds/ )  version: 0.6
    
    Service ( GPH_QuickMessageService ) tns="http://tempuri.org/"
       Prefixes (3)
          ns0 = "GPH_QuickMessageServiceLib"
          ns1 = "http://schemas.microsoft.com/2003/10/Serialization/"
          ns2 = "http://schemas.microsoft.com/2003/10/Serialization/Arrays"
       Ports (2):
          (WSDualHttpBinding_GPH_QuickMessageService)
             Methods (7):
                JoinTheConversation(xs:string userName)
                LeaveTheConversation(xs:string userName)
                NotifyUserJoinedTheConversation()
                NotifyUserLeftTheConversation()
                NotifyUserOfMessage()
                ReceiveMessage(xs:string userName, ns2:ArrayOfstring addressList, xs:string userMessage)
                sum(xs:int a, xs:int b)
             Types (4):
                ns2:ArrayOfstring
                ns1:char
                ns1:duration
                ns1:guid
          (NetTcpBinding_GPH_QuickMessageService)
             Methods (7):
                JoinTheConversation(xs:string userName)
                LeaveTheConversation(xs:string userName)
                NotifyUserJoinedTheConversation()
                NotifyUserLeftTheConversation()
                NotifyUserOfMessage()
                ReceiveMessage(xs:string userName, ns2:ArrayOfstring addressList, xs:string userMessage)
                sum(xs:int a, xs:int b)
             Types (4):
                ns2:ArrayOfstring
                ns1:char
                ns1:duration
                ns1:guid
    
    
    result = None
    DEBUG:suds.client:HTTP succeeded:
    
    
    Process finished with exit code 0


Я пробовал несколько способов, отличных от пены, таких как ЗСИ, зип, но всегда получаю результат как 'Никто' или '0'. Я прикрепил регистратор на эти SOAP-клиентские процессы и всегда получаю либо то, либо другое 'HTTP преуспевает' или '202 принято- Я и сам не мог понять, что здесь не так.

Сталкивался ли кто-нибудь с такой же проблемой? Пожалуйста, дайте мне какую-нибудь подсказку, чтобы решить эту проблему.

Или любая другая идея, чтобы получить дуплексную связь между вместо python2.7 и WCF-это всегда приветствуется.

0 Ответов