在C#中实现Ping

此博客展示了用C#实现Ping功能的代码。通过创建Socket、构建ICMP包、计算校验和等步骤,实现向指定IP或主机名发送Ping请求,并根据响应情况返回相应结果,如未发现主机、主机无响应、超时等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

using System;
using System.Drawing;
using System.Collections;
using System.Data;
using System.Net;
using System.Net.Sockets;

///		Ping类
public class Ping
{
//声明常量
const int SOCKET_ERROR = -1;
const int ICMP_ECHO = 8;

// 程序入口
public static void Main()
{
	Ping p = new Ping();
	Console.WriteLine("请输入要 Ping 的IP或者主机名字:");
	string MyUrl = Console.ReadLine();
	Console.WriteLine("正在 Ping " + MyUrl + " ……");
	Console.Write(p.PingHost(MyUrl));
}

public string PingHost(string host)
{
	// 声明 IPHostEntry
	IPHostEntry serverHE, fromHE;
	int nBytes = 0;
	int dwStart = 0, dwStop = 0;

	//初始化ICMP的Socket
	Socket socket =
		new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
       socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 1000);
	// 得到Server EndPoint
	try
	{
		serverHE = Dns.GetHostByName(host);
	}
	catch(Exception)
	{

		return "没有发现主机";
	}

	// 把 Server IP_EndPoint转换成EndPoint
	IPEndPoint ipepServer = new IPEndPoint(serverHE.AddressList[0], 0);
	EndPoint epServer = (ipepServer);

	// 设定客户机的接收Endpoint
	fromHE = Dns.GetHostByName(Dns.GetHostName());
	IPEndPoint ipEndPointFrom = new IPEndPoint(fromHE.AddressList[0], 0);
	EndPoint EndPointFrom = (ipEndPointFrom);

	int PacketSize = 0;
	IcmpPacket packet = new IcmpPacket();

	// 构建要发送的包
	packet.Type = ICMP_ECHO; //8
	packet.SubCode = 0;
	packet.CheckSum = UInt16.Parse("0");
	packet.Identifier   = UInt16.Parse("45");
	packet.SequenceNumber  = UInt16.Parse("0");
	int PingData = 32; // sizeof(IcmpPacket) - 8;
	packet.Data = new Byte[PingData];

	// 初始化Packet.Data
	for (int i = 0; i < PingData; i++)
	{
		packet.Data[i] = (byte)'#';
	}

	//Variable to hold the total Packet size
	PacketSize = PingData + 8;
	Byte [] icmp_pkt_buffer = new Byte[ PacketSize ];
	Int32 Index = 0;
	//Call a Method Serialize which counts
	//The total number of Bytes in the Packet
	Index = Serialize(
		packet,
		icmp_pkt_buffer,
		PacketSize,
		PingData );
	//Error in Packet Size
	if( Index == -1 )
	{
		 return "Error Creating Packet";
	}

	// convert into a UInt16 array

	//Get the Half size of the Packet
	Double double_length = Convert.ToDouble(Index);
	Double dtemp = Math.Ceiling( double_length / 2);
	int cksum_buffer_length = Convert.ToInt32(dtemp);
	//Create a Byte Array
	UInt16 [] cksum_buffer = new UInt16[cksum_buffer_length];
	//Code to initialize the Uint16 array
	int icmp_header_buffer_index = 0;
	for( int i = 0; i < cksum_buffer_length; i++ )
	{
		cksum_buffer[i] =
			BitConverter.ToUInt16(icmp_pkt_buffer,icmp_header_buffer_index);
		icmp_header_buffer_index += 2;
	}
	//Call a method which will return a checksum
	UInt16 u_cksum = checksum(cksum_buffer, cksum_buffer_length);
	//Save the checksum to the Packet
	packet.CheckSum  = u_cksum;

	// Now that we have the checksum, serialize the packet again
	Byte [] sendbuf = new Byte[ PacketSize ];
	//again check the packet size
	Index = Serialize(
		packet,
		sendbuf,
		PacketSize,
		PingData );
	//if there is a error report it
	if( Index == -1 )
	{
		 return "Error Creating Packet";

	}


	dwStart = System.Environment.TickCount; // Start timing
	//send the Packet over the socket
	if ((nBytes = socket.SendTo(sendbuf, PacketSize, 0, epServer)) == SOCKET_ERROR)
	{
		 return "Socket Error: cannot send Packet";
	}
	// Initialize the buffers. The receive buffer is the size of the
	// ICMP header plus the IP header (20 bytes)
	Byte [] ReceiveBuffer = new Byte[256];
	nBytes = 0;
	//Receive the bytes
	bool recd =false ;
	int timeout=0 ;

	//loop for checking the time of the server responding
	while(!recd)
	{
		nBytes = socket.ReceiveFrom(ReceiveBuffer, 256, 0, ref EndPointFrom);
		if (nBytes == SOCKET_ERROR)
		{
			return "主机没有响应" ;

		}
		else if(nBytes>0)
		{
			dwStop = System.Environment.TickCount - dwStart; // stop timing
			 return "Reply from "+epServer.ToString()+" in "
				+dwStop+"ms.  Received: "+nBytes+ " Bytes.";


		}
		timeout=System.Environment.TickCount - dwStart;
		if(timeout>1000)
		{
			return "超时" ;
		}
	}

	//close the socket
	socket.Close();
	return "";
}
/// <summary>
///  This method get the Packet and calculates the total size
///  of the Pack by converting it to byte array
/// </summary>
public static Int32 Serialize(IcmpPacket packet, Byte[] Buffer,
	Int32 PacketSize, Int32 PingData )
{
	Int32 cbReturn = 0;
	// serialize the struct into the array
	int Index=0;

	Byte [] b_type = new Byte[1];
	b_type[0] = (packet.Type);

	Byte [] b_code = new Byte[1];
	b_code[0] = (packet.SubCode);

	Byte [] b_cksum = BitConverter.GetBytes(packet.CheckSum);
	Byte [] b_id = BitConverter.GetBytes(packet.Identifier);
	Byte [] b_seq = BitConverter.GetBytes(packet.SequenceNumber);

	Array.Copy( b_type, 0, Buffer, Index, b_type.Length );
	Index += b_type.Length;

	Array.Copy( b_code, 0, Buffer, Index, b_code.Length );
	Index += b_code.Length;

	Array.Copy( b_cksum, 0, Buffer, Index, b_cksum.Length );
	Index += b_cksum.Length;

	Array.Copy( b_id, 0, Buffer, Index, b_id.Length );
	Index += b_id.Length;

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

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

	cbReturn = Index;
	return cbReturn;
}
/// <summary>
///		This Method has the algorithm to make a checksum
/// </summary>
public static UInt16 checksum( UInt16[] buffer, int size )
{
	Int32 cksum = 0;
	int counter;
	counter = 0;

	while ( size > 0 )
	{
		UInt16 val = buffer[counter];

		cksum += Convert.ToInt32( buffer[counter] );
		counter += 1;
		size -= 1;
	}

	cksum = (cksum >> 16) + (cksum & 0xffff);
	cksum += (cksum >> 16);
	return (UInt16)(~cksum);
}
}
/// 类结束
/// <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 UInt16 CheckSum;   // ones complement checksum of struct
public UInt16 Identifier;      // identifier
public UInt16 SequenceNumber;     // sequence number
public Byte [] Data;

} // class IcmpPacket
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值