ネットワークプログラミング-サーバネットワーク時間の読み取り


シーン:時間サーバはインターネットの多くのネットワークデバイスの同期に使用されます。時間サーバのデフォルトポートは37で、時間サーバがクライアントの接続要求を受信すると、すぐにネットワーク時間に戻ります。ネットワーク時間は4バイトの符号なし整数で、現在時間と1900年の元月1日の0時正の秒値の差を表しています。
JTimeClient.java
import java.net.*;
import java.io.*;

public class JTimeClient {
  private String server;  //     
  private int port;       //   

  public JTimeClient(String server) {
    this(server, 37);//          37
  }	
  
  public JTimeClient(String server, int port) {
  	this.server = server;
  	this.port = port;
  }
  
  //      , -1    
  public long getNetTime() {
  	Socket socket = null;
  	InputStream in = null;
    try {
      //  
      socket = new Socket(server, port);
      //     
      in = socket.getInputStream( );
      //    ,     4       ,
      //    1900   1 0    
      long netTime = 0;
      for(int i=0; i<4; i++) {
      	netTime = (netTime << 8) | in.read();
      }
      
      return netTime;
    }
    catch (UnknownHostException e) {
   	  //e.printStackTrace();
    }
    catch (IOException e) {
      //e.printStackTrace();
    }
    finally {//      
      try {//     
        if(in != null) in.close();
      }	catch (Exception e) {}

      try {//    
        if(socket != null) socket.close();
      }	catch (Exception e) {}
    }
  	return -1;
  }
  
  public static void main(String[] args) {
  	JTimeClient timeClient = null;
  	
	if(args.length == 1) {//            
	  timeClient = new JTimeClient(args[0]);
	}
	else if(args.length == 2) {//           
	  timeClient = new JTimeClient(args[0], Integer.parseInt(args[1]));
	}
	else {
	  System.out.println("Usage: java JTimeClient TimeServer Port");
	  return;
	}

    System.out.println("Time:" + timeClient.getNetTime());
  }
}
タイムサーバーが起動されていない場合、本プログラムの結果を直接実行します。java JTimeClient local host Time:-1
交替勤務方式:JTimeServer.java
import java.net.*;
import java.io.*;
import java.util.Date;

public class JTimeServer implements Runnable {
  private int port;
  	
  public JTimeServer() {
  	this(37);//          37
  }

  public JTimeServer(int port) {
  	this.port = port;
  }
  
  public void run() {
  	try {
  	  //          	 
      ServerSocket server = new ServerSocket(port);
      //            
  	  while(true) {
        Socket connection = null;
        try {
          //         
          connection = server.accept();
          
          //  Date.getTime        (    )
          //  2208988800           
          Date now = new Date();
          long netTime = now.getTime()/1000 + 2208988800L;
        
          byte[] time = new byte[4];
          for(int i=0; i<4; i++) {
          	time[3 - i] = (byte)(netTime &0x00000000000000FFL);
          	netTime >>= 8;
          }
          //        ,       
          OutputStream out = connection.getOutputStream();
		  
          out.write(time);
          out.flush();      
        }
        catch (IOException e) {
        }
        finally {//      
          if (connection != null) connection.close(); 
        }
  	  }
  	}
  	catch(IOException e) {
  	}
  }
  
  
  public static void main(String[] args) {
  	JTimeServer timeServer = null;
  	
	if(args.length == 0) {
	  timeServer = new JTimeServer();
	}
	else if(args.length == 1) {//                
	  timeServer = new JTimeServer(Integer.parseInt(args[0]));
	}
	else {
	  System.out.println("Usage: java JTimeServer Port");
	  return;
	}
	
	(new Thread(timeServer)).start();
  }
}
運転結果:3558353322
同時作業方式:JTimeServer 2.java
import java.net.*;
import java.io.*;
import java.util.Date;
class JTimeThread extends Thread {
  private Socket connection;  
  public JTimeThread(Socket connection) {
  	this.connection = connection;
  }  
  public void run() {
  	try {
      //  Date.getTime        (    )
      //  2208988800           
      Date now = new Date();
      long netTime = now.getTime()/1000 + 2208988800L;
        
      byte[] time = new byte[4];
      for(int i=0; i<4; i++) {
        time[3 - i] = (byte)(netTime &0x00000000000000FFL);
        netTime >>= 8;
      }
      //        ,       
      OutputStream out = connection.getOutputStream();
      out.write(time);
      out.flush();      
  	}
  	catch(IOException e) {
  	}  
    finally {//         
      try {
        if (connection != null) connection.close(); 
      } catch (IOException e) {}
    }
  }
} 
public class JTimeServer2 implements Runnable {
  private int port;  	
  public JTimeServer2() {
  	this(37);//          37
  }
  public JTimeServer2(int port) {
  	this.port = port;
  }  
  public void run() {
  	ServerSocket server = null;
  	try {
  	  //          	 
      server = new ServerSocket(port);
      //            
  	  while(true) {
        try {
          //         
          Socket connection = server.accept();
          //       JTimeThread          
          (new JTimeThread(connection)).start();
        }
        catch (IOException e) {
        }
  	  }
  	}
  	catch(IOException e) {
  	}
  	finally { //     Socket
      try {
        if(null != server) server.close();
      } catch (IOException e) {}
  	}
  }  
  public static void main(String[] args) {
  	JTimeServer2 timeServer = null;  	
	if(args.length == 0) {
	  timeServer = new JTimeServer2();
	}
	else if(args.length == 1) {//                
	  timeServer = new JTimeServer2(Integer.parseInt(args[0]));
	}
	else {
	  System.out.println("Usage: java JTimeServer2 Port");
	  return;
	}	
	(new Thread(timeServer)).start();
  }
}

