Socketの初歩的なプログラミング-簡単なチャットを実現


初めてsocketネットワークプログラミングに触れ、ネット上の先輩たちの文章も参考にしました.自分でも書いてみて、過程を記録してみましょう.
 
サービス側:(クライアントメッセージを受信して印刷)
 
public class SocketServer {
	private List<Socket> socketList = new ArrayList<Socket>();
	 public static void main(String[] args) {  
		 SimServer ss = new SimServer();
		 try {
			ss.service();
		} catch (IOException e) {
			e.printStackTrace();
		}
	 }  
	 
	 public void service() throws IOException {
		 ServerSocket server = new ServerSocket(7001);  
		 SimServer ss = new SimServer();
		 while (true) {  
			 Socket socket = server.accept(); 
			 socketList.add(socket);
			 ServerThread st = new ServerThread(socket, socketList);
			 st.start();
		 }  
		 
	 }
	 
	 class ServerThread extends Thread {
		private Socket client;
		private List<Socket> socketList;
		public ServerThread(Socket client, List<Socket> socketList) {
			this.client = client;
			this.socketList = socketList;
		}
		
		@Override
		public void run() {
			BufferedReader in = null;  
            PrintWriter out = null;  
            try {  
                in = new BufferedReader(new InputStreamReader(client.getInputStream()));  
                while (true) {  
                    String msg = in.readLine();  
                    System.out.println(InetAddress.getLocalHost().getHostAddress() + "      :" +msg);
//                    System.out.print("      :");
//                    String input = new BufferedReader(new InputStreamReader(System.in)).readLine();
                    System.out.println();
                    for(int i=0; i<socketList.size(); i++) {
//                    	out = new PrintWriter(client.getOutputStream());
                    	out = new PrintWriter(socketList.get(i).getOutputStream());
                    	out.println("     :" + msg);
                    	out.println();
                    	out.flush();  
//                    out.println("Server handle: " + Arrays.toString(msg.getBytes()));
// 					  out.write("Server handle: " + Arrays.toString(msg.getBytes()));
//                    String lineSeprator = (String) java.security.AccessController.doPrivileged(
//                    		new sun.security.action.GetPropertyAction("line.separator"));
//                    out.write(lineSeprator);
//                    if (msg.equals("bye")) {  
//                        break;  
//                    }  
                    	
                    }
                }  
            } catch(IOException ex) {  
                ex.printStackTrace();  
            } finally {  
                try {  
                    in.close();  
                } catch (Exception e) {}  
                try {  
                    out.close();  
                } catch (Exception e) {}  
                try {  
//                    client.close();  
                } catch (Exception e) {}  
            }
		}
		 
	 } 
	   
}

 
クライアント:(メッセージを送信してメッセージを受信する.これは非同期であるべきであるため、2つのスレッドを作成する必要があります)
public class SocketClient {
	
	class Send extends Thread {
		private Socket socket;
		public Send(Socket socket) {
			this.socket = socket;
		}
		@Override
		public void run() {
			PrintWriter out = null;
			BufferedReader input = null;
			 try {
				out = new PrintWriter(socket.getOutputStream());
				input = new BufferedReader(new InputStreamReader(System.in));
				 while (true) {
			        	System.out.print(InetAddress.getLocalHost().getHostAddress()+"       :");
			            String msg = input.readLine();  
			            out.println(msg);  
			            out.flush(); 
			             
			        }  
//			        socket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}finally {
				try {
					if(input != null)
						 input.close(); 
					 if(out != null)
	                     out.close();
//					 if(socket != null)
//						 socket.close();
                } catch (Exception e) {}  
                
			}
		}
	}
	
	class Recv extends Thread {
		private Socket socket;
		public Recv(Socket socket) {
			this.socket = socket;
		}
		@Override
		public void run() {
			BufferedReader reader = null;
			 try {
				reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
				 while (true) {
					 	System.out.println();
			            String msg = reader.readLine();  
			            System.out.println(msg);  
			           
			        }  
			} catch (IOException e) {
				e.printStackTrace();
			}finally {
				try {
					if(reader != null)
						reader.close(); 
//					 if(socket != null)
//						 socket.close();
                } catch (Exception e) {}
			}
		}
	}
	
	public static void main(String[] args) {
		SimClient sc = new SimClient();
		try {
			Socket s = new Socket("localhost", 7001);
			sc.new Recv(s).start();
			sc.new Send(s).start();
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}	
}

 
(別のマシンに同じクライアントがあるが、ipアドレスをサーバがあるマシンのipに変更する)
 
-----------------------------------
このプロセスでは、次の点が見つかりました.
1)サービス側はサーバSocketを使用し、クライアントがサービス側に接続されるたびにserverSocket.accept()がクライアントと対話するためのsocketを生成するようにトリガする.
2)PrintWriter.write(String msg)はメッセージを送信できません.PrintWriter.println(String msg)は可能ですが、println(String msg)は(同時にwrite lineSeprator)に相当します.
 out.write("Server handle: "+ Arrays.toString(msg.getBytes()));
 String lineSeprator = (String) java.security.AccessController.doPrivileged(
                  new sun.security.action.GetPropertyAction("line.separator"));
 out.write(lineSeprator);
3)サービス・エンド・スレッドは、いくつかのクライアントが接続されていることを知るためにsocketListを送信する必要があります.