Implement PING with JNI

xiaoxiao2021-03-06  63

JDK does not provide a class that accesss the Raw Socket, two methods for implementing ping in Java:

Call the PING program comes with the operating system, as follows: / ** * ping an implementation, call the operating system's ping command * / public static int ping (String host) {string system = (String) (System.getProperty Os.name "). ToolowerCase (); string command =" "; if (System.indexof (" win ")! = -1) {Command =" ping -w 500 " host; // Set 500 ms Timeout} else IF ("Linux")! = -1) {Command = "ping -t 4" host; // ping four times} else {Command = "ping" host;} int minTime = Integer.MAX_VALUE, curTime; try {Process process = Runtime.getRuntime () exec ( "ping" host);. BufferedReader in = new BufferedReader (new InputStreamReader (process.getInputStream ())); String line = null ; Int count = 10, index; // Up to read only 10 lines while ((line = in.readLine ())! = Null && count--! = 0) {line = line.tolowercase (); if (((((" = line.indexof ("time")))! = -1) {byte [] buf = line.getbytes (); int start = 0, end = buf.length, i, j; for (i = index 4; I

Write a PING class first, contain local methods pingcore (..)

Package zzzhc.net;

/ ** * @Author zzzhc * / public class ping {

Private string host;

Private Int Timeout = 1000; // mm

Public ping (string host) {this.host = Host;}

Public ping (string host, int today) {this (host); this.timeout = timeout;}

/ ** * * @return ping time * / public int ping () {return pingcore (Host, Timeout);}

/ ** * * @Param host * @Param timeout * @return ping time * / public static int ping (string host, int timeout) {return pingcore;}

Private static native Int pingcore;

/ ** * @Return Returns the host. * / Public string gethost () {Return Host;}

/ ** * @Param Host * The host to set. * / Public void setost (string host) {this.host = host;}

/ ** * @Return Returns the timeout. * / Public int gettimeout () {return timeout;}

/ ** * @Param Timeout * The timeout to set. * / Public void settimeout (int Timeout) {this.timeout = timeout;}

Public static void main (string [] args) {final ping ping = new ping ("192.168.1.1"); System.out.Println ("Time =" ping.ping ());}

Static {system.loadLibrary ("ping");}} To switch to the CLASSES directory: execute javah zzzhc.net.ping under Console get zzzhc_net_ping.h, then implement this header file, generate a DLL under VC Newly built an empty DLL project, join the header file zzzhc_net_ping.h, create a new zzzhc_NET_PING.C file, implementing the ping C source code is easy to find, just in the zzzhc_net_ping.c file, just simply call it, the code: ping C Source code , Forget where it is found, small modified header file //// ping.h // # include #include #include #include #ifdef_msc_ver # prgma Comment (Lib, "WS2_32.LIB" # Endif # Pragma Pack (1) #define ICMP_ECHOREPLY 0 # define ICMP_ECHOREQ 8

// IP Header - RFC 791typedef struct tagIPHDR {unsigned char VIHL; // Version and IHL unsigned char TOS; // Type Of Service short TotLen; // Total Length short ID; // Identification short FlagOff; // Flags and Fragment Offset unsigned char TTL; // Time To Live unsigned char Protocol; // Protocol unsigned short Checksum; // Checksum struct in_addr iaSrc; // Internet Address - Source struct in_addr iaDst; // Internet Address - Destination} iPHDR, * PIPHDR;

// ICMP Header - RFC 792typedef struct tagICMPHDR {unsigned char Type; // Type unsigned char Code; // Code u_short Checksum; // Checksum u_short ID; // Identification u_short Seq; // Sequence unsigned char Data; // Data} ICMPHDR, * PICMPHDR;

#define Req_DataSize 32 // Echo Request Data Size

// ICMP Echo RequestTypef struct timechorequest {icmphdr icmphdr; dword dwtime; unsigned char cdata [req_datasize];} echorequest, * pechorequest;

// ICMP Echo replytypedPedef struct timechoreply {iphdr iphdr; echorequest echorequest; unsigned char cfiller [256];} echoreply, * pechoreply;

INT ping (lpcstr pstrhost, int timeout); # pragma pack ()

Implementation: /// ping.c - ping program using ICMP and Raw Sockets //

#include "ping.h"

// INTERNAL FUNCTIONSVOID REPORTERROR (LPCSTR PStrFrom); int WaitForechorePly (socket S, int Timeout); u_shortin_cksum (u_short * addr, int LEN);

// ICMP Echo Request / Reply functionsint sendechorequest (socket, lpsockaddr_in); DWORD RecvechorePly (socket, lpsockaddr_in, u_char *);

Static int initection = 0;

Void init () {WSADATA WSADATA; Word WVersionRequested = MakeWord (1, 1); if (inInited == 0) {WSASTARTUP (WVersionRequested, & Wsadata); inInited = 1;}}

Void destory () {if (inTed == 1) {wsacleanup ();}}

// Ping () // Calls SendEchoRequest () and // RecvEchoReply () and prints resultsint Ping (LPCSTR pstrHost, int timeout) {SOCKET rawSocket; LPHOSTENT lpHost; struct sockaddr_in saDest; struct sockaddr_in saSrc; DWORD dwTimeSent; DWORD dwElapsed; u_char CTTL; int NRET;

INIT ();

// Create a Raw socket rawSocket = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); if (rawSocket == SOCKET_ERROR) {ReportError ( "socket ()"); return -1;} // Lookup host lpHost = gethostbyname (pstrHost); IF (lphost == null) {fprintf (stderr, "/ nhost not found:% s / n", pstrhost; return -1;} // setup destination socket address sadest.sin_addr.s_addr = * ((u_long far * ) (lphost-> h_addr); sadst.sin_family = af_INET; SADEST.SIN_PORT = 0;

