2016-04-04 7 views
0

Ich habe die Chat-Anwendung mit Signalr Client und Chatsever als Klasse implementiert. Jetzt möchte ich Chat-Server als WCF-Dienst implementieren.Chat-Anwendung mit Signaler als WCF-Service

<link rel="stylesheet" href="Styles/jquery-ui.css" /> 
    <script src="Scripts/jquery-1.8.2.js"></script> 
    <script src="Scripts/jquery-ui.js"></script> 
    <script type="text/javascript" src="Scripts/jquery.dialogextend.1_0_1.js"></script> 
    <script type="text/javascript" src="Scripts/jquery.signalR.js"></script> 
    <script type="text/javascript" src="Scripts/jQuery.tmpl.js"></script> 
    <script type="text/javascript" src="signalr/hubs"></script> 
    <script id="new-online-contacts" type="text/x-jquery-tmpl"> 
     <div> 
     <ul> 
     {{each messageRecipients}} 
      <li id="chatLink${messageRecipientId}"><a href="javascript:;" onclick="javascript:SRChat.initiateChat('${messageRecipientId}','${messageRecipientName}');">${messageRecipientName}</a></li> 
     {{/each}} 
     </ul> 
     </div> 
    </script> 
    <script id="new-chatroom-template" type="text/x-jquery-tmpl"> 
    <div id="chatRoom${chatRoomId}" class="chatRoom"> 
     <ul id="messages${chatRoomId}" class="chatMessages"> 
     </ul> 
     <form id="sendmessage${chatRoomId}" action="#"> 
      <input type="text" id="newmessage${chatRoomId}" class="chatNewMessage"/> 
      <div class="clear"></div> 
      <input type="button" id="chatsend${chatRoomId}" value="Send" class="chatSend" OnClick="javascript:SRChat.sendChatMessage('${chatRoomId}')" /> 
      <input type="button" id="chatend${chatRoomId}" value="End Chat" class="chatSend" OnClick="javascript:SRChat.endChat('${chatRoomId}')" /> 
     </form> 
    </div> 
    </script> 
    <script id="new-chat-header" type="text/x-jquery-tmpl"> 
    <div id="chatRoomHeader${chatRoomId}"> 
     {{each messageRecipients}} 
      {{if $index == 0}} 
       ${messageRecipientName} 
      {{else}} 
       , ${messageRecipientName} 
      {{/if}} 
     {{/each}} 
    <div> 
    </script> 
    <script id="new-message-template" type="text/x-jquery-tmpl"> 
    <li class="message" id="m-${chatMessageId}"> 
     <strong>${displayPrefix}</strong> 
     {{html messageText}} 
    </li> 
    </script> 
    <script id="new-notify-message-template" type="text/x-jquery-tmpl"> 
    <li class="message" id="m-${chatMessageId}"> 
     <strong>{{html messageText}}</strong> 
    </li> 
    </script> 
    <script type="text/javascript"> 
    //<![CDATA[ 

     $(document).ready(function() { 

      SRChat.attachEvents(); 
     }); 

     SRChat = new function() { 
      var Username = GetParameterValues('Username'); 
      function GetParameterValues(param) { 
       var url = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); 
       for (var i = 0; i < url.length; i++) { 
        var urlparam = url[i].split('='); 
        if (urlparam[0] == param) { 
         return urlparam[1]; 
        } 
       } 
      } 
      var chatRooms = 0; 
      var numRand = Username; 
      var senderId = numRand; 
      var senderName = 'User :' + numRand; 

      var sRChatServer; 

      window.onbeforeunload = function() { 
       if (chatRooms > 0) 
        return "All chat instances will be ended!"; 
      }; 

      this.attachEvents = function() { 
       $("#userNameLabel").html(senderName); 
       if ($.connection != null) { 
        jQuery.support.cors = true; 
        $.connection.hub.url = 'signalr/hubs'; 
        sRChatServer = $.connection.sRChatServer; 

        $.connection.hub.start({ transport: 'auto' }, function() { 
         sRChatServer.server.connect(senderId, senderName).fail(function (e) { 
          alert(e); 
         }); 
        }); 

        sRChatServer.client.initiateChatUI = function (chatRoom) { 
         var chatRoomDiv = $('#chatRoom' + chatRoom.chatRoomId); 
         if (($(chatRoomDiv).length > 0)) { 
          var chatRoomText = $('#newmessage' + chatRoom.chatRoomId); 
          var chatRoomSend = $('#chatsend' + chatRoom.chatRoomId); 
          var chatRoomEndChat = $('#chatend' + chatRoom.chatRoomId); 

          chatRoomText.show(); 
          chatRoomSend.show(); 
          chatRoomEndChat.show(); 
         } 
         else { 
          var e = $('#new-chatroom-template').tmpl(chatRoom); 
          var c = $('#new-chat-header').tmpl(chatRoom); 

          chatRooms++; 

          //dialog options 
          var dialogOptions = { 
           "id": '#messages' + chatRoom.chatRoomId, 
           "title": c, 
           "width": 360, 
           "height": 365, 
           "modal": false, 
           "resizable": false, 
           "close": function() { javascript: SRChat.endChat('' + chatRoom.chatRoomId + ''); $(this).remove(); } 
          }; 

          // dialog-extend options 
          var dialogExtendOptions = { 
           "close": true, 
           "maximize": false, 
           "minimize": true, 
           "dblclick": 'minimize', 
           "titlebar": 'transparent' 
          }; 

          e.dialog(dialogOptions).dialogExtend(dialogExtendOptions); 

          $('#sendmessage' + chatRoom.chatRoomId).keypress(function (e) { 
           if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) { 
            $('#chatsend' + chatRoom.chatRoomId).click(); 
            return false; 
           } 
          }); 
         } 
        }; 

        sRChatServer.client.updateChatUI = function (chatRoom) { 
         var chatRoomHeader = $('#chatRoomHeader' + chatRoom.chatRoomId); 
         var c = $('#new-chat-header').tmpl(chatRoom); 
         chatRoomHeader.html(c); 
        }; 

        sRChatServer.client.receiveChatMessage = function (chatMessage, chatRoom) { 
         sRChatServer.client.initiateChatUI(chatRoom); 
         var chatRoom = $('#chatRoom' + chatMessage.conversationId); 
         var chatRoomMessages = $('#messages' + chatMessage.conversationId); 
         var e = $('#new-message-template').tmpl(chatMessage).appendTo(chatRoomMessages); 
         e[0].scrollIntoView(); 
         chatRoom.scrollIntoView(); 
        }; 

        sRChatServer.client.receiveLeftChatMessage = function (chatMessage) { 
         var chatRoom = $('#chatRoom' + chatMessage.conversationId); 
         var chatRoomMessages = $('#messages' + chatMessage.conversationId); 
         var e = $('#new-notify-message-template').tmpl(chatMessage).appendTo(chatRoomMessages); 
         e[0].scrollIntoView(); 
         chatRoom.scrollIntoView(); 
        }; 

        sRChatServer.client.receiveEndChatMessage = function (chatMessage) { 
         var chatRoom = $('#chatRoom' + chatMessage.conversationId); 
         var chatRoomMessages = $('#messages' + chatMessage.conversationId); 
         var chatRoomText = $('#newmessage' + chatMessage.conversationId); 
         var chatRoomSend = $('#chatsend' + chatMessage.conversationId); 
         var chatRoomEndChat = $('#chatend' + chatMessage.conversationId); 

         chatRooms--; 

         var e = $('#new-notify-message-template').tmpl(chatMessage).appendTo(chatRoomMessages); 

         chatRoomText.hide(); 
         chatRoomSend.hide(); 
         chatRoomEndChat.hide(); 

         e[0].scrollIntoView(); 
         chatRoom.scrollIntoView(); 
        }; 

        sRChatServer.client.onGetOnlineContacts = function (chatUsers) { 
         var e = $('#new-online-contacts').tmpl(chatUsers); 
         var chatLink = $('#chatLink' + senderId); 
         e.find("#chatLink" + senderId).remove(); 
         $("#chatOnlineContacts").html(""); 
         $("#chatOnlineContacts").html(e); 
        }; 
       } 
      }; 

      this.sendChatMessage = function (chatRoomId) { 
       var chatRoomNewMessage = $('#newmessage' + chatRoomId); 

       if (chatRoomNewMessage.val() == null || chatRoomNewMessage.val() == "") 
        return; 

       var chatMessage = { 
        senderId: senderId, 
        senderName: senderName, 
        conversationId: chatRoomId, 
        messageText: chatRoomNewMessage.val() 
       }; 

       chatRoomNewMessage.val(''); 
       chatRoomNewMessage.focus(); 
       sRChatServer.server.sendChatMessage(chatMessage).fail(function (e) { 
        alert(e); 
       }); 

       return false; 
      }; 

      this.endChat = function (chatRoomId) { 
       var chatRoomNewMessage = $('#newmessage' + chatRoomId); 

       var chatMessage = { 
        senderId: senderId, 
        senderName: senderName, 
        conversationId: chatRoomId, 
        messageText: chatRoomNewMessage.val() 
       }; 
       chatRoomNewMessage.val(''); 
       chatRoomNewMessage.focus(); 
       sRChatServer.server.endChat(chatMessage).fail(function (e) { 
        //alert(e); 
       }); 
      }; 

      this.initiateChat = function (toUserId, toUserName) { 
       if (sRChatServer == null) { 
        alert("Problem in connecting to Chat Server. Please Contact Administrator!"); 
        return; 
       } 
       sRChatServer.server.initiateChat(senderId, senderName, toUserId, toUserName).fail(function (e) { 
        alert(e); 
       }); 
      }; 

     }; 
    //]]> 
    </script> 
