WCF learning Summary 4-message broadcasting with duplex

Source: Internet
Author: User

In WCF, three message exchange modes are defined: 1. Request/reply; 2. One-way; 3. duplex.
Request/ReplyIs the default mode, that is, synchronous call. After calling a service method, you need to wait for the Service Message to return, even if the method returns the void type.
One-wayThis method will be returned immediately after the method is called. Note that one-way cannot be used in a non-void or a method that contains the out/Ref parameter, leading to an invalidoperationexception.
DuplexAlso known as Duplex Communication, the implementation is a little more complex than the first two. (1) Specify the callback type in servicecontract; (2) specify [operationcontract (isoneway = true)] for callback operations; (3) Use operationcontext in the service contract. current. getcallbackchannel to obtain the client callback instance.

In addition, wsdualhttpbinding and nettcpbinding provide support for duplex communication in the predefined WCF binding type. However, there are essential differences between the two in the implementation mechanism of duplex communication. Wsdualhttpbinding is based on the HTTP transmission protocol, while the HTTP protocol itself is based on the request-reply transmission protocol, and the HTTP-based channel is essentially one-way. Wsdualhttpbinding actually creates two channels, one for communications between the client and the server, and the other for communications between the server and the client, indirectly providing duplex communication. Nettcpbinding is fully based on TCP protocol that supports duplex communication.

Next, we will introduce how to use the WCF duplex message exchange to broadcast the server to the client.

