configurar c# wcf wcf-binding net.tcp

c# - configurar web.config wcf



ConfiguraciĆ³n del servicio WCF TCP en una aplicaciĆ³n web (7)

He estado luchando con esto durante días, literalmente pasando por un centenar de artículos que dan pautas parciales sobre cómo configurar un servicio WCF basado en TCP en una aplicación web. Si alguien puede ayudarme, haré esta pregunta en una guía completa .

Estado actual

La conexión net.tcp funciona en mi máquina de desarrollo. También funciona localmente después de ser implementado en un Windows Server 2008 R2. Sin embargo, no funciona de forma remota, aunque es posible hacer telnet al puerto 808 en el servidor de forma remota. Desplázate hasta la parte inferior de la pregunta para obtener más información. Por favor ayuda si puedes.

Crearé una nueva pregunta para este detalle y actualizaré esta pregunta con la respuesta si obtengo un resultado.

Código

ServerHubService.svc con el siguiente contenido:

namespace Manage.SignalR { [ServiceContract] public class ServerHubService { [OperationContract] public void UpdateServerStatus(string serverStatus) { // Do something } } }

Configuración de la aplicación que aloja el servicio

Después de un tutorial en línea, agregué lo siguiente a mi Web.config (Probé MUCHAS variaciones diferentes). Este es el Web.config de la aplicación web que aloja el servicio al que más tarde quiero conectarme con TCP.

<configuration> <system.serviceModel> <services> <service behaviorConfiguration="ServerHubBehavior" name="Manage.SignalR.ServerHubService"> <endpoint address="" binding="netTcpBinding" bindingConfiguration="portSharingBinding" name="MyServiceEndpoint" contract="Manage.SignalR.ServerHubService"> <identity> <dns value="localhost" /> </identity> </endpoint> <endpoint address="mex" binding="mexTcpBinding" bindingConfiguration="" name="MyServiceMexTcpBidingEndpoint" contract="IMetadataExchange" /> <host> <baseAddresses> <add baseAddress="net.tcp://test.mydomain.com:808/SignalR/ServerHubService.svc" /> </baseAddresses> </host> </service> </services> <behaviors> <serviceBehaviors> <behavior name="ServerHubBehavior"> <serviceMetadata httpGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="false" /> </behavior> </serviceBehaviors> </behaviors> <bindings> <netTcpBinding> <binding name="portSharingBinding" portSharingEnabled="true"/> </netTcpBinding> </bindings> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" minFreeMemoryPercentageToActivateService="0" multipleSiteBindingsEnabled="true" /> </system.serviceModel> </configuration>

httpGetEnabled="true" es importante porque de lo contrario no puede crear una referencia de servicio para el servicio.

Configuración del servidor donde se ejecuta la aplicación web

Estoy configurando esto en mi máquina de desarrollo que tiene IIS 7.5

Leí que IIS Express (integrado en Visual Studio) no es compatible con net.tcp, así que configuré un nuevo sitio web en IIS 7.5 usando .NET 4.5 y que tiene un enlace net.tcp

También fui a Configuración avanzada para el sitio web y establecí Protocolos habilitados a http,net.tcp

Me aseguré de que la característica de activación no HTTP de Windows esté habilitada (y reiniciada). Es una función de Windows así que busque "Activar o desactivar las características de Windows" para encontrar esto.

Confirmando que la aplicación web se está ejecutando

El sitio web funciona bien para el resto de la aplicación web. Configuré test.mydomain.com para señalar a 127.0.0.1 en mi archivo hosts . Incluso puedo visitar http://test.mydomain.com/SignalR/ServerHubService.svc y me mostrará una buena página generada automáticamente desde .NET, explicando cómo usar este servicio.

Hasta aquí todo bien.

La página generada por .NET me dice que use esta dirección para generar una conexión a mi servicio:

net.tcp://computername/SignalR/ServerHubService.svc/mex

Intentando conectarse al servicio como un cliente

Si no recuerda establecer httpGetEnabled="true" , obtendrá un error al intentar crear una referencia de servicio. Si utiliza WCF Test Client (también una herramienta incluida en Visual Studio) y no configuró httpGetEnabled, obtendrá un error como el siguiente:

Error: No se pueden obtener los metadatos de net.tcp: //nombreDeEquipo/SignalR/ServerHubService.svc/mex

Si se trata de un servicio de Windows (R) Communication Foundation al que tiene acceso, verifique que haya habilitado la publicación de metadatos en la dirección especificada. Para obtener ayuda sobre la publicación de metadatos, consulte la documentación de MSDN en http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata

URI de error de Exchange: net.tcp: //nombreDeEquipo/SignalR/ServerHubService.svc/mex La metadata contiene una referencia que no se puede resolver: ''net.tcp: //nombreDeEquipo/SignalR/ServerHubService.svc/mex''. No se pudo conectar a net.tcp: //nombreDeEquipo/SignalR/ServerHubService.svc/mex. El intento de conexión duró un lapso de tiempo de 00: 00: 04.0032289.

Código de error de TCP 10061: No se pudo establecer ninguna conexión porque la máquina de destino la rechazó activamente [2001: 0: 4137: 9e76: c81: a4c: a547: b2fd]: 808. No se pudo establecer ninguna conexión porque la máquina objetivo lo rechazó activamente [2001: 0: 4137: 9e76: c81: a4c: a547: b2fd]: 808

Sin embargo, si has hecho todo lo anterior, deberías poder agregar una referencia al servicio.

Métodos de llamada en el servicio

Al intentar llamar a un método Hello World simple en el servicio de WCF Test Client, devuelve el siguiente error:

No se pudo conectar a net.tcp: //nombredecomputadora/SignalR/ServerHubService.svc. El intento de conexión duró un lapso de tiempo de 00: 00: 04.0002288. Código de error de TCP 10061: No se pudo establecer conexión porque la máquina de destino la rechazó activamente.

Esta es la stacktrace interna que se incluye con el error:

No se pudo establecer ninguna conexión porque la máquina de destino la rechazó activamente [2001: 0: 5ef5: 79fb: 3884: a: a547: b2fd]: 808 en System.Net.Sockets.Socket.DoConnect (EndPoint endPointSnapshot, SocketAddress socketAddress) en System .Net.Sockets.Socket.Connect (EndPoint remoteEP) en System.ServiceModel.Channels.SocketConnectionInitiator.Connect (Uri uri, TimeSpan timeout)

Si usa netstat -an |find /i "listening" para ver que no escucha nada en el puerto 808, es probable que se deba a que el servicio Net.Tcp Listener Adapter no se está ejecutando.

Confirmación

La llamada se realiza ahora, pero se necesita alguna confirmación antes de que se pueda declarar un éxito. Debo confirmar que, de hecho, se trata de una llamada net.tcp al puerto 808 y no una llamada en el punto final http. Estoy tratando de hacer esto con Wireshark, pero no aparece, probablemente porque es una llamada que ocurre desde y hacia mi máquina local.

Despliegue

El último desafío para conquistar sería implementar esto en un servidor web, asegurando que lo que funciona en la máquina de desarrollo también funcione en el servidor web.

No funciona después de publicar en Windows Server 2008 R2. SocketException: An existing connection was forcibly closed by the remote host la SocketException: An existing connection was forcibly closed by the remote host común SocketException: An existing connection was forcibly closed by the remote host .

Funciona bien localmente en el servidor, pero no funciona de forma remota.

Aquí está la lista de verificación utilizada para verificar el servidor:

