2012-08-03 2 views
3

원격 호스트에서 UDP 데이터를받는 C# 응용 프로그램이 있습니다. 나는 때로는 내 소켓이 아무것도받지 못한다는 것을 알았고 나는 왜 그런지 전혀 알지 못한다! Wireshark는 내 데이터가 원격 장치에서 올바르게 전송되고 있다고 알려줍니다. 나는 때로는 내가 잘받을 수있는 이유를 얻는 것 같지 않으며 때로는 할 수 없다.UDP가 때때로 어떤 것도받을 수 없습니다.

나는 예외를하지 않지만, 경우에 내 코드가 도움이됩니다 OnRecieve 여기

라는 결코 극복 :

class cUdpRx 
{ 
    private Thread rxThread = null; 
    private Socket UdpSocket; 
    private IPEndPoint localEp; 
    byte[] byData; 
    //rxbytes event 
    public delegate void OnRxBytesEventHandler(byte[] rxBuf); 
    public event OnRxBytesEventHandler OnRxBytesEvent; 



    /// <summary> 
    /// Creates the udp socket 
    /// </summary> 
    /// <param name="Port"></param> 
    /// <returns></returns> 
    public bool CreateSocket(int Port) 
    { 
     try 
     { 
      byData = new byte[1500]; //create our buffer 
      UdpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 
      UdpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 
      localEp = new IPEndPoint(IPAddress.Any,Port); 
      UdpSocket.Bind(localEp); 
      UdpSocket.BeginReceive(byData,0,byData.Length, SocketFlags.None, new AsyncCallback(OnRecieve), UdpSocket); 

      return true; //seemed to work ok 
     } 
     catch 
     { 
      Dispose(); 
      return false; //something went wrong, abort 
     } 
    } 

    private void OnRecieve(IAsyncResult iar) 
    { 
     byte[] rxData; 
     int nBytesRec = 0; 
     Socket socket = (Socket)iar.AsyncState; 
     try //in case something else has already disposed of the socket 
     { 
      nBytesRec = socket.EndReceive(iar); 
     } 
     catch 
     { 
      Debug.WriteLine("cant access udp rx socket"); 
     } 
     try 
     { 
      if (nBytesRec > 0) 
      { 
       rxData = new byte[nBytesRec]; 
       Array.Copy(byData, rxData, nBytesRec); //copy exact data into new array 
       OnRxBytesEvent(rxData); 
      } 
      if(!killThreads) 
       UdpSocket.BeginReceive(byData, 0, byData.Length, SocketFlags.None, new AsyncCallback(OnRecieve), UdpSocket); 
     } 
     catch(SocketException se) 
     { 
      Debug.WriteLine(se.ToString()); 
     } 
    } 
어떤 도움이 정말 그 앞으로가는 나 중지로 감상 할 수있다

내 프로젝트와. 감사합니다

업데이트 그것은 IPAdress.any를 사용하는 것 같습니다. 내가 변경하는 경우 :

localEp = new IPEndPoint(IPAddress.Any,Port); 

192.168.0.33 내 컴퓨터의 IP 주소입니다

localEp = new IPEndPoint(IPAddress.Parse("192.168.0.33"),Port); 

에, 그것은 데이터마다 시간을받습니다. 누구나 이유를 설명 할 수 있습니까? IPAddress.any를 사용하고 무선 및 유선 연결에서 수신하는 것이 매우 유용합니다. IPAddress.any는 0.0.0.0과 같으며 MSDN에 따르면 모든 네트워크 인터페이스에서 수신해야합니다.

+2

UDP는 TCP처럼 패킷이 도착한다고 보장하지 않습니다. 흔들린 연결의 효과를 볼 수도 있습니다. – Dervall

+2

wireshark가 패킷을보고 있다면 적어도 NIC가 패킷을 수신한다는 의미입니다. 나도 데이터를 잘 받거나 전혀받지 못한다. 또한 OnRecieve에서 두 번의 try/catch를 사용하는 것이 이상하게 보일 수 있다고 덧붙이고 싶습니다. 그러나 나는 그 시간에 디버깅을하고 있었으므로 무시하려고했습니다. – gcb

답변

1

이러한 문제의 일반적인 원인은 충분히 빠른 패킷 처리가 아닙니다. 그들은 소켓 수신 버퍼를 채우고 커널은 그것들을 버리기 시작합니다.

트래픽 버스트를 수용하려면 소켓 receive buffer size을 늘리십시오. 빠른 소켓 판독 경로에서 불필요한 모든 것을 제거하십시오.

rxData = new byte[nBytesRec]; 

while (!time_to_stop) { 
    int len = socket.Receive(rxData); 
    OnRxBytesEvent(rxData, len); 
} 

귀하의 코드 주석이 멀티 캐스트를 언급 : 은 단순 반복적 인 접근 방식 짖는 소리 대신 스레드 풀에 작업을 고려하십시오. 명시 적으로 group membership을 추가해야하고, 명시 적으로 또는 라우팅 테이블을 통해 결정된대로 인터페이스의 멀티 캐스트 그룹에 합류해야하므로 두 인터페이스의 멀티 캐스트 데이터를 수신하려면 두 개의 소켓이 필요합니다. .

+1

네트워크 프로토콜에 흐름 제어 기능이있어서 수신 버퍼를 너무 많이 채울 수 없습니다. 멀티 캐스팅에 대한 언급은 다른 곳에서 코드를 복사하는 데 있습니다.이 문제는 Ipadress.any를 사용하는 것으로 보입니다. – gcb

+0

흐름 제어, oh my ... "불가능"은 다소 강력한 설명입니다. 가정을 다시 확인하십시오. 'INADDR_ANY'는 아마도 실제 문제와 관련이 없습니다. –

+0

나는 어떤 가정도하고 있지 않다. IPAddress.Any를 사용하는 대신 컴퓨터의 IP 주소에 바인딩하면 작동합니다. 또한, 나는 원래의 질문에서 말했듯이, wireshark에서 무슨 일이 일어나는지 볼 수 있습니다. – gcb

0

방금 ​​같은 문제가 발생하여 timeTolive를 큰 데이터로 설정하여 해결했습니다.

_client = new UdpClient(); 
_client.Client.Bind(new IPEndPoint(IPAddress.Any, targetURI.Port)); 
_client.JoinMulticastGroup(IPAddress.Parse(targetURI.Host) , 250); 
  • 은의 TimeToLive = 250, 그것을 작동합니다.
  • timeToLive = 50, 작동하지 않거나 작동하지 않습니다.
  • timeToLive = none 또는 0, 작동하지 않습니다.
관련 문제