1. Define a service contract (create a WCF Service Library Project: wcfduplexmessageservice)
Using system. servicemodel; <br/> namespace wcfduplexmessageservice <br/> {<br/> [servicecontract (callbackcontract = typeof (iclient)] <br/> Public interface imessageservice <br/> {<br/> [operationcontract] <br/> void registerclient (); <br/>}< br/> Public interface iclient <br/>{< br/> [operationcontract (isoneway = true)] <br/> void sendmessage (string message ); <br/>}< br/>}
(1) The defined iclient is used for client callback.
(2) The defined registerclient () is used to register the client callback instance to the server.

2. Implementation Service (engineering wcfduplexmessageservice)
(1) to register all clients to a service object, define the server as the singleton instance mode:
Instancecontextmode = instancecontextmode. Single (Singleton instances are instantiated when the service host is started)
(2) A static list <iclient> is defined to save the client callback instance in a unified manner and make it public as property, so that serverui can be accessed easily.
(3) Listening to the channel. closing event to prevent exceptions on the server due to client shutdown during Broadcast
When the client is closed (the channel is closed), this event is triggered, and the client callback instance is removed from the event processing.
Using system; <br/> using system. collections. generic; <br/> using system. servicemodel; <br/> namespace wcfduplexmessageservice <br/>{< br/> [servicebehavior (instancecontextmode = instancecontextmode. single)] <br/> public class messageservice: imessageservice, idisposable <br/>{< br/> Public static list <iclient> clientcallbacklist {Get; set ;} <br/> Public messageservice () <br/>{< br/> clientcallbacklist = new list <iclient> (); <br/>}< br/> Public void registerclient () <br/>{< br/> var client = operationcontext. current. getcallbackchannel <iclient> (); <br/> var id = operationcontext. current. sessionid; <br/> console. writeline ("{0} registered. ", ID); <br/> operationcontext. current. channel. closing + = new eventhandler (channel_closing); <br/> clientcallbacklist. add (client); <br/>}< br/> void channel_closing (Object sender, eventargs e) <br/>{< br/> lock (clientcallbacklist) <br/>{< br/> clientcallbacklist. remove (iclient) sender); <br/>}< br/> Public void dispose () <br/>{< br/> clientcallbacklist. clear (); <br/>}< br/>}

3. server host and UI implementation

BroadcastWhen the button is pressed, wcfduplexmessageservice. messageservice is traversed.ClientcallbacklistCallback.
Using system; <br/> using system. collections. generic; <br/> using system. componentmodel; <br/> using system. windows. forms; <br/> using system. servicemodel; <br/> namespace wcfduplexmessagesvchost <br/>{< br/> Public partial class form1: Form <br/>{< br/> Public form1 () <br/>{< br/> initializecomponent (); <br/>}< br/> private servicehost _ host = NULL; <br/> private void form1_load (Object sender, even Targs e) <br/>{< br/> _ host = new servicehost (typeof (wcfduplexmessageservice. messageservice); <br/> _ host. open (); <br/> This. label1.text = "messageservice opened. "; <br/>}< br/> private void form=formclosing (Object sender, formclosingeventargs e) <br/>{< br/> If (_ host! = NULL) <br/>{< br/> _ host. close (); <br/> idisposable host = _ host as idisposable; <br/> host. dispose (); <br/>}< br/> private void button#click (Object sender, eventargs E) <br/>{< br/> var list = wcfduplexmessageservice. messageservice. clientcallbacklist; <br/> If (list = NULL | list. count = 0) <br/> return; <br/> lock (list) <br/>{< br/> foreach (VAR client in List) <br/> {<br/> // broadcast <br/> client. sendmessage (this. textbox1.text); <br/>}< br/>}
Configuration:
In order for the client to generate a proxy directly through the public metadata, add the following in the configuration file:
<Endpoint address = "mex" binding ="Mexico httpbinding"Contract ="Imetadataexchange"/>
Because the metadata exposed service (imetadataexchange) uses mexhttpbinding and duplex uses nettcpbinding, You need to append the baseaddress: http: // localhost: 9998/wcfduplexmessageservice
Or modify the binding method of the metadata publishing service: changeMextcpbinding

<? XML version = "1.0"?> <Br/> <configuration> <br/> <system. web> <br/> <compilation DEBUG = "true"/> <br/> </system. web> <br/> <system. servicemodel> <br/> <services> <br/> <service name = "wcfduplexmessageservice. messageservice "> <br/> <endpoint address =" "binding =" nettcpbinding "bindingconfiguration =" "Contract =" wcfduplexmessageservice. imessageservice "> <br/> <identity> <br/> <DNS value =" localhost "/> <br/> </identity> <br/> </Endpoint> <br/> <endpoint address = "mex" binding = "mexhttpbinding" Contract = "imetadataexchange"/> <br/> <post> <br/> <baseaddresses> <br/> <add baseaddress = "net. TCP: // localhost: 9999/wcfduplexmessageservice/"/> <br/> <add baseaddress =" http: // localhost: 9998/wcfduplexmessageservice "/> <br/> </baseaddresses> <br/> </post> <br/> </service> <br/> </services> <br /> <behaviors> <br/> <servicebehaviors> <br/> <behavior> <br/> <servicemetadata httpgetenabled = "true"/> <br/> <servicedebug includeexceptiondetailinfaults = "false"/> <br/> </behavior> <br/> </servicebehaviors> <br/> </behaviors> <br/> </system. servicemodel> <br/> <startup> <supportedruntime version = "v4.0" SKU = ". netframework, version = v4.0 "/> </startup> </configuration>

4. Client implementation
(1) generate a client proxy through add service reference

(2) Implement wcfsvc. imessageservicecallback (client. CS)
Using system; <br/> namespace wcfduplexmessageclient <br/>{< br/> public class client: wcfsvc. imessageservicecallback <br/>{< br/> Public void sendmessage (string message) <br/>{< br/> console. writeline ("[clienttime {0: hhmmss}] service broadcast: {1}", datetime. now, message); <br/>}< br/>}
(3) Start the client and call wcfsvc. messageserviceclient to register the client instance to the service.
Using system; <br/> using system. servicemodel; <br/> namespace wcfduplexmessageclient <br/>{< br/> class Program <br/>{< br/> static void main (string [] ARGs) <br/>{< br/> var client = new client (); <br/> var CTX = new instancecontext (client); <br/> var SVC = new wcfsvc. messageserviceclient (CTX); <br/> SVC. registerclient (); <br/> console. read (); <br/>}< br/>}
OK, run:

Supplement:
1. If the isoneway attribute of the callback contract is removed, the server will cause invalidoperationexception. About duplex message exchange customization can also look at this blog: http://www.cnblogs.com/xinhaijulan/archive/2011/01/09/1931272.html
2. When IIS 5.x of XP uses wsduplexbinding, the listener address of the callback service is 80 by default, and 80 is the listener port exclusively occupied by IIS. The addressalreadyinuseexception exception occurs. To solve this problem, you need to modify the callback service listening address: clientbaseaddress of wsduplexbinding.

Links to this series:

WCF learning summary 1-simple example

WCF learning Summary 2 -- configure WCF

WCF learning Summary 3-instance mode

WCF Study Summary 4-message broadcasting with duplex

WCF Study Summary 5-user name verification for message interception

WCF learning summary 6 -- WCF parameters and return values

WCF study summary 7-stream mode for File Upload

WCF learning Summary 8 -- WCF Transaction Processing

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.