问题
服务器因为防火墙的原因,或者为了安全禁止了ping服务,导致无法ping通,会让我们误判断两个服务器之间网络不通,但是服务器却可以远程访问,是正常连通状态,编写程序判断两个服务器之间网络状况。
思路
1、先判断网络是否可以连通;
2、可以连通在程序中使用ping命令获取网络状况和丢包率;
3、无法连通,使用ping命令先获取网络丢包率,再通过对外开放的端口使用TCP三次握手判断是否可连接;
4、UDP无法判断,UDP是无连接状态,发送出去就不会考虑对方是否接收;
解决
准备:确保被检测的服务器是开启状态,并将需要对外开放的端口放开。
实现代码
获取网络状态
/**
* 获取网络状态
* @param host
* @param timeout
* @return
*/
private static boolean isHostReachable(String host,Integer timeout){
try {
return InetAddress.getByName(host).isReachable(timeout);
} catch (IOException e) {
logger.error("判断网络状态异常" + e.getMessage());
e.printStackTrace();
}
return false;
}
使用ping的方式获取丢包率,windows和Linux系统ping命令获取的结果不一样,需要分开解析返回的字符串
/**
* 通过ip获取信息,loss:丢包率,delay:延时
* @param cmd
* @return
*/
private static Map<String,String> getNetworkStatusByPing(String os,String cmd){
Map<String,String> networkMap = new HashMap<>(3);
//获取当前进程运行对象
Runtime runtime = Runtime.getRuntime();
Process process = null;
String line = null;
InputStream inputStream = null;
InputStreamReader isReader = null;
BufferedReader reader = null;
String loss = "";//丢包率
String delay = "";//延时
try {
process = runtime.exec(cmd);
inputStream = process.getInputStream();//实例化输入流
isReader = new InputStreamReader(inputStream,"GB2312");
reader = new BufferedReader(isReader);
StringBuffer buffer = new StringBuffer();
if (os.contains("win") || os.contains("Win")|| os.contains("WIN")){//Windows系统执行结果解析
while ((line = reader.readLine()) != null){
//丢包率
if (line.contains("%")){
loss = line.substring(line.lastIndexOf("=") + 1 ,line.indexOf("%") + 1);
if (loss.contains("(")){
loss = loss.substring(loss.indexOf("(") + 1).trim();
}
System.out.println(loss);
}
//网络延时
if ((line.contains(",") || line.contains(",")) && line.contains("=") && line.contains("ms")){
delay = line.substring(line.lastIndexOf("=") + 1 ,line.lastIndexOf("ms") + 2).trim();
System.out.println(delay);
}
buffer.append(line + "\n");
}
}else{//Linux系统执行结果解析
while ((line = reader.readLine()) != null){
//丢包率
if (line.contains("%")){
String[] msg = null;
if (line.contains(",")){
msg = line.split(",");
}else if (line.contains(",")){
msg = line.split(",");
}
if (msg.length > 0) {
loss = msg[2].substring(0, msg[2].indexOf("%") + 1).trim();
System.out.println(loss);
}
}
//网络延时
if (line.contains("/")){
String[] msg = line.split("=");
String[] names = msg[0].split("/");
String[] values = msg[1].split("/");
for (int i = 0;i < names.length;i++){
String str = names[i];
if ("avg".equalsIgnoreCase(str)){
delay = values[i];
break;
}
}
System.out.println(delay);
}
buffer.append(line + "\n");
}
}
if (StringUtils.isNotEmpty(loss)){
networkMap.put("loss",loss);
}else {
networkMap.put("loss","0%");
}
if (StringUtils.isNotEmpty(delay)){
networkMap.put("delay",delay);
}else {
networkMap.put("delay","99999ms");
networkMap.put("status","-1");//无法ping通
}
System.out.println(buffer.toString());
inputStream.close();
isReader.close();
reader.close();
// runtime.exit(1);
} catch (IOException e) {
logger.error("通过ping方式获取网络信息异常:" + e.getMessage());
e.printStackTrace();
// runtime.exit(1);
}
return networkMap;
}
判断开发端口网络状况
/**
* 判断指定端口网络状态
* @param localAddress 源地址
* @param remoteAddress 目标地址
* @param port 端口
* @param timeout 超时时间
* @return
*/
private static boolean isRealchable(InetAddress localAddress,InetAddress remoteAddress,int port,int timeout){
boolean realchable = false;
Socket socket = null;
try {
socket = new Socket();
//端口为0标识在本地挑选一个可用端口进行连接
SocketAddress socketAddress = new InetSocketAddress(localAddress,0);
socket.bind(socketAddress);
InetSocketAddress endpointSocketAddress = new InetSocketAddress(remoteAddress,port);
socket.connect(endpointSocketAddress,timeout);
System.out.println("Socket连接建立成功");
realchable = true;
} catch (IOException e) {
logger.info("Socket连接失败,localAddress:" + localAddress
+ ",remoteAddress:" + remoteAddress + ",port:" + port) ;
System.out.println("Socket连接失败,localAddress:" + localAddress
+ ",remoteAddress:" + remoteAddress + ",port:" + port );
}finally {
if (socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return realchable;
}
/**
* 判断指定端口网络状况
* @param remoteAddress 目标地址
* @param port 端口
*/
public static boolean getNetworkByPort(InetAddress remoteAddress,int port){
boolean netStatus = false;
Enumeration<NetworkInterface> netInterfaces;
try {
netInterfaces = NetworkInterface.getNetworkInterfaces();
while (netInterfaces.hasMoreElements()){
NetworkInterface ni = netInterfaces.nextElement();
Enumeration<InetAddress> localAddress = ni.getInetAddresses();
while (localAddress.hasMoreElements()){
InetAddress local = localAddress.nextElement();
if (isRealchable(local,remoteAddress,port,3000)){
netStatus = true;
break;
}
}
}
} catch (SocketException e) {
logger.error("获取本地ip与目标地址端口通信失败:" + e.getMessage());
e.printStackTrace();
}
System.out.println(netStatus);
return netStatus;
}
办法很蠢,路过有获取网络丢包率好办法的请告知一下!