python 2.7和wcf之间的双工通信

时间:2018-01-29 06:02:08

标签: python-2.7 wcf

我是WCF的新手。我能够使用NetTcpBindings构建一个自托管的WCF服务和4个连接到它的.NET应用程序。现在我需要一个用Python2.7脚本编写的客户端连接到这个提供双工通信的WCF服务。

据我搜索,应使用 WsDualHttpBinding SOAP 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;
        }
    }
}

以下是服务主机应用

中的 App.config
<?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脚本中的内容(我使用suds-jurko 0.6hack将SOAP 1.2用作.NET wsDualHttpBinding only supports 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客户端已绑定到服务器并获取可用操作列表,但无法从这些操作中获取结果。它总是返回无

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

我尝试过除了肥皂水之外的其他几种方式,例如ZSIzeep,但始终将结果显示为''或' 0 ”。我在这些SOAP客户端进程上附加了记录器,并始终获得“ HTTP成功”或“ 202接受”。无法弄清楚自己在这里应该出现什么问题。

身体是否面临同样的问题?请给我一些线索来解决这个问题。

或者在Python2.7和WCF之间进行双工通信的任何其他想法总是受到赞赏。

0 个答案:

没有答案