ServerSocketの覚書
仕事で必要に迫られて書いてみたんですが
少し納得いかなかったので書き直してみました。
Socketの使い方とかだんだん忘れてきているので
きちんと書いて覚え書きとして残しといたほうがよさそうだなとおもったので
めもめも。
サーバはこんな感じに。
package socketexample; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; abstract class AbstractSever{ private int port = 0; private boolean stop = false; private Thread t = null; public AbstractSever(int port){ this.port = port; } public void start(){ t = new Thread(new Runnable(){ public void run(){ serverRunnning(); } }); t.start(); } public boolean isAlive(){ return (t == null)?false:t.isAlive(); } private void serverRunnning(){ try { ServerSocket server = new ServerSocket(port); while(!stop){ try { final Socket soc = server.accept(); new Thread(new Runnable(){ @Override public void run(){ System.err.println("start >> " + Thread.currentThread().getId()); service(soc); try{ soc.close(); }catch(Exception err){ err.printStackTrace(); } System.err.println("<< end " + Thread.currentThread().getId()); } }).start(); } catch (IOException ex) { ex.printStackTrace(); } } } catch (IOException ex) { ex.printStackTrace(); } } public boolean stop(){ return stop = true; } abstract void service(Socket soc); }
サービスの実装を分離してみる。。。
package socketexample; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; public class EchoServer extends AbstractSever { public EchoServer(int port){ super(port); } @Override void service(Socket soc) { try { InputStream in = soc.getInputStream(); OutputStream out = soc.getOutputStream(); StringBuffer sb = new StringBuffer(); int cnt = 0; byte[] buf = new byte[1024]; while ((cnt = in.read(buf, 0, buf.length)) != -1) { sb.append(new String(buf, 0, cnt)); if (sb.charAt(sb.length() - 1) == '\n') { String s = Thread.currentThread().toString() + ": " + sb.toString(); out.write(s.getBytes()); if (s.endsWith("end\r\n")) { break; } else { sb.setLength(0); } } } } catch (IOException ex) { ex.printStackTrace(); } } }
サーバはこうやって起動します
AbstractSever server = new EchoServer(55110); server.start();
telnet で平文を送ると その文字列を返します。
せっかくなんでクライアントも作ってみました。
package socketexample; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.Socket; import java.util.logging.Level; import java.util.logging.Logger; public class Client { String host; int port; public Client(String host, int port){ this.host = host; this.port = port; } public void run() { BufferedReader br = null; try { final Socket soc = new Socket(host, port); final InputStream in = soc.getInputStream(); final OutputStream out = soc.getOutputStream(); new Thread(new Runnable(){ @Override public void run(){ try { byte[] buf = new byte[1024]; int cnt = 0; while ((cnt = in.read(buf, 0, buf.length)) != -1) { System.out.print(new String(buf, 0, cnt)); } } catch (IOException ex) { Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); } } }).start(); try { br = new BufferedReader(new InputStreamReader(System.in)); String line; while((line = br.readLine()) != null){ if(soc.isClosed())break; out.write((line+"\r\n").getBytes()); } } finally { if (br != null) { br.close(); } } } catch (Exception err) { err.printStackTrace(); } } }
ソケットの読み込みを別スレッドにしないと
書き込みが終わらないと読み込めなくなっちゃいます。
クライアントはこうやって起動します。
new Client("localhost", 55110).run();
Socket通信自体は簡単なんですが、結構面倒。。。
moremagic
2014-05-08