MajiMeM

- 備忘録 -

EchoServant - .nio ver -

プログラム

備考

  • サーバ・クライアントは実行後選択
  • 多重接続対応
  • クライアントは一定期間ごとにメッセージを送り続け,規定時間後終了
  • サーバは起動し続ける(クライアントを待ち続ける)

コード

Main
public class Main {	
	private static MyLog l = new MyLog();
	private static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	private static final int SERVER_PORT = 5555;
	private static final String LOCAL_IP = "192.168.0.216";
	
	public static void main(String[] args) throws IOException {
		l.l("'s'erver or 'c'lient>>");
		String mode = br.readLine();
		if (mode.equals("s")) {
			server();
		} else if (mode.equals("c")) {
			client();		
		}

	}

	/* server lunch */
	static private void server() throws IOException {
		l.il("Server start");
		new Server(SERVER_PORT).start();
	}
	
	/* client lunch*/
	static private void client() throws IOException {
		l.il("Client start");
		l.il("Server ip: " + LOCAL_IP);
		l.il("Server port: " + SERVER_PORT);
		new Client(LOCAL_IP, SERVER_PORT).start();
	}	
}
Server
class Server {
	public static final int BUFFER_SIZE = 8192;
	public static final int TIMEOUT = 5 * 1000; // 5 sec
	private MyLog l = new MyLog();
	private ServerSocketChannel serverSocketChanel;
	private Selector selector;
	private int port;
	
	public Server(int port) throws IOException {
		this.port = port;
		selector = Selector.open();
		acceptableSocketChannelRegister();
	}

	public void start() {
		try {
			while (selector.keys().size() > 0) {
				int selectedKeyCount = 0;
				if ((selectedKeyCount = selector.select(TIMEOUT)) <= 0) {
					l.il("Select Time out (" + TIMEOUT + " ms): selectedKeyCount: " + selectedKeyCount);
					continue;
				} else {
					l.il("Select: selectedKeyCount: " + selectedKeyCount);
				}
				Iterator selectedKeysIterator = selector.selectedKeys().iterator();
				while (selectedKeysIterator.hasNext()) {
					SelectionKey key = (SelectionKey)selectedKeysIterator.next();
					selectedKeysIterator.remove();
					if (!key.isValid()) {
						l.il("Received invalid key: " + key);
						continue;
					}
					if (key.isAcceptable()) {
						l.il("Selcted key: accept");
						handleAcceptable(key);
					}
					if (key.isReadable()) {
						l.il("Selcted key: read");
						handleReadable(key);
					}
					if (key.isWritable()) {
						l.il("Selcted key: write");
						handleWritable(key);
					}
					if (key.isConnectable()) {
						l.il("Selcted key: connect");
						//handleConnectable(key);
					}
				}
			}
		} catch (Exception e) {
		}
	}
	
	private void handleAcceptable(SelectionKey key) {		
		try {
			ServerSocketChannel srvCh = (ServerSocketChannel)key.channel();
			SocketChannel channel = srvCh.accept();
			channel.configureBlocking(false);
			ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
			channel.register(key.selector(), SelectionKey.OP_READ, buffer);
			l.il("Connected client: " + channel);
			acceptableSocketChannelRegister();
		} catch(Exception e) {
		}
	}
	
	private void handleReadable(SelectionKey key) {		
		try {
			SocketChannel channel = (SocketChannel)key.channel();
			ByteBuffer buffer = (ByteBuffer)key.attachment();
			int count = channel.read(buffer);
			if (count < 0) {
				key.interestOps(key.interestOps() & ~SelectionKey.OP_READ);
				l.il("Close client(read): " + channel);
				//channel.close();
				return;
			} else if (count == 0) {
				key.interestOps(key.interestOps() & ~SelectionKey.OP_READ);
			}
			key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);
			handleWritable(key);
		} catch(Exception e) {
		}
	}

	private void handleWritable(SelectionKey key) {		
		try {
			SocketChannel channel = (SocketChannel)key.channel();
			ByteBuffer buffer = (ByteBuffer)key.attachment();
			buffer.flip();
			l.ll("Echo message: " + decode(buffer.duplicate()));
			int count = channel.write(buffer);
			buffer.compact();
			if (count < 0) {
				key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
				l.il("Close client(write): " + channel);
				//channel.close();
				return;
			} else if (count == 0) {
				key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
			}
		} catch(Exception e) {
		}
	}
	
	private void acceptableSocketChannelRegister() throws IOException {
		serverSocketChanel = ServerSocketChannel.open();
		serverSocketChanel.configureBlocking(false);
		serverSocketChanel.socket().bind(new InetSocketAddress(port));
		serverSocketChanel.register(selector, serverSocketChanel.validOps());
		l.il("Server status: " + serverSocketChanel.socket().toString());
		l.il("ServerSocketChannel valid ops: " + serverSocketChanel.validOps());
	}
	
	private String decode(ByteBuffer buffer) throws CharacterCodingException {
		Charset charset = Charset.forName("UTF-8");
		CharsetDecoder decoder = charset.newDecoder();
		return decoder.decode(buffer).toString();
	}
}
Client
class Client {
	public static final int BUFFER_SIZE = 8192;
	public static final int TIMEOUT = 5 * 1000; // 5 sec
	private MyLog l = new MyLog();
	private Socket socket;
	public Client(String ip, int port) {
		try {
			this.socket = new Socket();
			socket.setReceiveBufferSize(BUFFER_SIZE);
			socket.connect(new InetSocketAddress(ip, port));
			socket.setSendBufferSize(BUFFER_SIZE);
			socket.setSoTimeout(TIMEOUT);
		} catch (Exception e) {			
		} finally {
		}
	}

	public void start() {
		handleConversation(socket);		
	}
	
	private void handleConversation(Socket socket) {
		BufferedReader br = null;
		BufferedWriter bw = null;
		try {
			br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
			// 500ms間隔で書き込み
			for (int i = 0; i < 10; i++) { 
				String sendLine = "Hello from Client. i=" + i + "\n";
				bw.write(sendLine);
				bw.flush();
				String receavedLine = br.readLine();
				l.ll("Sended: " + sendLine);
				l.ll("Received: " + receavedLine);
				Thread.sleep(2000);
				l.ll("--");
			}
		} catch (Exception e) {
		} finally {
			try {
				bw.close();
				br.close();
				socket.close();
			} catch (IOException e) {
			}
			l.il("End client");
		}
	}	
}	
MyLog
public class MyLog {
	public MyLog() {
	}

	public void l(String s) {		
		System.out.print(s);
	}

	public void ll(String s) {		
		System.out.println(s);
	}

	public void i(String s) {
		System.err.print("INFO: " + s);
	}

	public void il(String s) {
		System.err.println("INFO: " + s);
	}
	
	public void w(String s) {		
		System.err.print("WERNING: " + s);
	}

	public void wl(String s) {		
		System.err.println("WERNING: " + s);
	}

	public void s(String s) {		
		System.err.print("SEVERE: " + s);
	}

	public void sl(String s) {		
		System.err.println("SEVERE: " + s);
	}

}
Related Posts Plugin for WordPress, Blogger...