</head> 
<body> 
    <form id="form1" runat="server"> 

    <div> 

     <div id="userNameLabel"> 
     </div> 
     <br /> 
     <br /> 
     <div id="chatRooms"> 
     </div> 
     <div id="chatOnlineContacts"> 
     </div> 
    </div> 
    </form> 
</body> 

Mein Server-Side-Code ist

using System; 
using System.Collections.Concurrent; 
using System.Linq; 
using System.Threading.Tasks; 
using SignalR.Hubs; 

namespace SRChat 
{ 
    [HubName("sRChatServer")] 
    public class SRChatServer:Hub 

    { 
     #region Private Variables 
     private static readonly ConcurrentDictionary<string, MessageRecipient> _chatUsers = new ConcurrentDictionary<string, MessageRecipient>(StringComparer.OrdinalIgnoreCase); 
     private static readonly ConcurrentDictionary<string, ChatRoom> _chatRooms = new ConcurrentDictionary<string, ChatRoom>(StringComparer.OrdinalIgnoreCase); 
     #endregion 

     #region Public Methods 

     public bool Connect(string userId, string userName) 
     { 
      try 
      { 
       if (string.IsNullOrEmpty(userId) | string.IsNullOrEmpty(userName)) 
       { 
        return false; 
       } 
       if (GetChatUserByUserId(userId) == null) 
       { 
        AddUser(userId, userName); 
       } 
       else 
       { 
        ModifyUser(userId, userName); 
       } 
       SendOnlineContacts(); 
       return true; 
      } 
      catch (Exception ex) 
      { 
       throw new InvalidOperationException("Problem in connecting to chat server!"); 
      } 
     } 
     public override Task Disconnect() 
     { 
      try 
      { 
       DeleteUser(Context.ConnectionId); 
       return null; 
      } 
      catch (Exception ex) 
      { 
       throw new InvalidOperationException("Problem in disconnecting from chat server!"); 
      } 
     } 
     public bool InitiateChat(string fromUserId, string fromUserName, string toUserId, string toUserName) 
     { 
      try 
      { 
       if (string.IsNullOrEmpty(fromUserId) || string.IsNullOrEmpty(fromUserName) || string.IsNullOrEmpty(toUserId) || string.IsNullOrEmpty(toUserName)) 
       { 
        return false; 
       } 

       var fromUser = GetChatUserByUserId(fromUserId); 
       var toUser = GetChatUserByUserId(toUserId); 

       if (fromUser != null && toUser != null) 
       { 
        if (!CheckIfRoomExists(fromUser, toUser)) 
        { 
         //Create New Chat Room 
         ChatRoom chatRoom = new ChatRoom(); 
         chatRoom.chatRoomInitiatedBy = fromUser.messageRecipientId; 
         chatRoom.chatRoomInitiatedTo = toUser.messageRecipientId; 

         chatRoom.messageRecipients.Add(fromUser); 
         chatRoom.messageRecipients.Add(toUser); 

         //create and save blank message to get new conversation id 
         ChatMessage chatMessage = new ChatMessage(); 
         chatMessage.messageText = "Chat Initiated"; 
         chatMessage.senderId = fromUser.messageRecipientId; 
         chatMessage.senderName = fromUser.messageRecipientName; 

         fromUser.chatRoomIds.Add(chatRoom.chatRoomId); 
         toUser.chatRoomIds.Add(chatRoom.chatRoomId); 

         //Create SignalR Group for this chat room and add users connection to it 
         Groups.Add(fromUser.connectionId, chatRoom.chatRoomId); 
         Groups.Add(toUser.connectionId, chatRoom.chatRoomId); 

         //Add Chat room object to collection 
         if (_chatRooms.TryAdd(chatRoom.chatRoomId, chatRoom)) 
         { 
          //Generate Client UI for this room 
          Clients[fromUser.connectionId].initiateChatUI(chatRoom); 
         } 
        } 
       } 
       return true; 
      } 
      catch (Exception ex) 
      { 
       throw new InvalidOperationException("Problem in starting chat!"); 
      } 
     } 
     public bool EndChat(ChatMessage chatMessage) 
     { 
      try 
      { 
       ChatRoom chatRoom; 
       if (_chatRooms.TryGetValue(chatMessage.conversationId, out chatRoom)) 
       { 
        if (_chatRooms[chatRoom.chatRoomId].chatRoomInitiatedBy == chatMessage.senderId) 
        { 
         chatMessage.messageText = string.Format("{0} left the chat. Chat Ended!", chatMessage.senderName); 
         if (_chatRooms.TryRemove(chatRoom.chatRoomId, out chatRoom)) 
         { 
          Clients[chatRoom.chatRoomId].receiveEndChatMessage(chatMessage); 
          foreach (MessageRecipient messageReceipient in chatRoom.messageRecipients) 
          { 
           if (messageReceipient.chatRoomIds.Contains(chatRoom.chatRoomId)) 
           { 
            messageReceipient.chatRoomIds.Remove(chatRoom.chatRoomId); 
            Groups.Remove(messageReceipient.connectionId, chatRoom.chatRoomId); 
           } 
          } 
         } 
        } 
        else 
        { 
         MessageRecipient messageRecipient = GetChatUserByUserId(chatMessage.senderId); 
         if (messageRecipient != null && messageRecipient.chatRoomIds.Contains(chatRoom.chatRoomId)) 
         { 
          chatRoom.messageRecipients.Remove(messageRecipient); 
          messageRecipient.chatRoomIds.Remove(chatRoom.chatRoomId); 
          if (chatRoom.messageRecipients.Count < 2) 
          { 
           chatMessage.messageText = string.Format("{0} left the chat. Chat Ended!", chatMessage.senderName); 
           if (_chatRooms.TryRemove(chatRoom.chatRoomId, out chatRoom)) 
           { 
            Clients[chatRoom.chatRoomId].receiveEndChatMessage(chatMessage); 
            foreach (MessageRecipient messageReceipient in chatRoom.messageRecipients) 
            { 
             if (messageReceipient.chatRoomIds.Contains(chatRoom.chatRoomId)) 
             { 
              messageReceipient.chatRoomIds.Remove(chatRoom.chatRoomId); 
              Groups.Remove(messageReceipient.connectionId, chatRoom.chatRoomId); 
             } 
            } 
           } 
          } 
          else 
          { 
           chatMessage.messageText = string.Format("{0} left the chat.", chatMessage.senderName); 
           Groups.Remove(messageRecipient.connectionId, chatRoom.chatRoomId); 
           Clients[messageRecipient.connectionId].receiveEndChatMessage(chatMessage); 
           Clients[chatRoom.chatRoomId].receiveLeftChatMessage(chatMessage); 
           Clients[chatRoom.chatRoomId].updateChatUI(chatRoom); 
          } 
         } 
        } 
       } 
       else 
       { 
        throw new InvalidOperationException("Problem in ending chat!"); 
       } 
       return true; 
      } 
      catch (Exception ex) 
      { 
       throw new InvalidOperationException("Problem in ending chat!"); 
      } 
     } 
     public bool SendChatMessage(ChatMessage chatMessage) 
     { 
      try 
      { 
       ChatRoom chatRoom; 
       if (_chatRooms.TryGetValue(chatMessage.conversationId, out chatRoom)) 
       { 
        chatMessage.chatMessageId = Guid.NewGuid().ToString(); 
        chatMessage.timestamp = DateTime.Now; 
        Clients[chatMessage.conversationId].receiveChatMessage(chatMessage, chatRoom); 
        return true; 
       } 
       else 
       { 
        throw new InvalidOperationException("Problem in sending message!"); 
       } 
      } 
      catch (Exception ex) 
      { 
       throw new InvalidOperationException("Problem in sending message!"); 
      } 
     } 
     private bool SendOnlineContacts() 
     { 
      try 
      { 
       OnlineContacts onlineContacts = new OnlineContacts(); 
       foreach (var item in _chatUsers) 
       { 
        onlineContacts.messageRecipients.Add(item.Value); 
       } 
       Clients.onGetOnlineContacts(onlineContacts); 
       return false; 
      } 
      catch (Exception ex) 
      { 
       throw new InvalidOperationException("Problem in getting contacts!"); 
      } 
     } 

