WCF如何绑定netTcpBinding寄宿到控制台应用程序详解

2022-10-16,,,,

契约

新建一个wcf服务类库项目,在其中添加两个wcf服务:gameservice,playerservice

代码如下:

[servicecontract]
public interface igameservice
{
 [operationcontract]
 task<string> dowork(string arg);
}
public class gameservice : igameservice
{
 public async task<string> dowork(string arg)
 {
  return await task.fromresult($"hello {arg}, i am the gameservice.");
 }
}
[servicecontract]
public interface iplayerservice
{
 [operationcontract]
 task<string> dowork(string arg);
}
public class playerservice : iplayerservice
{
 public async task<string> dowork(string arg)
 {
  return await task.fromresult($"hello {arg}, i am the playerservice.");
 }
}

服务端

新建一个控制台应用程序,添加一个类 servicehostmanager

public interface iservicehostmanager : idisposable
{
 void start();
 void stop();
}

public class servicehostmanager<tservice> : iservicehostmanager
 where tservice : class
{
 servicehost _host;

 public servicehostmanager()
 {
  _host = new servicehost(typeof(tservice));
  _host.opened += (s, a) => {
   console.writeline("wcf监听已启动!{0}", _host.description.endpoints[0].address);
  };
  _host.closed += (s, a) =>
  {
   console.writeline("wcf服务已终止!{0}", _host.description.endpoints[0].name);
  };   
 }
 public void start()
 {
  console.writeline("正在开启wcf服务...{0}", _host.description.endpoints[0].name);
  _host.open();
 }
 public void stop()
 {
  if (_host != null && _host.state == communicationstate.opened)
  {
   console.writeline("正在关闭wcf服务...{0}", _host.description.endpoints[0].name);
   _host.close();
  }
 }
 public void dispose()
 {
  stop();
 }

 public static task startnew(cancellationtokensource canceltokensource)
 {
  var thetask = task.factory.startnew(() =>
  {
   iservicehostmanager shs = null;
   try
   {
    shs = new servicehostmanager<tservice>();
    shs.start();
    while (true)
    {
     if (canceltokensource.iscancellationrequested && shs != null)
     {
      shs.stop();
      break;
     }
    }
   }
   catch (exception ex)
   {
    console.writeline(ex);
    if (shs != null)
     shs.stop();
   }
  }, canceltokensource.token);

  return thetask;
 }
}

在main方法中启动wcf主机

class program
 {
  static program()
  {
   console.writeline("初始化...");
   console.writeline("服务运行期间,请不要关闭窗口。");
   console.writeline();
  }

  static void main(string[] args)
  {
   console.title = "wcf主机 x64.(按 [esc] 键停止服务)";
   var canceltokensource = new cancellationtokensource();
   servicehostmanager<wcfcontract.services.gameservice>.startnew(canceltokensource);
   servicehostmanager<wcfcontract.services.playerservice>.startnew(canceltokensource);
   while (true)
   {
    if (console.readkey().key == consolekey.escape)
    {
     console.writeline();
     canceltokensource.cancel();
     break;
    }
   }
   console.readline();
  }
 }

服务端配置

在控制台应用程序的app.config中配置system.servicemodel

<system.servicemodel>
 <services>
  <service name="wettery.wcfcontract.services.gameservice" behaviorconfiguration="gamemetadatabehavior">
  <endpoint address="net.tcp://localhost:19998/wettery/gameservice" binding="nettcpbinding" contract="wettery.wcfcontract.services.igameservice" bindingconfiguration="nettcpbindingconfig">
   <identity>
   <dns value="localhost" />
   </identity>
  </endpoint>
  </service>
  <service name="wettery.wcfcontract.services.playerservice" behaviorconfiguration="playermetadatabehavior">
  <endpoint address="net.tcp://localhost:19998/wettery/playerservice" binding="nettcpbinding" contract="wettery.wcfcontract.services.iplayerservice" bindingconfiguration="nettcpbindingconfig">
   <identity>
   <dns value="localhost" />
   </identity>
  </endpoint>
  </service>
 </services>
 <bindings>
  <nettcpbinding>
  <binding name="nettcpbindingconfig" closetimeout="00:30:00" opentimeout="00:30:00" receivetimeout="00:30:00" sendtimeout="00:30:00" transactionflow="false" transfermode="buffered" transactionprotocol="oletransactions" hostnamecomparisonmode="strongwildcard" listenbacklog="100" maxbufferpoolsize="2147483647" maxbuffersize="2147483647" maxconnections="100" maxreceivedmessagesize="2147483647">
   <readerquotas maxdepth="64" maxstringcontentlength="2147483647" maxarraylength="2147483647 " maxbytesperread="4096" maxnametablecharcount="16384" />
   <reliablesession ordered="true" inactivitytimeout="00:30:00" enabled="false" />
   <security mode="transport">
   <transport clientcredentialtype="windows" protectionlevel="encryptandsign" />
   </security>
  </binding>
  </nettcpbinding>
 </bindings>
 <behaviors>
  <servicebehaviors>
  <behavior name="gamemetadatabehavior">
   <servicemetadata httpgetenabled="true" httpgeturl="http://localhost:8081/wettery/gameservice/metadata" />
   <servicedebug includeexceptiondetailinfaults="true" />
   <servicethrottling maxconcurrentcalls="1000" maxconcurrentinstances="1000" maxconcurrentsessions="1000" />
  </behavior>
  <behavior name="playermetadatabehavior">
   <servicemetadata httpgetenabled="true" httpgeturl="http://localhost:8081/wettery/playerservice/metadata" />
   <servicedebug includeexceptiondetailinfaults="true" />
   <servicethrottling maxconcurrentcalls="1000" maxconcurrentinstances="1000" maxconcurrentsessions="1000" />
  </behavior>
  </servicebehaviors>
 </behaviors>
 </system.servicemodel>

未避免元数据泄露,部署时将httpgetenable设为false

运行控制台应用程序

按[esc]键终止服务

客户端测试

服务端运行后,用wcftestclient工具测试,服务地址即behavior中配置的元数据get地址

http://localhost:8081/wettery/gameservice/metadata

http://localhost:8081/wettery/playerservice/metadata

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。

《WCF如何绑定netTcpBinding寄宿到控制台应用程序详解.doc》

下载本文的Word格式文档,以方便收藏与打印。