remarks generate example c# .net network-programming using-statement

generate - C#programación de red y uso de recursos



params comments c# (3)

He estado investigando mucho sobre la mejor forma de escribir el código de red "correcto" en C #.

He visto una serie de ejemplos usando la instrucción "usar" de C #, y creo que este es un buen enfoque, sin embargo, he visto un uso inconsistente de él con varias expresiones.

Por ejemplo, supongamos que tengo un código como este:

TcpClient tcpClient = new TcpClient("url.com", 80); NetworkStream tcpStream = tcpClient.GetStream(); StreamReader tcpReader = new StreamReader(tcpStream); StreamWriter tcpWriter = new StreamWriter(tcpStream);

Obviamente, este código va a ser muy escamoso. Entonces, he visto un código que pone el uso en el tcpClient, lo cual parece bueno. Sin embargo, ¿NetworkStream tampoco tiene recursos que necesiten limpiarse? ¿Qué pasa con StreamReader / Writer?

¿Debo completar las 4 declaraciones en declaraciones de uso anidado?

Y si es así, ¿qué sucede cuando ha llegado el momento de deshacerse? ¿StreamWriter no cerrará la transmisión y, en consecuencia, el socket? Entonces, ¿qué sucede cuando StreamReader, luego NetworkStream, luego TcpClient cada uno pasa por sus disposiciones?

Lo cual nos lleva a otra pregunta. Con StreamReader y StreamWriter compuestos de la misma secuencia, ¿a quién pertenece? ¿No creen los dos que son los dueños y por lo tanto tratarán de destruirlo? ¿O el marco sabe que la secuencia ya ha sido destruida y simplemente la ignora silenciosamente?

Casi parece que la sentencia using solo es necesaria para la última instrucción de la cadena, pero ¿qué ocurre si se lanza una excepción en GetStream ()? No creo que limpiaría adecuadamente el socket entonces, por lo que parece redundante, los usos son necesarios para garantizar que esto no suceda.

¿Alguien sabe de algún buen libro reciente sobre programación de redes con .net y preferiblemente c # que incluya capítulos sobre el manejo de excepciones y la gestión de recursos? O tal vez algunos buenos artículos en línea? Todos los libros que puedo encontrar pertenecen a la era .NET 1.1 (Programación de redes para Microsoft .NET Framework, Programación de redes en .NET, etc.), por lo que parece un tema que necesita algunos buenos recursos.

EDITAR:

Por favor, no dejen que el muy buen comentario de Marc impida que alguien más comente esto :)

Me gustaría escuchar a cualquier persona leer recomendaciones u opiniones sobre el manejo de recursos, especialmente con respecto al uso asincrónico.


En general, los objetos deben manejar internamente múltiples llamadas Dispose() y solo hacer el código principal una vez; por lo tanto, una secuencia que obtenga Dispose() d varias veces no suele ser un problema. Personalmente, usaría mucho de using allí; Sin embargo, tenga en cuenta que no necesita sangrar / anidar (a menos que diferentes niveles tengan diferentes tiempos de vida):

using(TcpClient tcpClient = new TcpClient("url.com", 80)) using(NetworkStream tcpStream = tcpClient.GetStream()) using(StreamReader tcpReader = new StreamReader(tcpStream)) using(StreamWriter tcpWriter = new StreamWriter(tcpStream)) { ... }

Como dices, esto garantiza que si se produce un error durante la inicialización, todo se limpia correctamente. Esto también garantiza que cada nivel tenga la oportunidad (en el orden correcto) de manejar correctamente cualquier información almacenada en el búfer, etc.

Re de la propiedad; En primer lugar, NetworkStream es una rareza ... la mayoría de las transmisiones tienen entrada xo salida. NetworkStream dobla algunas reglas y calza dos direcciones en una API; entonces esta es una excepción ... normalmente la propiedad sería más clara. Además, muchos contenedores tienen un indicador para determinar si deben cerrar el flujo envuelto. StreamReader no lo hace, pero algunos lo hacen (como GZipStream , que tiene una opción leaveOpen ctor). Si no desea transferir la propiedad, esta es una opción, o puede usar un intermediario de flujo no cerrado, aquí está ( NonClosingStream o similar).

Re libros; Recogí una copia de "Sockets TCP / IP en C #: Guía práctica para programadores" ( aquí ): adecuada, pero no excelente.


Si un objeto admite IDisposable, lo mejor es ponerlo en un bloque de {} uso porque el método de eliminación se llama automáticamente. Esto también hace que haya menos código de su parte. Es importante tener en cuenta que usar ''usar'' no maneja ninguna excepción. Aún debes hacer eso si quieres manejar cualquier error. Una vez que el bloque de uso está fuera del alcance, también lo hace su objeto.

Old Style Code object obj; try { obj= new object(); //Do something with the object } catch { //Handle Exception } finally { if (obj != null) { obj.Dispose(); } } Newer Style Code try { using (object obj = new object()) { //Do something with the object } catch { //Handle Exception }


¿Qué hay de los enchufes? ¿Está bien hacer eso?

serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); serverSocket.Connect(serverEndPoint, m_NegotiationPort); . . . serverSocket.Close();

o mejor

using (Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) { . . . }