     #endregion 

     #region Private Methods 

     private Boolean CheckIfRoomExists(MessageRecipient fromUser, MessageRecipient toUser) 
     { 
      foreach (string chatRoomId in fromUser.chatRoomIds) 
      { 
       Int32 count = (from mr in _chatRooms[chatRoomId].messageRecipients 
           where mr.messageRecipientId == toUser.messageRecipientId 
           select mr).Count(); 
       if (count > 0) 
       { 
        return true; 
       } 
      } 
      foreach (string chatRoomId in toUser.chatRoomIds) 
      { 
       Int32 count = (from mr in _chatRooms[chatRoomId].messageRecipients 
           where mr.messageRecipientId == fromUser.messageRecipientId 
           select mr).Count(); 
       if (count > 0) 
       { 
        return true; 
       } 
      } 
      return false; 
     } 
     private MessageRecipient AddUser(string userId, string userName) 
     { 
      var user = new MessageRecipient(); 
      user.messageRecipientId = userId; 
      user.messageRecipientName = userName; 
      user.connectionId = Context.ConnectionId; 
      _chatUsers[userId] = user; 
      return user; 
     } 
     private MessageRecipient ModifyUser(string userId, string userName) 
     { 
      var user = GetChatUserByUserId(userId); 
      user.messageRecipientName = userName; 
      user.connectionId = Context.ConnectionId; 
      _chatUsers[userId] = user; 
      return user; 
     } 
     private Boolean DeleteUser(string userId, string userName) 
     { 
      var user = GetChatUserByUserId(userId); 
      if (user != null && _chatUsers.ContainsKey(user.messageRecipientId)) 
      { 
       MessageRecipient messageRecipient; 
       return _chatUsers.TryRemove(user.messageRecipientId, out messageRecipient); 
      } 
      return false; 
     } 
     private Boolean DeleteUser(string connectionId) 
     { 
      var returnValue = false; 
      var user = GetChatUserByConnectionId(connectionId); 
      if (user != null && _chatUsers.ContainsKey(user.messageRecipientId)) 
      { 
       MessageRecipient messageRecipient; 
       returnValue = _chatUsers.TryRemove(user.messageRecipientId, out messageRecipient); 

       //remoave from all groups and chatrooms 
       foreach (string chatRoomId in messageRecipient.chatRoomIds) 
       { 
        _chatRooms[chatRoomId].messageRecipients.Remove(messageRecipient); 

        Groups.Remove(messageRecipient.connectionId, chatRoomId); 

        //notify user left chat 
        ChatMessage chatMessage = new ChatMessage(); 
        chatMessage.conversationId = chatRoomId; 
        chatMessage.senderId = messageRecipient.messageRecipientId; 
        chatMessage.senderName = messageRecipient.messageRecipientName; 
        if (_chatRooms[chatRoomId].chatRoomInitiatedBy == messageRecipient.messageRecipientId) 
        { 
         chatMessage.messageText = string.Format("{0} left the chat. Chat Ended!", messageRecipient.messageRecipientName); 
         ChatRoom chatRoom; 

         if (_chatRooms.TryRemove(chatRoomId, out chatRoom)) 
         { 
          foreach (MessageRecipient messageReceipient in chatRoom.messageRecipients) 
          { 
           if (messageReceipient.chatRoomIds.Contains(chatRoomId)) 
           { 
            messageReceipient.chatRoomIds.Remove(chatRoomId); 
           } 
          } 
          Clients[chatRoomId].receiveEndChatMessage(chatMessage); 
         } 
        } 
        else 
        { 
         if (_chatRooms[chatRoomId].messageRecipients.Count() < 2) 
         { 
          chatMessage.messageText = string.Format("{0} left the chat. Chat Ended!", messageRecipient.messageRecipientName); 
          ChatRoom chatRoom; 
          if (_chatRooms.TryRemove(chatRoomId, out chatRoom)) 
          { 
           foreach (MessageRecipient messageReceipient in chatRoom.messageRecipients) 
           { 
            if (messageReceipient.chatRoomIds.Contains(chatRoomId)) 
            { 
             messageReceipient.chatRoomIds.Remove(chatRoomId); 
            } 
           } 
           Clients[chatRoomId].receiveEndChatMessage(chatMessage); 
          } 
         } 
         else 
         { 
          chatMessage.messageText = string.Format("{0} left the chat.", messageRecipient.messageRecipientName); 
          Clients[chatRoomId].receiveLeftChatMessage(chatMessage); 
         } 
        } 
       } 
      } 
      return returnValue; 
     } 
     private MessageRecipient GetChatUserByUserId(string userId) 
     { 
      return _chatUsers.Values.FirstOrDefault(u => u.messageRecipientId == userId); 
     } 
     private MessageRecipient GetChatUserByConnectionId(string connectionId) 
     { 
      return _chatUsers.Values.FirstOrDefault(u => u.connectionId == connectionId); 
     } 

