Дуплексная связь между 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-это всегда приветствуется.