设计并实现一个Ping程序,以掌握UDP套接字的使用以及ICMP协议中ECHO报文的发送和接受方法。

设计并实现一个Ping程序,以掌握UDP套接字的使用以及ICMP协议中ECHO报文的发送和接受方法。,第1张

import java.io.*

import java.net.*

import java.nio.channels.*

import java.util.*

import java.util.regex.*

public class Ping {

static int DAYTIME_PORT = 13

static int port = DAYTIME_PORT

static class Target {

InetSocketAddress address

SocketChannel channel

Exception failure

long connectStart

long connectFinish = 0

boolean shown = false

Target(String host) {

try {

address = new InetSocketAddress(InetAddress.getByName(host),

port)

} catch (IOException x) {

failure = x

}

}

void show() {

String result

if (connectFinish != 0)

result = Long.toString(connectFinish - connectStart) + "ms"

else if (failure != null)

result = failure.toString()

else

result = "Timed out"

System.out.println(address + " : " + result)

shown = true

}

}

static class Printer extends Thread {

LinkedList pending = new LinkedList()

Printer() {

setName("Printer")

setDaemon(true)

}

void add(Target t) {

synchronized (pending) {

pending.add(t)

pending.notify()

}

}

public void run() {

try {

for () {

Target t = null

synchronized (pending) {

while (pending.size() == 0)

pending.wait()

t = (Target) pending.removeFirst()

}

t.show()

}

} catch (InterruptedException x) {

return

}

}

}

static class Connector extends Thread {

Selector sel

Printer printer

LinkedList pending = new LinkedList()

Connector(Printer pr) throws IOException {

printer = pr

sel = Selector.open()

setName("Connector")

}

void add(Target t) {

SocketChannel sc = null

try {

sc = SocketChannel.open()

sc.configureBlocking(false)

boolean connected = sc.connect(t.address)

t.channel = sc

t.connectStart = System.currentTimeMillis()

if (connected) {

t.connectFinish = t.connectStart

sc.close()

printer.add(t)

} else {

synchronized (pending) {

pending.add(t)

}

sel.wakeup()

}

} catch (IOException x) {

if (sc != null) {

try {

sc.close()

} catch (IOException xx) {

}

}

t.failure = x

printer.add(t)

}

}

void processPendingTargets() throws IOException {

synchronized (pending) {

while (pending.size() >0) {

Target t = (Target) pending.removeFirst()

try {

t.channel.register(sel, SelectionKey.OP_CONNECT, t)

} catch (IOException x) {

t.channel.close()

t.failure = x

printer.add(t)

}

}

}

}

void processSelectedKeys() throws IOException {

for (Iterator i = sel.selectedKeys().iterator()i.hasNext()) {

SelectionKey sk = (SelectionKey) i.next()

i.remove()

Target t = (Target) sk.attachment()

SocketChannel sc = (SocketChannel) sk.channel()

try {

if (sc.finishConnect()) {

sk.cancel()

t.connectFinish = System.currentTimeMillis()

sc.close()

printer.add(t)

}

} catch (IOException x) {

sc.close()

t.failure = x

printer.add(t)

}

}

}

volatile boolean shutdown = false

void shutdown() {

shutdown = true

sel.wakeup()

}

public void run() {

for () {

try {

int n = sel.select()

if (n >0)

processSelectedKeys()

processPendingTargets()

if (shutdown) {

sel.close()

return

}

} catch (IOException x) {

x.printStackTrace()

}

}

}

}

public static void main(String[] args) throws InterruptedException,

IOException {

args = new String[] { "8888", "192.168.10.193" }

if (args.length <1) {

System.err.println("Usage: java Ping [port] host...")

return

}

int firstArg = 0

if (Pattern.matches("[0-9]+", args[0])) {

port = Integer.parseInt(args[0])

firstArg = 1

}

Printer printer = new Printer()

printer.start()

Connector connector = new Connector(printer)

connector.start()

LinkedList targets = new LinkedList()

for (int i = firstArgi <args.lengthi++) {

Target t = new Target(args[i])

targets.add(t)

connector.add(t)

}

Thread.sleep(2000)

connector.shutdown()

connector.join()

for (Iterator i = targets.iterator()i.hasNext()) {

Target t = (Target) i.next()

if (!t.shown)

t.show()

}

}

}

二、JAVA调用外部EXE实现PING功能

import java.io.*

import java.lang.*

public class Ping {

public Ping() {

}

public static void main(String args[])

{

if (args.length <1)

{

System.out.println("syntax Error!")

}

else

{

String line = null

try

{

Process pro = Runtime.getRuntime().exec("ping " + args[0])

BufferedReader buf = new BufferedReader(new InputStreamReader(pro.getInputStream()))

while((line = buf.readLine()) != null)

System.out.println(line)

}

catch(Exception ex)

{

System.out.println(ex.getMessage())

}

}

}

}

C#:

class Ping