     #endregion 
    } 
} 

ich dieses als Wcf-Dienst oder Web-Service implementieren möchten. Bitte helfen Sie mir im Voraus

+0

Was versuchen Sie zu erreichen? Sie möchten Hub in einer WCF-Konsole hosten? –

+0

Hallo @Quentin Roger, ich versuche, als Web-WCF-Service keine Konsole zu implementieren. –

+0

Ein Web-WCF-Dienst kann im IIS/Managed Service oder in der verwalteten App gehostet werden. Welchen Weg werden Sie benutzen, um Ihren Wcf zu hosten? –

Antwort

0

Ich denke, der beste Weg, um das zu erreichen, ist einen Windows Managed Service zu erstellen. (Weil Sie die Lebensdauer Ihres Dienstes nicht steuern können, wenn in IIS mit einer pro Anrufkonfiguration gehostet).

So sollten Sie einen neuen Windows-Dienst erstellt und gehostet sowohl Ihre WCF-Dienst und signalr (es ist nur eine Idee, aber ich denke, der Code kann so aussieht):

public class HostWindowService : ServiceBase 
{ 
    public ServiceHost serviceHost = null; 
    public HostWindowService() 
    {  
     ServiceName = "WCFWindowsServiceSample"; 
    } 

    public static void Main() 
    { 
     ServiceBase.Run(new HostWindowService()); 
    } 

