View Full Version : 请微软老师解答:Windows Vista中ICMP协议和XP比有改动吗?


heh2007
04-02-2007, 09:04 AM
开发工具:VS2003 .NET FrameWork1.1
调用下列的SlpPing类的应用程序在Windows XP/2000中执行正常,但在Windows
Vista里总是出现远程节点无应答的错误(Debug时总出现<Request timed out.
m_sHostToPing:192.168.1.1>),为了能在Windows Vista中能执行,下列有关ICMP协议如何修改??

例:SlpPing slpPing = new SlpPing(“192.168.1.1”);
bool bSts = slpPing.PingHost();
/// <summary>
/// Class that ping the specified host
/// </summary>
public class SlpPing
{

/// <summary>
/// Constructor
/// </summary>
public SlpPing(string strHostToPing)
{
m_sHostToPing = strHostToPing;
}

//Declare some Constant Variables
private const int SOCKET_ERROR = -1;
private const int ICMP_ECHO = 8;
private const int ICMP_PACKDATA_SIZE = 32;
private const int MAX_PACKET_SIZE = 65535;

private string m_sHostToPing; // Host to ping

private const int nPingTimeout = 1000; // Timeout
private int nPingCount = 1; // Ping count
private long lngPacketsSent = 0;
private long lngPacketsReceived = 0;

public bool PingHost()
{
bool bSts = false;
int nBytesReceived = 0;
int nStart = 0, nStop = 0;
int nLoop = 0;
int iResult = 0;
int iPacketSize = ICMP_PACKDATA_SIZE + 8;
long lngTotalTransmitTime = 0;
try
{
byte[] byteSendBuffer = new byte[iPacketSize];
// Construct the packet to send
bSts = DoIcmpPacketData(byteSendBuffer);
IPAddress hostadd = IPAddress.Parse(m_sHostToPing);
EndPoint epServer = new IPEndPoint(hostadd, 0);
IPHostEntry pingSource = Dns.GetHostByName(Dns.GetHostName());
EndPoint endPointFrom = new IPEndPoint(pingSource.AddressList[0],0);
Debug.WriteLine(string.Format("\nPinging {0} [{1}] with {2} bytes of
data:\n", m_sHostToPing,
((IPEndPoint)epServer).Address.ToString(), ICMP_PACKDATA_SIZE));

//Loop the ping
int nMinTransmitTime = int.MaxValue, nMaxTransmitTime = int.MinValue;
do
{
bool bReceived = false ;

//Initialize a Socket of the Type ICMP
Socket pingSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Raw, ProtocolType.Icmp);
//Set socket timeout, but this doesn't seem to work...
pingSocket.SetSocketOption( SocketOptionLevel.Socket,
SocketOptionName.ReceiveTimeout, (int) nPingTimeout);
pingSocket.SetSocketOption( SocketOptionLevel.Socket,
SocketOptionName.SendTimeout, (int) nPingTimeout);

// Initialize the buffers. The receive buffer is the size of the
// ICMP header plus the IP header (20 bytes)
byte [] ReceiveBuffer = new byte[MAX_PACKET_SIZE];

nStart = System.Environment.TickCount; // Start timing
//Gather stats
lngPacketsSent ++;
//send the Pack over the socket
iResult = pingSocket.SendTo(byteSendBuffer, iPacketSize,
SocketFlags.None , epServer);
Debug.WriteLine (string.Format("Send to {0}
m_sHostToPing:{1}",((IPEndPoint)epServer).Address.ToString(), m_sHostToPing));
if ((iResult) == SOCKET_ERROR)
{
//Debug.WriteLine("Socket Error cannot Send Packet");
}

//Receive the bytes
nBytesReceived = 0;
//loop while waiting checking the time of the server responding
while(!bReceived)
{
try
{
nBytesReceived = pingSocket.ReceiveFrom(ReceiveBuffer,
MAX_PACKET_SIZE, SocketFlags.None, ref endPointFrom);
}
catch
{
Debug.WriteLine (string.Format("Request timed out.
m_sHostToPing:{0}", m_sHostToPing));
bReceived = false;
break;
}
if (nBytesReceived == SOCKET_ERROR)
{
Debug.WriteLine(string.Format("Host not Responding.
m_sHostToPing:{0}", m_sHostToPing));
bReceived = false;
break;
}
else if (nBytesReceived > 0)
{
if (((IPEndPoint)endPointFrom).Address.ToString() == m_sHostToPing)
{
bReceived = true;
nStop = System.Environment.TickCount - nStart; // stop timing

//Check for timeout
if ( nStop > nPingTimeout)
{
Debug.WriteLine (string.Format("Request timed out.
m_sHostToPing:{0}", m_sHostToPing));
bReceived = false;
System.Threading.Thread.Sleep(System.TimeSpan.FromMilliseconds(1000));
break;
}
if (nStop < 10)
{
Debug.WriteLine(string.Format("Reply from {0}: bytes: {1}
time:<10ms m_sHostToPing:{2}", ((IPEndPoint)endPointFrom).Address.ToString(),
nBytesReceived - 28, m_sHostToPing));
}
else
{
Debug.WriteLine(string.Format("Reply from {0}: bytes: {1} time:
{2}ms m_sHostToPing:{3}", ((IPEndPoint)endPointFrom).Address.ToString(),
nBytesReceived - 28, nStop, m_sHostToPing));
}
nPingCount = 1;
break;
}
else
{ //If received data from other host, dispose it.
//Debug.WriteLine(string.Format("Reply from {0}: bytes: {1}
time:<10ms m_sHostToPing:{2}", ((IPEndPoint)endPointFrom).Address.ToString(),
nBytesReceived - 28, m_sHostToPing));
bReceived = false;
}
}
}//while

//Gather stats
if (bReceived)
{
lngPacketsReceived++;
lngTotalTransmitTime += nStop;
if (nStop > nMaxTransmitTime) nMaxTransmitTime = nStop;
if (nStop < nMinTransmitTime) nMinTransmitTime = nStop;
}
nLoop++;

if (bReceived && nLoop < nPingCount) //not last ping
{
System.Threading.Thread.Sleep(System.TimeSpan.FromMilliseconds(1000));
}
//close the socket
pingSocket.Shutdown(SocketShutdown.Both);
pingSocket.Close();
} while (nLoop < nPingCount); //Do

}
catch
{
lngPacketsSent = -1;
}
return (lngPacketsSent == lngPacketsReceived);
}

/// <summary>
/// This method is used to construct the packet to send
/// </summary>
private static bool DoIcmpPacketData(byte[] byteSendBuffer)
{
bool bSts = false;
int nPacketSize = 0;
IcmpPacket PingPacket = new IcmpPacket();

// Construct the packet to send
PingPacket.Type = ICMP_ECHO; //8
PingPacket.SubCode = 0;
PingPacket.CheckSum = UInt16.Parse("0");
PingPacket.Identifier = UInt16.Parse("45");
PingPacket.SequenceNumber = UInt16.Parse("0");
PingPacket.Data = new Byte[ICMP_PACKDATA_SIZE];
//Initialize the Packet.Data
for (int nCount = 0; nCount < ICMP_PACKDATA_SIZE; nCount++)
{
PingPacket.Data[nCount] = (byte)'#';
}

//Variable to hold the total Packet size
nPacketSize = ICMP_PACKDATA_SIZE + 8;
byte [] bytPktBuffer = new byte[nPacketSize];
int nResult = 0;

//Call a Method Serialize which counts
//The total number of Bytes in the Packet
nResult = Serialize(PingPacket, bytPktBuffer, nPacketSize,
ICMP_PACKDATA_SIZE );

//Error in Packet Size
if( nResult == -1 )
{
//Debug.WriteLine("Error in Making Packet");
return bSts;
}

// now get this critter into a ushort array
ushort [] cksum_buffer = new ushort[Convert.ToInt32( Math.Ceiling(
Convert.ToDouble(nResult) / 2))];

//Code to initialize the ushort array
int ncmp_header_buffer_index = 0;
for( int nCount = 0; nCount < cksum_buffer.Length; nCount++ )
{
cksum_buffer[nCount] = BitConverter.ToUInt16(bytPktBuffer,
ncmp_header_buffer_index);
ncmp_header_buffer_index += 2;
}

//Call a method which will return a checksum
//Save the checksum to the Packet
PingPacket.CheckSum = CheckSum(cksum_buffer);

// Now that we have the checksum, serialize the packet again
nResult = Serialize(PingPacket, byteSendBuffer, nPacketSize,
ICMP_PACKDATA_SIZE );
//if there is a error report it
if( nResult == -1 )
{
//Debug.WriteLine("Error in Making Packet");
return bSts;
}
bSts = true;
return bSts;
}

/// <summary>
/// This method is used to get the Packet and calculates the total size
/// of the Pack by converting it to byte array
/// </summary>
private static int Serialize(IcmpPacket ThisPacket, byte[] Buffer, int
PacketSize, int PingData )
{
int nReturn = 0;
// serialize the struct into the array
int nIndex = 0;

byte [] b_type = new byte[1];
b_type[0] = ThisPacket.Type;

byte [] b_code = new byte[1];
b_code[0] = ThisPacket.SubCode;

byte [] b_cksum = BitConverter.GetBytes(ThisPacket.CheckSum);
byte [] b_id = BitConverter.GetBytes(ThisPacket.Identifier);
byte [] b_seq = BitConverter.GetBytes(ThisPacket.SequenceNumber);

// Debug.WriteLine("Serialize type ");
Array.Copy( b_type, 0, Buffer, nIndex, b_type.Length );
nIndex += b_type.Length;

// Debug.WriteLine("Serialize code ");
Array.Copy( b_code, 0, Buffer, nIndex, b_code.Length );
nIndex += b_code.Length;

// Debug.WriteLine("Serialize cksum ");
Array.Copy( b_cksum, 0, Buffer, nIndex, b_cksum.Length );
nIndex += b_cksum.Length;

// Debug.WriteLine("Serialize id ");
Array.Copy( b_id, 0, Buffer, nIndex, b_id.Length );
nIndex += b_id.Length;

Array.Copy( b_seq, 0, Buffer, nIndex, b_seq.Length );
nIndex += b_seq.Length;

// copy the data
Array.Copy( ThisPacket.Data, 0, Buffer, nIndex, PingData );
nIndex += PingData;
if( nIndex != PacketSize/* sizeof(IcmpPacket) */)
{
nReturn = -1;
return nReturn;
}

nReturn = nIndex;
return nReturn;
}
/// <summary>
/// Checksum -
/// Algorithm to create a checksup for a buffer
/// </summary>
private static ushort CheckSum( ushort[] BufferToChecksum )
{
int nCheckSum = 0;

for (uint nCount = 0; nCount < BufferToChecksum.Length; nCount++)
{
nCheckSum += Convert.ToInt32( BufferToChecksum[nCount] );
}

nCheckSum = (nCheckSum >> 16) + (nCheckSum & 0xffff);
nCheckSum += (nCheckSum >> 16);
return (ushort)(~nCheckSum);
}

/// <summary>
/// Class that holds the Pack information
/// </summary>
public class IcmpPacket
{
public byte Type; // type of message
public byte SubCode; // type of sub code
public ushort CheckSum; // ones complement checksum of struct
public ushort Identifier; // identifier
public ushort SequenceNumber; // sequence number
public byte[] Data; // byte array of data
} // class IcmpPacket
}

v-jicwan@prcvap.microsoft.com
04-03-2007, 10:15 AM
ã

ӭMSDNύ⣬ǽᾡ

Windows Server 2003ϲһṩij򣬷PingHostķֵΪfalse,ٴԷִд׳쳣
nBytesReceived = pingSocket.ReceiveFrom(ReceiveBuffer, MAX_PACKET_SIZE, SocketFlags.None, ref endPointFrom);

쳣ϢA connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond

ٵһ´룬ΪWindows XP/2000ICMPЭWindows VistaӦһġκ⣬ͨMSDNǽ

Jasson Wang
߼ֹ֧ʦ
΢ȫ֧
---------------------------------------------------------------------------------------
ǵķʱ䣺һ9:00-18:00ڼճ⣩ǽգ48СʱṩʼӦһо⡣΢鼼֧Ϣʣhttp://support.microsoft.com/gp/newsgroupsupport/zh-cn.

ʱĶʹáظ(Reply to Group)⽫ûл档
---------------------------------------------------------------------------------------
ԡ״ṩûκεͬʱҲûκȨ

heh2007
04-04-2007, 04:54 AM
微软老师:

您好!

是的,谢谢您的答复。
问题是:同样的程序在Windows XP/2000测试中能通过。为何在Windows Vista中不能通过?
在Windows Vista中在.Net FrameWork1.1上怎样在程序中进行Ping操作?
盼望在万忙中给于解答!

提出此问题的背景是这样的:
我公司的通讯软件由于回避Windows XP SP2(不成功TCP连接的限制10个)
的限制所以增加了SlpPing的类,在尝试TCP连接前先实行Ping操作。如Ping成功
再进行TCP连接的操作。在Windows2000/XP测试都成功。此类的原理是去年从网上得到。
但是在Windows Vista平台测试时又发现SlpPing不能正常操作。
如何修改才能成功进行Ping操作。

“v-jicwan@prcvap.microsoft.com”编写:

> 您好:
>
> 欢迎您到MSDN新闻组提交问题,我们将会尽力帮助您。
>
> 我在Windows Server 2003上测试了一下您提供的程序,发现PingHost的返回值为false,跟踪代码调试发现此行代码抛出异常:
> nBytesReceived = pingSocket.ReceiveFrom(ReceiveBuffer, MAX_PACKET_SIZE, SocketFlags.None, ref endPointFrom);
>
> 异常信息:A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
>
> 建议您单步跟踪调试一下代码,我认为Windows XP/2000中ICMP协议与Windows Vista中应该是一样的。如果您有任何问题,请通过MSDN新闻组与我们交流。
>
> Jasson Wang
> 在线技术支持工程师
> 微软全球技术支持中心
> ---------------------------------------------------------------------------------------
> 我们的服务时间:周一至周五9:00-18:00(节假日除外)。我们将在两个工作日(48小时)内提供初始回应,并和您一起研究并解决问题。更多微软新闻组技术支持信息,请访问:http://support.microsoft.com/gp/newsgroupsupport/zh-cn.
>
> 回帖时,请在您的新闻组阅读器中使用“回复组(Reply to Group)”,这将帮助其他用户从您的提问中获益。
> ---------------------------------------------------------------------------------------
> 本贴子以”现状”提供且没有任何担保,同时也没有授予任何权利。
>

秦风意动
04-04-2007, 11:54 AM
有没有考虑.net framework版本的兼容性
1.1 vs 3.0(2.0)

“heh2007”编写:

> 微软老师:
>
> 您好!
>
> 是的,谢谢您的答复。
> 问题是:同样的程序在Windows XP/2000测试中能通过。为何在Windows Vista中不能通过?
> 在Windows Vista中在.Net FrameWork1.1上怎样在程序中进行Ping操作?
> 盼望在万忙中给于解答!
>
> 提出此问题的背景是这样的:
> 我公司的通讯软件由于回避Windows XP SP2(不成功TCP连接的限制10个)
> 的限制所以增加了SlpPing的类,在尝试TCP连接前先实行Ping操作。如Ping成功
> 再进行TCP连接的操作。在Windows2000/XP测试都成功。此类的原理是去年从网上得到。
> 但是在Windows Vista平台测试时又发现SlpPing不能正常操作。
> 如何修改才能成功进行Ping操作。
>
> “v-jicwan@prcvap.microsoft.com”编写:
>
> > 您好:
> >
> > 欢迎您到MSDN新闻组提交问题,我们将会尽力帮助您。
> >
> > 我在Windows Server 2003上测试了一下您提供的程序,发现PingHost的返回值为false,跟踪代码调试发现此行代码抛出异常:
> > nBytesReceived = pingSocket.ReceiveFrom(ReceiveBuffer, MAX_PACKET_SIZE, SocketFlags.None, ref endPointFrom);
> >
> > 异常信息:A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
> >
> > 建议您单步跟踪调试一下代码,我认为Windows XP/2000中ICMP协议与Windows Vista中应该是一样的。如果您有任何问题,请通过MSDN新闻组与我们交流。
> >
> > Jasson Wang
> > 在线技术支持工程师
> > 微软全球技术支持中心
> > ---------------------------------------------------------------------------------------
> > 我们的服务时间:周一至周五9:00-18:00(节假日除外)。我们将在两个工作日(48小时)内提供初始回应,并和您一起研究并解决问题。更多微软新闻组技术支持信息,请访问:http://support.microsoft.com/gp/newsgroupsupport/zh-cn.
> >
> > 回帖时,请在您的新闻组阅读器中使用“回复组(Reply to Group)”,这将帮助其他用户从您的提问中获益。
> > ---------------------------------------------------------------------------------------
> > 本贴子以”现状”提供且没有任何担保,同时也没有授予任何权利。
> >

heh2007
04-04-2007, 12:20 PM
谢谢您的建议。
已在Windows Vista里安装.Net FrameWork1.1.
而且我公司的通讯软件除了这个Ping操作失败外,其他的Tcp通讯和Udp通讯,FTP操作都没有问题。所以只能考虑微软公司在OS升级时增加对IPv6的支持时对ICMP协议可能作了变动。
在Windows Vista中在.Net FrameWork1.1上怎样在程序中进行Ping操作?
盼望微软老师在万忙中给于解答!


“秦风意动”编写:

> 有没有考虑.net framework版本的兼容性
> 1.1 vs 3.0(2.0)
>
> “heh2007”编写:
>
> > 微软老师:
> >
> > 您好!
> >
> > 是的,谢谢您的答复。
> > 问题是:同样的程序在Windows XP/2000测试中能通过。为何在Windows Vista中不能通过?
> > 在Windows Vista中在.Net FrameWork1.1上怎样在程序中进行Ping操作?
> > 盼望在万忙中给于解答!
> >
> > 提出此问题的背景是这样的:
> > 我公司的通讯软件由于回避Windows XP SP2(不成功TCP连接的限制10个)
> > 的限制所以增加了SlpPing的类,在尝试TCP连接前先实行Ping操作。如Ping成功
> > 再进行TCP连接的操作。在Windows2000/XP测试都成功。此类的原理是去年从网上得到。
> > 但是在Windows Vista平台测试时又发现SlpPing不能正常操作。
> > 如何修改才能成功进行Ping操作。
> >
> > “v-jicwan@prcvap.microsoft.com”编写:
> >
> > > 您好:
> > >
> > > 欢迎您到MSDN新闻组提交问题,我们将会尽力帮助您。
> > >
> > > 我在Windows Server 2003上测试了一下您提供的程序,发现PingHost的返回值为false,跟踪代码调试发现此行代码抛出异常:
> > > nBytesReceived = pingSocket.ReceiveFrom(ReceiveBuffer, MAX_PACKET_SIZE, SocketFlags.None, ref endPointFrom);
> > >
> > > 异常信息:A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
> > >
> > > 建议您单步跟踪调试一下代码,我认为Windows XP/2000中ICMP协议与Windows Vista中应该是一样的。如果您有任何问题,请通过MSDN新闻组与我们交流。
> > >
> > > Jasson Wang
> > > 在线技术支持工程师
> > > 微软全球技术支持中心
> > > ---------------------------------------------------------------------------------------
> > > 我们的服务时间:周一至周五9:00-18:00(节假日除外)。我们将在两个工作日(48小时)内提供初始回应,并和您一起研究并解决问题。更多微软新闻组技术支持信息,请访问:http://support.microsoft.com/gp/newsgroupsupport/zh-cn.
> > >
> > > 回帖时,请在您的新闻组阅读器中使用“回复组(Reply to Group)”,这将帮助其他用户从您的提问中获益。
> > > ---------------------------------------------------------------------------------------
> > > 本贴子以”现状”提供且没有任何担保,同时也没有授予任何权利。
> > >

v-jicwan@prcvap.microsoft.com
04-05-2007, 06:39 AM
:

ллķϢ,Ǻ.

Windows VistaϣĬ£WindowsǽֹPingͨWindows VistaĿ򿪷ǽġ߼ѡڴTabҳICMPáťڵĶԻѡAllow incoming echo requestVista˶IPV6֧֣ܴIPV4IPV6֣,Ȼ󵥻ȷϡťɣȻٳʹPingǷ

PingȻĻҪVistaһ汾ˣʹõIJϵͳVista RC 1.0

Jasson Wang
߼ֹ֧ʦ
΢ȫ֧
---------------------------------------------------------------------------------------
ǵķʱ䣺һ9:00-18:00ڼճ⣩ǽգ48СʱṩʼӦһо⡣΢鼼֧Ϣʣhttp://support.microsoft.com/gp/newsgroupsupport/zh-cn.

ʱĶʹáظ(Reply to Group)⽫ûл档
---------------------------------------------------------------------------------------
ԡ״ṩûκεͬʱҲûκȨ

v-jicwan@prcvap.microsoft.com
04-09-2007, 02:51 AM
:

?ʲôҪǰ?

Jasson Wang
߼ֹ֧ʦ
΢ȫ֧
---------------------------------------------------------------------------------------
ǵķʱ䣺һ9:00-18:00ڼճ⣩ǽգ48СʱṩʼӦһо⡣΢鼼֧Ϣʣhttp://support.microsoft.com/gp/newsgroupsupport/zh-cn.

ʱĶʹáظ(Reply to Group)⽫ûл档
---------------------------------------------------------------------------------------
ԡ״ṩûκεͬʱҲûκȨ

v-jicwan@prcvap.microsoft.com
04-10-2007, 02:26 AM
˵:
ʹ.Net 2.0PingWindows XP SP2Windows VistaϿʵֿԲο룺
using System;
using System.Net;
using System.Net.NetworkInformation;
using System.Threading;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
AutoResetEvent waitHandle = new AutoResetEvent(false);
System.Net.NetworkInformation.Ping p = new Ping();
//Ping Yahoo.com
p.PingCompleted += new PingCompletedEventHandler(p_PingCompleted);
p.SendAsync(IPAddress.Parse("216.109.112.135"),null);
//wait 30 seconds
waitHandle.WaitOne(new TimeSpan(0, 0, 5),false);
}

static void p_PingCompleted(object sender, PingCompletedEventArgs e)
{
Console.WriteLine(e.Reply.Status);
}
}
}

heh2007
04-10-2007, 11:04 AM
微软老师:

您好!这几天出差,答复晚了。很抱歉。

谢谢您的指教。

改变下面的防火墙属性已解决。
管理工具-〉高级安全Windows防火墙-〉双击<Windows防火墙属性>
将入站连接 改为阻止-〉允许

非常感谢!

“v-jicwan@prcvap.microsoft.com”编写:

> 补充说明:
> 使用.Net 2.0的Ping类在Windows XP SP2和Windows Vista上可以正常工作,具体的实现可以参考下述代码:
> using System;
> using System.Net;
> using System.Net.NetworkInformation;
> using System.Threading;
>
> namespace ConsoleApplication1
> {
> class Program
> {
> static void Main(string[] args)
> {
> AutoResetEvent waitHandle = new AutoResetEvent(false);
> System.Net.NetworkInformation.Ping p = new Ping();
> //Ping Yahoo.com
> p.PingCompleted += new PingCompletedEventHandler(p_PingCompleted);
> p.SendAsync(IPAddress.Parse("216.109.112.135"),null);
> //wait 30 seconds
> waitHandle.WaitOne(new TimeSpan(0, 0, 5),false);
> }
>
> static void p_PingCompleted(object sender, PingCompletedEventArgs e)
> {
> Console.WriteLine(e.Reply.Status);
> }
> }
> }
>
>