2009-02-01 4 views
7

저는 C#에서 "올바른"네트워크 코드를 작성하는 최선의 방법에 대해 많은 연구를 해 왔습니다.C# 네트워크 프로그래밍 및 리소스 사용

C#의 "using"문을 사용하여 여러 가지 예제를 보았습니다. 그러나 이것은 좋은 접근 방법이라고 생각합니다. 그러나 다양한 식과 일관성없는 사용법을 보아 왔습니다. 예를 들어

, 나는 몇 가지 코드를 다음과 같이 있다고 가정

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

물론,이 코드는 매우 색다른 될 것입니다. 그래서, tcpClient에서 사용하는 코드를 보았습니다. 그러나 NetworkStream에도 정리가 필요한 리소스가 있습니까? StreamReader/Writer는 어떻습니까?

내포 된 using 문에 4 개의 문을 모두 감쌀 필요가 있습니까?

만약 그렇다면 시간이 끝나면 어떻게 될까요? StreamWriter가 스트림을 닫고 결과적으로 소켓을 닫지 않습니까? 그런 다음 StreamReader, NetworkStream, TcpClient가 각각 처분 될 때 어떤 일이 발생합니까?

다른 질문이 제기됩니다. StreamReader와 StreamWriter가 같은 스트림으로 구성되어 있는데 누가 소유하고 있습니까? 그들은 둘 다 자신이 그것을 소유하고 있다고 생각하지 않으며, 따라서 그것을 파괴하려고 시도하지 않을 것인가? 아니면 프레임 워크가 스트림이 이미 파괴되었다는 사실을 알고 자동으로 무시합니다.

사용하는 명령문이 체인의 마지막 명령문에만 필요하지만 거의 예외가 발생하면 GetStream()에 어떤 결과가 발생합니까? 나는 소켓을 적절하게 청소할 것이라고 생각하지 않는다. 따라서 중복 사용은 이것이 일어나지 않도록하는 데 필요하다.

누구든지 네트워크 프로그래밍에 대한 최신 지식을 알고 있습니까 ?net 및 prefeably C# 예외 처리 및 리소스 관리에 대한 장을 포함합니까? 아니면 온라인에서 좋은 기사일까요? 내가 찾을 수있는 모든 책은 .NET 1.1 시대 (Microsoft .NET Framework 용 네트워크 프로그래밍, .NET에서의 네트워크 프로그래밍 등)에서 나온 것이므로 좋은 리소스가 필요한 주제처럼 보입니다.

편집 :

, 마크의 아주 좋은 의견이 :)에 대한 주석에서 다른 사람을 중지하지 마십시오

나는, 자원 관리에 누구를 elses 책 권고 또는 의견을 특히 듣고 싶습니다

비동기 사용과 관련하여

답변

14

일반적으로 개체는 내부적으로 여러 Dispose() 호출을 처리해야하며 주 코드 만 한 번 수행해야합니다. 따라서 Dispose() d 번을 여러 번 가져 오는 스트림은 일반적으로 문제가되지 않습니다. 개인적으로 나는 using을 많이 사용합니다. (다른 수준이 서로 다른 삶의 시간을 제외하고)하지만 당신은/들여 쓰기 둥지를 필요는 없습니다 :

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)) 
{ 
    ... 
} 

당신이 말하는 것처럼, 이것은 오류가 초기화하는 동안 발생하는 경우, 모든 것이 아직 정리되는 것을 보장한다 바르게. 이것은 또한 모든 레벨이 버퍼링 된 데이터 등을 올바르게 처리 할 수있는 기회를 얻게합니다.

Re ownership; NetworkStream은 실제로 처음에는 이상합니다 ... 대부분의 스트림은 입력 xor 출력 중 하나입니다.NetworkStream은 몇 가지 규칙을 구부리며 두 방향을 하나의 API로 표현합니다. 그래서 이것은 예외입니다 ... 일반적으로 소유권은 더 명확합니다. 또한 많은 래퍼에는 래핑 된 스트림을 닫아야하는지 여부를 결정하는 플래그가 있습니다. StreamReader은 아니지만 일부는 수행합니다 (GZipStream, 예 : leaveOpen ctor 옵션). 소유권을 흘리지 않으려면이 옵션을 사용하거나 폐업하지 않는 스트림 중개자를 사용하십시오. 하나는 here (NonClosingStream 또는 그 유사)입니다.

Re books; 나는 "TCP/IP Sockets in C# : Practical Guide for Programmer"(here)의 사본을 골랐다.

+0

감사합니다. 이것은 크게 내가 의심했던 것입니다. 나는 NetworkStream이 이상하다는 점에 동의한다. 별도의 스트림을 작성하고 스트림을 작성하는 것이 덜 문제가되는지 확실하지 않지만 그것이 무엇인지 알 수 있습니다. 책 추천 주셔서 감사합니다. –

+0

또한 언급 한 사이트에서 NonClosingStream 구현을 보지 못했습니다. –

+0

거기에 있습니다 - MiscUtil.IO.NonClosingStreamWrapper –

0

개체가 IDisposable을 지원하는 경우 dispose 메서드가 자동으로 호출되므로 {} 블록을 사용하는 것이 가장 좋습니다. 이것은 또한 당신의 부분에 적은 코드를 만듭니다. 'using'을 사용하면 예외를 처리하지 않는다는 것을 알아 두는 것이 중요합니다. 오류를 처리하고 싶다면 여전히해야합니다. 사용 블록이 범위를 벗어나면 개체도 마찬가지입니다.

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 
} 
-1

소켓이란 무엇입니까? 는 확인을하는 것입니다 : 피드백에 대한

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

이상

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