import java.net.*;
import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;

public class EchoServer extends Frame 
{
	static public void main(String args[])
	{
		EchoServer frame=new EchoServer();
	}
	ServerSocket s_socket=null;
	int port=80;
	boolean flag=true;//要求待ちループのフラグ
	TextArea textArea=new TextArea();
	public EchoServer(){
		super("エコーサーバー(port番号80番)");
		add("Center",textArea);
		addWindowListener(
			new WindowAdapter()
			{
				public void windowClosing(WindowEvent e)
                {
                   	flag=false;//フラグを倒すとループが終了
                }	
			}
		);
		setSize(500,300);
		setVisible(true);
		run();
	}
	//サーバソケットを作成し無限ループで接続要求を処理する。
	public void run(){
		try{
			s_socket = new ServerSocket(port);//ポート番号のサーバソケットを作成
			s_socket.setSoTimeout(100); 
			textArea.append("Start port"+port+"\n");
			while(flag){
				try{
					Socket socket = s_socket.accept();
					setChannel(socket);
				} catch(SocketTimeoutException ste){}
			}
			s_socket.close();
			s_socket=null;
		}catch(IOException e){e.printStackTrace();}
		System.exit(0);//プログラムの終了
	}
	
	//Channelの総数を制限し、かつ使い回しを行う
	final int maxChannel=10;
	WebChannel ChannelList[]=new WebChannel[maxChannel];
	public void setChannel(Socket socket){
		WebChannel obj=null;
		for(int i=0;i<maxChannel;i++){
			if(ChannelList[i]==null){
				ChannelList[i]=this.new WebChannel();
			}
			if(ChannelList[i].activ==false){
				obj=ChannelList[i];
				break;
			}
		}
		if(obj!=null)obj.startChannel(socket);
	}

	//1対1の通信は別スレッドを内部クラスで用意する。並列処理する
	class WebChannel implements Runnable{
		boolean activ=false;
		Socket socket=null;
		Thread thread=null;

		//ServerSocketを待たせないために1対1の通信は別スレッドで並列処理する
		public void startChannel(Socket socket){
			activ=true;
			this.socket = socket;
			thread=new Thread(this);
			thread.start();
		}
		public void run(){
			BufferedReader input=null;
			PrintWriter output=null;
			try{
				input=new BufferedReader(
					new InputStreamReader(socket.getInputStream(),"JISAutoDetect")
				);
				output=new PrintWriter(new OutputStreamWriter(socket.getOutputStream(),"SJIS"));

				output.print("HTTP/1.0 200 OK\r\n");
				output.print("Connection: close\r\n");
				output.print("Content-Type: text/html\r\n");
				output.print("\r\n\r\n");
				output.print("<HTML><HEAD></HEAD><BODT>\r\n");
				InetAddress inet=socket.getInetAddress();
				output.print(
					"あなた、"+inet.getHostName()
					+"("+inet.getHostAddress()+":"+socket.getPort()+")から" 
					+"送られてきたデータは次の通りでした<HR><PRE>\r\n"
				);
				
				textArea.append("<"+inet.getHostAddress()+":"+socket.getPort()+">\r\n");
				int count=0;
				while(true){
					if(input.ready()){
						int c=input.read();
						if(c==-1)break;
						output.print((char)c);
					}else{
						count++;
						if(10<count)break;
						try{Thread.sleep(20);}catch(Exception e2){break;}
					}
				}
				output.print("<HR></PRE></BODY></HTML>\r\n");
			} catch(IOException e){
				e.printStackTrace();
			}finally{
			//ここから後始末
				try {
					if(output!=null)output.close();output=null;
					if(input!=null)input.close();input=null;
					if(socket!=null)socket.close();socket=null;
				} catch (IOException e) {e.printStackTrace();}
				activ=false;
			}
		}
	} 
}