  • ¿Se está ejecutando el servicio Net.Tcp Listener Adapter ? Sí
  • ¿El sitio de IIS es vinculante para net.tcp establecido en 808:* ? Sí
  • ¿Los protocolos habilitados en Configuración avanzada para el sitio en IIS están configurados en http,net.tcp ? Sí
  • ¿El servidor está escuchando en el puerto 808? Sí, comprobado con netstat -an |find /i "listening"
  • ¿Hay un puerto 808 abierto en el firewall? Sí.
    • El cortafuegos está apagado en el servidor.
    • Puedo hacer telnet al servidor en el puerto 808 desde afuera con telnet mydomain.com 808
  • En la configuración del servicio en el servidor, se confirmó lo siguiente:
    • baseAddress se ajusta a net.tcp://mydomain.com:808/SignalR/ServerHubService.svc
    • Esto era localhost anteriormente, pero cambió a mydomain.com después de que no funcionó en el servidor: <identity><dns value="mydomain.com" /></identity>
  • Ha sido probado con un cliente localmente en el servidor y en otro servidor. Ambos pueden conectarse al puerto 808 con telnet y ambos dan el mismo mensaje de error.

¿Qué configuración podría faltar en el servidor? Estoy muy cerca de la meta. Ayúdenme a solucionar este problema y completar la pregunta.

Aquí está la configuración del cliente en el servidor que llama al servicio:

<system.serviceModel> <bindings> <netTcpBinding> <binding name="MyServiceEndpoint" /> </netTcpBinding> </bindings> <client> <endpoint address="net.tcp://mydomain.com:808/SignalR/ServerHubService.svc" binding="netTcpBinding" bindingConfiguration="MyServiceEndpoint" contract="ServerHubService.ServerHubService" name="MyServiceEndpoint"> <identity> <dns value="mydomain.com" /> </identity> </endpoint> </client> </system.serviceModel>

También probé sin 808 configurado en el punto final, ya que se rumorea que es el puerto predeterminado para las conexiones net.tcp. Sin embargo, todavía da el mismo resultado.

En lugar de intentar muchas cosas al azar, la buena pregunta es tal vez: ¿cómo se puede depurar algo como esto? ¿Puedo instalar un programa en cualquiera de los servidores que me dirá exactamente POR QUÉ está bloqueada esta llamada?

Con Wireshark configurado de esta manera, es posible ver la llamada que llega al servidor en el puerto 808 y posiblemente determinar por qué la llamada no funciona. Sin embargo, no tengo idea de cómo analizar esto en este momento.

Buena suerte

Me di por vencido e implementado esto en la capa de socket en su lugar. Funcionó de inmediato. Espero que esto pueda ayudar a otra persona, sin embargo. Estoy estableciendo una respuesta porque muchos de los problemas se resolvieron y eventualmente funcionó localmente, por lo que cualquier problema restante probablemente esté relacionado con mi entorno específico.


¿Intentó alojar el servicio (con fines de prueba) en un servicio de Windows en su máquina local? De esta forma, al menos sabrá si el problema está en el lado del servicio o en la configuración de IIS / servidor.


Alojar un servicio basado en TCP en IIS siempre ha sido un oso. WCF hace que sea muy fácil ejecutar su propio host de servicio, escuchando en su puerto TCP. Mi recomendación sería hacer eso y configurarlo para que funcione como un servicio de Windows.

Vea este artículo: http://msdn.microsoft.com/en-us/library/ff649818.aspx



En su pregunta mencionó que se conectó a "test.midominio.com" pero el error cambió el servidor a "nombre de computadora". Luego, en tu comentario, lo mencionas y todavía no puedes conectarte. Si desea que se devuelva el alias en WSDL / MEX, agregue el nodo useRequestHeadersForMetadataAddress en su comportamiento de servicio. Aquí está la información de MSDN en este nodo: MSDN useRequestHeadersForMetadataAddress node

Así es como debería verse tu configuración. Esto tiene en cuenta la respuesta dada por Prasath (httpGetEnabled = "true").

<serviceBehaviors> <behavior name="ServerHubBehavior"> <serviceMetadata httpGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="false" /> <useRequestHeadersForMetadataAddress> <defaultPorts> <add scheme="net.tcp" port="808" /> </defaultPorts> </useRequestHeadersForMetadataAddress> </behavior> </serviceBehaviors>


Supongo que el problema que está teniendo es que necesita configurar el SPN (Nombre principal del servicio) para su servicio WCF (en la máquina) y hacer que se agregue a la cuenta de servicio bajo la cual se está ejecutando el servicio.

Si lo está ejecutando bajo el usuario del grupo de aplicaciones predeterminado, entonces necesita tener el SPN configurado para la máquina.

Sé que es problemático y, por lo general, es la sorpresa que nos espera a los desarrolladores una vez que nuestro servicio esté listo para implementarse en entornos de producción o preproducción.

El Kerberos utiliza el SPN durante el proceso de autenticación.

Intente utilizar la dirección IP de la máquina para resolver su servicio en lugar del nombre de host. (Se supone que esto no requiere un SPN), reemplace "test.midominio.com" por la dirección IP de la máquina:

<host> <baseAddresses> <add baseAddress="net.tcp://192.168.0.253:808/SignalR/ServerHubService.svc" /> </baseAddresses> </host>

Eche un vistazo a estos artículos: - Kerberos para el administrador ocupado
- WCF en la intranet con autenticación de Windows
- Para la siguiente publicación, intente leer la que no se acepta como respuesta: ¿Qué SPN debo configurar para un servicio net.tcp?


Tuve un problema similar aquí hoy, al llamar a un servicio net.tcp wcf desde una asp.net web asp.net. No diré que, de todas las otras máquinas, este servicio ha funcionado durante años, pero las llamadas se realizaron con alojamiento propio, mientras que iis asp.net compatibilidad alojamiento -> contra el servicio net.tcp alojado. Cuando publiqué mi api web simple llamando al mismo servicio net.tcp, todo salió mal, y todas las conexiones se abortaron sin ningún motivo, incluso el seguimiento completo del wcf en ambos lados (servicio y cliente) no ayudó, simplemente diciendo lo mismo "conexión abortada".

Ya sabía que net.tcp viene con la seguridad del transporte habilitado, usando la autenticación de Windows para firmar y cifrar la comunicación, así que bien, intenté desactivar la seguridad y todo comenzó a funcionar correctamente.

Solo inténtelo apagando la seguridad de esta manera en ambos lados (cliente y servicio):

<security mode="None"/>

servicio completo de enlace:

<netTcpBinding> <binding name="netTcpBinding" portSharingEnabled="true"> <security mode="None"/> </binding> </netTcpBinding>

Espero que esto también te pueda ayudar.