Introduction to WCF TCP Duplex mode

Source: Internet
Author: User
Tags foreach datetime http request serialization unique id

In a service-oriented distributed environment, a standard platform-independent communication protocol is used to enable each service to interact with each other through a SOAP message. This process of interaction is actually the process of exchanging information. WCF supports different forms of information interchange, which we call the information Exchange Mode (Message Exchange pattern (MEP), below), and Common MEP includes: request/reply, one-way mode and duplex mode. By adopting a duplex MEP, we can implement the operation of invoking the client on the server side. Although WCF provides us with the low-level communication details, it allows us to shift our energies to the implementation of the business logic, which is unrelated to the communication protocol, but the understanding of the communication protocol can help us choose a suitable communication protocol according to the specific environment. When it comes to communication protocols, WCF often uses the following 4: Http,tcp,named pipe,msmq.

We used the example in the previous article (WCF Learning Tour-http Duplex mode (20)) to modify it to become a WCF service application for TCP two-way communication. Directly below the code.


1. Contract

Using Contracts;
Using System;
Using System.Collections.Generic;
Using System.Linq;
Using System.Runtime.Serialization;
Using System.ServiceModel;
Using System.Text;

Namespace Contracts
{

Note: Using the rename command on the refactoring menu, you can change the interface name "Ibookservice" in both the code and the configuration file.
[ServiceContract (callbackcontract = typeof (Icallback))]
public interface Ibookservice
{

      ///<summary>
      ///Request and reply mode, Default mode
      ///</summary>
      ///< param name= "Id" > Book id</param>
      ///<returns></returns>
        [OperationContract]
         String GetBook (string Id);
       ///<summary>

Single work mode, display name
</summary>
<param name= "name" > Book name </param>
[OperationContract (IsOneWay = True)]
void ShowName (string name);
<summary>
Duplex mode, display name
</summary>
<param name= "name" > Book name </param>
[OperationContract (IsOneWay = True)]
void DisplayName (string name);

}

}

Using System;
Using System.Collections.Generic;
Using System.Linq;
Using System.Runtime.Serialization;
Using System.ServiceModel;
Using System.Text;

Namespace Contracts
{

public interface Icallback
{

[OperationContract (IsOneWay = True)]
void Displayresult (string result);

}
}
2. Wcfservicelib

Using Contracts;
Using System;
Using System.Collections.Generic;
Using System.Linq;
Using System.Runtime.Serialization;
Using System.ServiceModel;
Using System.Text;

Namespace Wcfservicelib
{

Note: Use the rename command on the refactoring menu to change the class name "Bookservice" in the Code, SVC, and configuration files at the same time.

Note: To start the WCF test client to test the service, select Bookservice.svc or BookService.svc.cs in Solution Explorer and start debugging.
public class Bookservice:ibookservice
{

<summary>
Request and reply mode, default mode
</summary>
<param name= "Id" > Book id</param>
<returns></returns>
public string GetBook (string Id)
{

System.Threading.Thread.Sleep (20000);
int bookid = Convert.ToInt32 (Id);
Books book = Setbook (BookID);
string xml = xmlhelper.toxml<books> (book);
return XML;

}

Public books Setbook (int Id)
{

            books = new books ();
            Book. BookID = Id;
            Book. Authorid = 1;
            Book. Category = "IBM";
            Book. Price = 39.99M;
            Book. NumberOfCopies = 25;
            Book. Name = "DB2 database Performance Tuning and optimization";
            Book. Publishdate = new DateTime (2015, 2, 23);
            return book;
       }

<summary>
Single work mode, display name
</summary>
<param name= "name" > Name </param>
public void ShowName (string name)
{

string result = String. Format ("book name: {0}, date time {1}", Name, DateTime.Now.ToString ("Yyyy-mm-dd HH:mm:ss"));
Console.WriteLine ("\ r \ n" + result);

}

       ///<summary>
       / Duplex mode, callback display results
       ///</summary>
        ///<param name= "name" > name </param>
        public void DisplayName (string name)
        {
             string result=string. Format ("book name: {0}, date time {1}", Name, DateTime.Now.ToString ("Yyyy-mm-dd HH:mm:ss"));
            Console.WriteLine ("\ r \ n" + result);
            Icallback call = Operationcontext.current.getcallbackchannel<icallback> ();
            call. Displayresult ("Callback Client---" +result);

}

}

}
On the server side, the Callbackcontext instance specified by the client is obtained by OperationContext.Current.GetCallbackChannel to invoke the operation of the client.

