2013-07-19 3 views
3

많은 소켓에서 데이터를 송수신하는 소프트웨어를 개발 중입니다. 그것은 매우 비동기 적이며 그 이유 때문에 다음과 같은 시나리오가 걱정됩니다. N 개의 스레드가 동일한 소켓에 데이터를 보내려고합니다. 이것은 BeginSend를 동시에 호출하는 N 개의 스레드입니다.소켓 비동기 데이터 송수신

명확화 : 스레드를 사용하지 않지만 '시스템'이 사용합니다. "응용 프로그램이 BeginSend를 호출하면 시스템이 별도의 스레드를 사용하여 지정된 콜백 메서드를 실행합니다."

SocketException과 함께 실패했는지 확인하기 위해이 테스트를 수행했습니다. 아닙니다. (그에 대한 문서를 찾을 수 없기 때문에) 아니요 :

[Test] 
    public void DoIt2() 
    { 
     var byteCount = 0; 
     var manualEvents = new[] { new ManualResetEvent(false), new ManualResetEvent(false), new ManualResetEvent(false) }; 
     var message = new byte[] { 0x01, 0x02, 0x03, 0x04 }; 
     var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 

     var callback = new AsyncCallback(ar =>{ 
      var resetEvent = (ManualResetEvent)ar.AsyncState; 
      Interlocked.Add(ref byteCount, socket.EndSend(ar)); 
      resetEvent.Set(); 
     }); 

     socket.Connect("127.0.0.1", 8000); 
     socket.BeginSend(message, 0, message.Length, SocketFlags.None, callback, manualEvents[0]); 
     socket.BeginSend(message, 0, message.Length, SocketFlags.None, callback, manualEvents[1]); 
     socket.BeginSend(message, 0, message.Length, SocketFlags.None, callback, manualEvents[2]); 

     WaitHandle.WaitAll(manualEvents); 

     socket.Close(); 
     Assert.AreEqual(12, byteCount); 
    } 

녹색이되었습니다. 그러나, 뭔가 잘못되었다는 것을 알아야합니다. EndSend/EndReceive가 호출되기 전에 BeginSend/BeginReceive를 여러 번 호출 할 수 있다고 가정하는 것이 안전합니까? 내 말은, 다음과 같은 패턴이 오케이 야?

  1. BeginSend
  2. BeginSend
  3. BeginSend
  4. EndSend 무엇 도착 데이터 순서에 대한
  5. EndSend
  6. EndSend

? 나는 이것이 TCP라는 것을 알고 있지만 나의 질문은 BeginSend가 비동기 적이기 때문에 1에서 보낸 데이터는 2와 3 전에 도착할 것인가?

감사합니다.

답변

0

.NET 소켓 객체의 특성에 대해서는 잘 모릅니다. 그러나 일반적으로 다른 스레드에서 동일한 소켓으로 전송하는 것은 좋은 생각이 아닙니다. 소켓에서 보낸 데이터는 순서에 관계없이 그 소켓의 프로토콜을 위반할 가능성이 큽니다.

+0

요점은 스레드를 사용하지 않지만 '시스템'이 사용한다는 것입니다. 그 문서는 "응용 프로그램이 BeginSend를 호출 할 때 시스템은 별도의 스레드를 사용하여 지정된 콜백 메소드를 실행합니다"라고 말합니다. 나는 '시스템'이 OS라고 가정한다. 나는 그 질문을 분명히하도록 업데이트 할 것이다. 고마워요 – lontivero

+0

사과드립니다. 나는 .NET 클래스가 당신이하고있는 일을 감싸는 wrapper라면, 당신이 보낸 순서대로 OS가 그것을 할 것이라는 것을 안다. OS는 각 전송 요청마다 다른 스레드를 사용하지 않습니다. – noz

+0

설명 해석하기 수업이 OS 레벨에서 IO 완성을 사용하고 있다고 생각됩니다. 이 말은 콜백이 BeginSend를 호출 한 스레드와 다른 스레드에서 발생한다는 것입니다. 그러나 추가 스레드가 하나만 포함되어 있습니다. 콜백이 스레드 안전 인 한 모든 것이 잘되어야합니다. – noz