    protected override void OnStart(string[] args) 
    { 
     //host wcf service 
     if (serviceHost != null) 
     { 
      serviceHost.Close(); 
     }     
     serviceHost = new ServiceHost(typeof(WCFService));  
     serviceHost.Open(); 

     //host signalr 
     Task.Run(() => SignalRHost());     
    } 

    private void SignalRHost() 
    { 
     try 
     { 
      SignalR = WebApp.Start("http://localhost:8080"); 
     } 
     catch (TargetInvocationException) 
     { 
      WriteToConsole("A server is already running at " + "http://localhost:8080");   
      return; 
     }  
    } 

    class Startup 
    { 
     public void Configuration(IAppBuilder app) 
     { 
      app.UseCors(CorsOptions.AllowAll); 
      app.MapSignalR(); 
     } 
    }  

    protected override void OnStop() 
    { 
     if (serviceHost != null) 
     { 
      serviceHost.Close(); 
      serviceHost = null; 
     } 
    } 
} 

Referenzen: How to: Host a WCF Service in a Managed Windows Service und Self-Hosting SignalR in a Windows Service

+0

hi @Quentin Roger, Meine Anforderung ist die Entwicklung eines Windows-und Web-Anwendungen sind signall Clients und die Synchronisation zwischen diesen Clients wird von Signal-Server verwaltet, d. H. Als Wcf-Dienst implementiert, d. H. Möglich durch diese wyu empfohlen für mich.plz mir helfen. –

+0

hi @Quentin Roger, bitte hilf mir, es ist möglich? –

+0

hi @Quentin Roger, bitte helft mir ich arbeite daran –