3. Hosting:

Host configuration file:

<?xml version= "1.0" encoding= "Utf-8"?>
<configuration>
<startup>
<supportedruntime version= "v4.0" sku= ". netframework,version=v4.5.2 "/>

</startup>
<system.serviceModel>
<diagnostics>
<messagelogging logentiremessage= "true" logknownpii= "false" logmalformedmessages= "true"
Logmessagesatservicelevel= "true" logmessagesattransportlevel= "true"/>
<endtoendtracing propagateactivity= "true" activitytracing= "true"
Messageflowtracing= "true"/>
</diagnostics>

<services>
<service name= "Wcfservicelib.bookservice" >
<endpoint address= "Net.tcp://127.0.0.1:9999/bookservice" binding= "nettcpbinding"
contract= "Contracts.ibookservice"/>

</service>
</services>
</system.serviceModel>
</configuration>
We use nettcpbinding to simulate two-way communication based on TCP. The code is as follows:

Using Contracts;
Using System;
Using System.Collections.Generic;
Using System.Linq;
Using System.ServiceModel;
Using System.ServiceModel.Description;
Using System.Text;
Using System.Threading.Tasks;
Using Wcfservicelib;

Namespace Consolehosting
{

Class Program
{

static void Main (string[] args)
{
Console.WriteLine ("Enter the starting mode, C--code A--app.config way!") ");
String key = Console.ReadLine ();
Switch (key)
{
Case "C":
Startbycode ();
Break
Case "A":
Startbyconfig ();
Break
Default
Console.WriteLine ("Do not choose the way to start, use the default method");
Startbycode ();
Break

}
}

private static void Startbycode ()
{

Create a host's base address
Uri baseaddress = new Uri ("Http://localhost:8080/BookService");
Creating a Host
using (ServiceHost host = new ServiceHost (typeof (Bookservice), baseaddress))
{

               //Add endpoints to the host
                host. AddServiceEndpoint (typeof (Ibookservice), New Wsdualhttpbinding (), baseaddress);
                if (host. description.behaviors.find<servicemetadatabehavior> () = null)

                {
                    // Set the Httpgetenabled property to True
                     servicemetadatabehavior behavior = new ServiceMetadataBehavior ();
                     behavior. Httpgetenabled = true;
                     behavior. Httpgeturl = baseaddress;
                    //Add behavior to behaviors

Host. DESCRIPTION.BEHAVIORS.ADD (behavior);
Open Host

Host. Opened + + delegate
{
Console.WriteLine ("Bookservice Console program boarding has started, HTTP listening has started ..., press any key to terminate service!") ");
};

Host. Open ();
Print endpoint Information

Console.foregroundcolor = Consolecolor.yellow;
foreach (ServiceEndpoint se in host. description.endpoints)
{
Console.WriteLine ([endpoint]: {0}\r\n\t[a-address]: {1} \r\n\t [B-binding]: {2} \r\n\t [C-contract]: {3} ',
Se. Name, SE. Address, se. Binding.name, SE. Contract.name);
}
Console.read ();
}
}

}

private static void Startbyconfig ()
{
using (ServiceHost host = new ServiceHost (typeof (Bookservice))
{
Host. Opened + + delegate
{

Console.WriteLine ("Bookservice Console program boarding has started, TCP listening has started ..., press any key to terminate service!") ");
};

                host. Open ();
               //print Endpoint information                

                Console.foregroundcolor = Consolecolor.yellow;
                foreach ( ServiceEndpoint SE in host. description.endpoints)
                 {
                     Console.WriteLine ([endpoint]: {0}\r\n\t[a-address]: {1} \r\n\t [B-binding]: {2} \r\n\t [C-contract]: {3} ',
 & nbsp;               SE. Name, SE. Address, se. Binding.name, SE. Contract.name);
 
               }

Console.read ();
}

}

}

}


4. Client:

The information in the configuration file is modified:

<system.serviceModel>
<client>
<endpoint address= "Net.tcp://localhost:9999/bookservice" binding= "nettcpbinding"

bindingconfiguration= "" Contract= "Contracts.ibookservice"

Name= "Bookserviceendpoint"/>
</client>
</system.serviceModel>
Next you implement the call to the duplex service, which is the associated configuration and managed program. In the service Invoker, create service proxy objects through duplexchannelfactory<tchannel>,duplexchannelfactory<tchannel> and ChannelFactory <TChannel> functionality is a creation factory for a service proxy object, but Duplexchannelfactory<tchannel> is dedicated to the creation of service proxies based on duplex traffic. Before creating the Duplexchannelfactory<tchannel>, a callback object is created and the callback object is wrapped by InstanceContext. The code is as follows:

private void Btntcpduplex_click (object sender, EventArgs e)
{

duplexchannelfactory<ibookservice> ChannelFactory = new Duplexchannelfactory<ibookservice> ( InstanceContext, "Bookserviceendpoint");
Ibookservice client = Channelfactory.createchannel ();

With two methods on the Mainthread (delegate) object of the Bookcallback object, calling the Mainthread object in the thread is equivalent to calling both methods.

TextBox1.Text = = String. Format ("Start calling WCF service: {0}\r\n\r\n", DateTime.Now.ToString ("Yyyy-mm-dd HH:mm:ss"));

Client. DisplayName ("TCP---science can read books in this Way");

TextBox1.Text = = String. Format ("\r\n\r\n Call ended: {0}", DateTime.Now.ToString ("Yyyy-mm-dd HH:mm:ss"));
}
In creating duplexchannelfactory< Ibookservice >, the callback context Instance is specified: A callback object that implements the contract Bookcallback. The object is obtained by operationcontext.current.getcallbackchannel<icallback> () in the service.

The results after running the program are as follows:

2. Bi-directional communication v.s based on Http. Bi-directional communication based on TCP

Because of the differences between HTTP and TCP in their respective protocols, their hairstyles for two-way communication are different.

HTTP is an application-level protocol, and its main feature is connectionless and stateless. It uses the traditional "request/reply" Method of communication, the client sends HTTP request to the server side of a resource, the server received the HTTP request, postback corresponding HTTP Response. When the client receives the corresponding response, the connection is closed. That is, the connection between the client and the server is maintained only during the period of sending request to receive the response. At the same time, each HTTP-based connection is independent and irrelevant, and the current connection cannot get the state of the last connection. In order to save the state information of the invocation, ASP. NET by saving the state information in the server session, the specific approach is: ASP.net for each session to create a Unique ID, associated with a HttpSessionState object, And keep state information in memory or persistent storage media (such as SQL Server). WCF, in turn, implements the session support in a different way: it is associated with a service instance.

Let's talk about the process of HTTP two-way communication, when a client invokes a WCF service via an HTTP request, an endpoint is created on the client to listen for requests to it from the server. A client call to a WCF service establishes a client to server connection, and when the WCF service needs to callback the corresponding client during the execution of the operation, another server-side HTTP connection is actually established. While we say that WCF provides a duplex channel to support bidirectional communication, this duplex channel is actually made up of two HTTP connections.

Then look at TCP two-way communication process, for the TCP Transport layer protocol, it is a connection based protocol, before the formal data transmission, it is necessary to establish a connection between the client and the server, the connection is established through the classic "3 handshake" to achieve. TCP is inherently duplex, meaning that when a connection is created, data delivery from the client to the server and from the server to the client can be implemented using the same connection. For bidirectional communication in WCF, the client invokes the server, and the service-side callback client operation uses the same connection, the same channel. So the duplex communication mode based on TCP is really the duplex communication mode in the sense.

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.