// Tell the user what we're doing printf ("/ NPINGING% S [] with% d bytes of data: / n", pstrhost, inet_ntoa (sadest.sin_addr), req_datasize;

// send ICMP Echo Request Sendechorequest (Rawsocket, & Sadest);

// use select () to wait for data to be received nret = waitforechoreply (RawSocket, timeout); if (nret == Socket_ERROR) {ReportError ("SELECT ()");} if (! Nret) {printf ("/ Ntimeout ");} // receive reply dwtimesent = recvECHOREPLY (Rawsocket, & SASRC, & CTTL);

// calculate elapsed time dwelapsed = gettickcount () - dwtimesent; printf ("/ nreply from:% s: bytes =% d time =% ldms ttl =% d", inet_ntoa (sasrc.sin_addr), Req_DataSize, dwelapsed, cttl) ; Printf ("/ n"); nret = closocket; if (nret == socket_error) ReportError ("CloseSocket ()"); return dwelapsed;}

// SendEchoRequest () // Fill in echo request header // and send to destinationint SendEchoRequest (SOCKET s, LPSOCKADDR_IN lpstToAddr) {static ECHOREQUEST echoReq; static nId = 1; static nSeq = 1; int nRet;

// Fill in echo request echoReq.icmpHdr.Type = ICMP_ECHOREQ; echoReq.icmpHdr.Code = 0; echoReq.icmpHdr.Checksum = 0; echoReq.icmpHdr.ID = nId ; echoReq.icmpHdr.Seq = nSeq ;

// Fill in Some Data to send for (nret = 0; NRET

// Save Tick Count when Sent Echoreq.dwtime = GetTickCount ();

// put data in packet and compute checksum echoreq.icphdr.checksum = IN_CKSUM ((u_short *) & echoreq, sizeof (echorequest));

// send the echo request nret = sendto (s, / * socket * / (lpstr) & echoreq, / * buffer * / sizeof (echorequest), 0, / * flags * / (lpsockaddr) lpsttoaddr, / * destination * / sizeof (SockAddr_in)); / * Address Length * /

if (nRet == SOCKET_ERROR) ReportError ( "sendto ()"); return (nRet);} // RecvEchoReply () // Receive incoming data // and parse out fieldsDWORD RecvEchoReply (SOCKET s, LPSOCKADDR_IN lpsaFrom, u_char * pTTL) {Echoreply echoreply; int nret; int Naddrlen = sizeof (struct sockaddr_in);

// receive the echo reply nret = recvfrom (s, // socket (lpstr) & echoreply, // buffer sizeof (echoreply), // size of buffer 0, // flags (lpsockaddr) lpsaFrom, // from address & naddrlen; // Pointer to Address Len

// Check Return Value if (nret == Socket_ERROR) ReportError ("Recvfrom ()");

// Return Time Sent and IP TTL * PTTL = ECHOREPLY.IPHDR.TTTL; RETURN (Echoreply.echorequest.dwtime);

// What happened? Void ReportError (LPCSTR PWHERE) {fprintf (stderr, "/ n% s error:% d / n", wsagetlasterror ());}

// waitforechoreply () // use select () to determine when // Data is Waiting to Be Readint WaitForechorePly (Socket S, Int Timeout) {struct timeVal timeout; fd_set et;

Readfds.fd_count = 1; readfds.fd_Array [0] = S; timeout.tv_sec = timeout / 1000; timeout.tv_usec = timeout% 1000; Printf ("Timeout =% D / N, sec =% D, USEC =% D / N ", Timeout, Timeout / 1000, Timeout% 1000);

Return (SELECT (1, & Readfds, Null, Null, & Timeout);

/// mike muuss' in_cksum () Function // and his comments from the original // ping program ///////// * mike muuss /// * u. S. ARMY BALLISTIC Research Laboratory // * DecEmber, 1983

/ * * IN _ CKSUM * * Checksum routine for Internet Protocol family headers (C Version) * * / u_short in_cksum (u_short * addr, int len) {register int nleft = len; register u_short * w = addr; register u_short answer; Register int sum = 0; / * * Our algorithm is Simple, Using A 32 Bit Accumulator (SUM), * WE Add Sequential 16 Bit Words to It, And at the end, fold * back all the carry bits from the top 16 bits INTO the LOWER * 16 BITS. * / while (NLEFT> 1) {SUM = * W ; NLEFT - = 2;

/ * mop up an odd byte, if Necessary * / if (NLEFT == 1) {u_short u = 0;

* (u_char *) (& u) = * (u_char *) W; SUM = U;}

/ * * Add Back Carry Outs from top 16 bits to low 16 bits * / sum >> 16) (sum & 0xfff); / * Add Hi 16 to LOW 16 * / SUM = (SUM >> 16 ); / * Add carry * / answer = ~ sum; / * truncate to 16 bits * / return (answer);} zzzhc_NET_PING.C code as follows: #include "zzzhc_net_ping.h" #include "ping.h"

JNIEXPORT jint JNICALL Java_zzzhc_net_Ping_pingCore (JNIEnv * env, jclass jc, jstring host, jint timeout) {const char * str = (* env) -> GetStringUTFChars (env, host, 0); int elapse = Ping (str, timeout); ( * ENV) -> ReleaseStringutfchars (ENV, Host, STR); Return Elapse;}

Compile generation ping.dll, put ping.dll into classes, switch to the classes directory, perform Java zzzhc.net.ping this method is also directly, better way should be a class with a Raw Socket feature. , The method of calling this class implements ping so that Java can have all network functions.

转载请注明原文地址:https://www.9cbs.com/read-82180.html

New Post(0)