Date.getTime()は、現在のシステム時間を取得し、1927元月1日0時のlong型ミリ秒数に基づくものである。
PSの注意:Socketにデータを書き込む時、私達はまだ非常に重要な細部に注意しなければなりません。
Javaの新しいIOがSelectorを進化させ、現在のシステム時間をクライアントに返す無ブロッキングサーバを作成します。
import java.net.InetSocketAddress ;
import java.net.ServerSocket ;
import java.util.Set ;
import java.util.Iterator ;
import java.util.Date ;
import java.nio.channels.ServerSocketChannel ;
import java.nio.ByteBuffer ;
import java.nio.channels.SocketChannel ;
import java.nio.channels.Selector  ;
import java.nio.channels.SelectionKey  ;
public class DateServer{
	public static void main(String args[]) throws Exception {
		int ports[] = {8000,8001,8002,8003,8005,8006} ; //         
		Selector selector = Selector.open() ;	//   open()    Selector
		for(int i=0;i<ports.length;i++){
			ServerSocketChannel initSer = null ;
			initSer = ServerSocketChannel.open() ;	//         
			initSer.configureBlocking(false) ;	//          
			ServerSocket initSock = initSer.socket() ;
			InetSocketAddress address = null ;
			address = new InetSocketAddress(ports[i]) ;	//        
			initSock.bind(address) ;	//        
			initSer.register(selector,SelectionKey.OP_ACCEPT) ;	//     
			System.out.println("     , " + ports[i] + "    。") ;
		}
		//         key,                   
		int keysAdd = 0 ;
		while((keysAdd=selector.select())>0){	//      ,             
			Set<SelectionKey> selectedKeys = selector.selectedKeys() ;//        key
			Iterator<SelectionKey> iter = selectedKeys.iterator() ;
			while(iter.hasNext()){
				SelectionKey key = iter.next() ;	//      key
				if(key.isAcceptable()){
					ServerSocketChannel server = (ServerSocketChannel)key.channel() ;
					SocketChannel client = server.accept() ;	//      
					client.configureBlocking(false) ;//       
					ByteBuffer outBuf = ByteBuffer.allocateDirect(1024) ;	//
					outBuf.put(("      :" + new Date()).getBytes()) ;	//          
					outBuf.flip() ;
					client.write(outBuf) ;	//     
					client.close() ;	//   
				}
			}
			selectedKeys.clear() ;	//      key
		}
		
	}
}
注意:サーバーが動作したら、従来のソケットのようにサーバーをすぐに閉じず、次の接続を待ち続けます。
拡張:各種時間