{

const int SOCKET_ERROR = -1

const int ICMP_ECHO = 8

public static OnPingLog onpinglog=null

protected static PingLog plog=new PingLog()

public static void WirteLog(string s)

{

Ping.plog.writelog(s)

if(onpinglog!=null)

{

onpinglog(s)

}

}

public static UInt16 checksum(UInt16[] buffer,int size)

{

Int32 cksum = 0

int counter = 0

while (size>0)

{

UInt16 val = buffer[counter]

cksum += Convert.ToInt32(buffer[counter])

counter++

size--

}

cksum = (cksum >> 16)+(cksum & 0xffff)

cksum += (cksum >> 16)

return (UInt16)(~cksum)

}

public static Int32 Serialize( IcmpPacket packet,Byte[] Buffer,Int32 PacketSize,Int32 PingData)

{

Int32 cbReturn = 0

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

Array.Copy(packet.Data,0,Buffer,Index,PingData)

Index += PingData

if(Index != PacketSize)

{

cbReturn = -1

return cbReturn

}

cbReturn = Index

return cbReturn

}

public static void PingHost(string host)

{

IPHostEntry serverHE,fromHE

int nBytes = 0

int dwStart = 0

int dwStop = 0

Socket socket = new Socket(AddressFamily.InterNetwork,SocketType.Raw,ProtocolType.Icmp)

try

{

//serverHE = Dns.GetHostByName(host)

serverHE = Dns.GetHostByAddress(host.Split(':')[0])

}

catch(Exception)

{

WirteLog("目标主机" + host + "不存在")

return

}

//测试端口

// int portNum = 0

// if(host.Split(':').Length >1)

// {

//portNum = Int32.Parse(host.Split(':')[1])

// }

// else

// {

//portNum = 13

// }

// string hostName = host.Split(':')[0]

// try

// {

//TcpClient client = new TcpClient(hostName, portNum)

//client.Close()

// }

// catch (Exception e)

// {

//WirteLog("错误:" + host + e.Message + "")

//socket.Close()

//return

// }

IPEndPoint ipepServer

if(host.Split(':').Length >1)

{

ipepServer = new IPEndPoint(serverHE.AddressList[0],Int32.Parse(host.Split(':')[1]))

}

else

{

ipepServer = new IPEndPoint(serverHE.AddressList[0],0)

}

EndPoint epServer = (ipepServer)

fromHE = Dns.GetHostByName(Dns.GetHostName())

IPEndPoint ipEndPointFrom

if(host.Split(':').Length == 1)

{

ipEndPointFrom = new IPEndPoint(fromHE.AddressList[0],0)

}

else

{

ipEndPointFrom = new IPEndPoint(fromHE.AddressList[0],Int32.Parse(host.Split(':')[1]))

}

EndPoint EndPointFrom = (ipEndPointFrom)

int PacketSize = 0

IcmpPacket packet = new IcmpPacket()

packet.Type = ICMP_ECHO

packet.SubCode = 0

packet.CheckSum = UInt16.Parse("0")

packet.Identifier = UInt16.Parse("45")

packet.SequenceNumber = UInt16.Parse("0")

int PingData = 32

packet.Data = new Byte[PingData]

for(int i=0i<PingDatai++)

{

packet.Data[i] = (byte)'#'

}

PacketSize = PingData + 8

Byte[] icmp_pkt_buffer = new Byte[PacketSize]

Int32 Index = 0

Index = Serialize(packet,icmp_pkt_buffer,PacketSize,PingData)

if(Index == -1)

{

WirteLog("错误(Error in Making Packet)")

return

}

Double double_length = Convert.ToDouble(Index)

Double dtemp = Math.Ceiling(double_length/2)

int cksum_buffer_length = Convert.ToInt32(dtemp)

UInt16[] cksum_buffer = new UInt16[cksum_buffer_length]

int icmp_header_buffer_index = 0

for(int i=0i<cksum_buffer_lengthi++)

{

cksum_buffer[i] = BitConverter.ToUInt16(icmp_pkt_buffer,icmp_header_buffer_index)

icmp_header_buffer_index += 2

}

UInt16 u_cksum = checksum(cksum_buffer,cksum_buffer_length)

packet.CheckSum = u_cksum

Byte[] sendbuf = new Byte[PacketSize]

Index = Serialize(packet,sendbuf,PacketSize,PingData)

if(Index == -1)

{

WirteLog("错误(Error in Making Packet)")

return

}

dwStart = System.Environment.TickCount

if((nBytes = socket.SendTo(sendbuf,PacketSize,0,epServer)) == SOCKET_ERROR)

{

WirteLog("错误(Socket Error can not Sending Packet)")

}

Byte[] ReceiveBuffer = new Byte[256]

nBytes = 0

bool recd = false

int timeout = 0

while(!recd)

{

nBytes = socket.ReceiveFrom(ReceiveBuffer,256,0,ref EndPointFrom)

if(nBytes == SOCKET_ERROR)

{

WirteLog("错误(远程主机没有响应)")

recd = true

break

}

else if(nBytes > 0)

{

dwStop = System.Environment.TickCount - dwStart

WirteLog("成功(Reply from"+epServer.ToString()+":bytes = "+ nBytes.ToString()+"time = "+dwStop +"ms)")

recd = true

break

}

timeout = System.Environment.TickCount - dwStart

if(timeout > 1000)

{

WirteLog("错误(超时)")

recd = true

}

}

socket.Close()

}

}

public class IcmpPacket

{

public IcmpPacket()

{

//

// TODO: 在此处添加构造函数逻辑

//

}

public Byte Type

public Byte SubCode

public UInt16 CheckSum

public UInt16 Identifier

public UInt16 SequenceNumber

public Byte[] Data

}

ping使用的是ICMP协议,而Qt中没有现成的处理ICMP协议的类。所以使用Qt就是用来做界面的,ping的功能是用C来完成的。

给你两个思路:

思路1. 使用linux系统命令ping。 你的程序中fork一个新进程,在新进程里面通过system("ping xxxx")的方式来调用系统ping命令,然后把ping命令的输出通过管道输入到你的程序中来。

思路2. 从网上找一个c语言写的现成的ping源代码,有很多的。看懂了以后,把ping源代码集成到你的代码中(把ping的main函数改名字,变成你的内部函数),注意输出数据。这样你的程序就有个ping功能。因为Ping会堵塞的,最好不要在画面线程中运行。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/11104754.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-13
下一篇 2023-05-13

发表评论

登录后才能评论

评论列表(0条)

保存