Fragensteller
c# UDP Broadcast und ICMP (Host unreachable)

Frage
-
Hallo!
Ich habe ein Problem mit meinem Programm. Ich sende einen Broadcast per UDP um nach bstimmten Geräten zu suchen. Das funktionierte bisher auch super. Jetzt hängt hier ein Beamer im Netz und schickt auf meine Anfrage ein ICMP-Paket "Destination Host is unreachable". Das wäre nicht so schlimm, wenn bei Win < Vista (XP, 2003 Server ..) nicht mein lauschender Socket mit einer Exception beendet würde. Ich habe versucht, den Socket, wenn ich die Exception bekomme, wieder zu aktivieren. Das funktioniert aber nicht.
Hat jemand eine Idee, wie ich dieses Problem löse? Warum ist das bei Windows Vista und 7 anders?
Hier noch etwas Quellcode:
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Net;
using
System.Net.Sockets;
using
System.Text;
using
System.Threading;
namespace
MyNamespace
{
class
SockReadData
{
public
Socket soc;
public
SockRead sockRead;
public
byte
[] endBuf;
public
byte
[] readBuf;
public
EndPoint endPointFrom;
public
static
int
iReadBufMax = 4096;
public
SockReadData(SockRead theSockRead)
{
soc =
null
;
sockRead = theSockRead;
endBuf =
new
byte
[0];
readBuf =
new
byte
[iReadBufMax];
endPointFrom = (EndPoint)
new
IPEndPoint(
new
IPAddress(0), 0);
}
public
void
Clear()
{
soc =
null
;
sockRead =
null
;
endBuf =
new
byte
[0];
readBuf =
new
byte
[0];
endPointFrom = (EndPoint)
new
IPEndPoint(
new
IPAddress(0), 0);
}
}
class
SockRead
{
private
int
_iPort;
protected
Socket _soc;
public
List<SockReadData> _list;
public
bool
_stopRecieving =
false
;
private
Timer _recieveTimer;
private
int
_recTimeout = 3000;
public
string
service =
"noScan"
;
public
SockRead(
int
iPort,
int
timeout)
{
_list =
new
List<SockReadData>();
_iPort = iPort;
_recTimeout = timeout;
_recieveTimer =
new
Timer(
new
TimerCallback(stopRec),
null
, _recTimeout, 0);
}
public
void
Stop()
{
if
(_soc ==
null
)
return
;
_soc.Shutdown(SocketShutdown.Both);
_soc.Close();
_soc =
null
;
}
/// <summary>
/// sendet ein SNMP-Packet und startet das Empfangen von Antworten
/// </summary>
/// <param name="localIP">IP-Adresse, von welcher gesendet werden soll</param>
/// <returns>Boolean: true, wenn keine Fehler auftraten, sonst false</returns>
public
bool
Start(IPAddress localIP)
{
//neue Instanz von SockReadDate, wird die Antworten empfangen
SockReadData sockReadData =
new
SockReadData(
this
);
string
strErr;
// Empfangen ist schon gestartet muß erst gestoppt werden
if
(_soc !=
null
)
return
false
;
try
{
//Socket erstellen und konfigurieren
_soc =
new
Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
sockReadData.soc = _soc;
_soc.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast,
true
);
_soc.Bind(
new
IPEndPoint(localIP, _iPort));
Thread.Sleep(800);
sockReadData.endPointFrom =
new
IPEndPoint(IPAddress.Broadcast, _iPort);
_soc.BeginReceiveFrom(sockReadData.readBuf, 0, SockReadData.iReadBufMax, SocketFlags.None,
ref
sockReadData.endPointFrom,
new
AsyncCallback(beginRead), sockReadData);
//ReciveTimeout-Timer starten
_recieveTimer.Change(_recTimeout, 0);
return
true
;
}
catch
(System.Exception exc)
{
strErr = exc.ToString();
}
return
false
;
}
public
static
void
beginRead(IAsyncResult ar)
{
SockReadData readData = (SockReadData)ar.AsyncState;
SockReadData readDataNew =
new
SockReadData(readData.sockRead);
readDataNew.soc = readData.soc;
EndPoint endPoint = (EndPoint)
new
IPEndPoint(
new
IPAddress(0), 0);
string
strErr =
""
;
int
idx;
int
iRead;
try
{
iRead = readData.soc.EndReceiveFrom(ar,
ref
readData.endPointFrom);
readData.endBuf =
new
byte
[iRead];
for
(idx = 0; idx < iRead; idx++) { readData.endBuf[idx] = readData.readBuf[idx]; }
readData.readBuf =
null
;
// wieder zum einlesen vorbereiten;
readDataNew =
new
SockReadData(readData.sockRead);
readDataNew.soc = readData.soc;
readDataNew.endPointFrom =
new
IPEndPoint(IPAddress.Broadcast, readDataNew.sockRead._iPort);
readData.soc.BeginReceiveFrom(readDataNew.readBuf, 0, SockReadData.iReadBufMax, SocketFlags.None,
ref
readDataNew.endPointFrom,
new
AsyncCallback(beginRead), readDataNew);
readData.sockRead.Add(readData);
}
catch
(System.Exception exc)
{
strErr = exc.ToString();
}
}
public
void
Add(SockReadData sockReadData)
{
_list.Add(sockReadData);
//Timer zuruecksetzen
if
(service ==
"scan"
)
_recieveTimer.Change(_recTimeout, 0);
}
public
void
stopRec(
object
sender)
{
_stopRecieving =
true
;
}
public
bool
Send(
byte
[] byData)
{
string
strErr =
""
;
if
(_soc ==
null
)
return
false
;
try
{
int
iRet = _soc.SendTo(byData, SocketFlags.None,
new
IPEndPoint(IPAddress.Broadcast, _iPort));
}
catch
(System.Exception exc)
{
strErr = exc.ToString();
}
return
false
;
}
}
}
Vielen Dank schon mal für eure zahlreichen Antworten ;o)
Viele Grüße
André Grimm- Bearbeitet Robert BreitenhoferModerator Dienstag, 12. Juli 2011 15:48 Formatierung
- Verschoben Robert BreitenhoferModerator Dienstag, 12. Juli 2011 15:51 C# - Network Programmierung (aus:.NET Framework)