实现的功能——将用户从一个Web网站重定向到另一个站点。下例从命令行读取URL和端口号,打开此端口号的服务器可能速度会很快,因此不需要多线程。尽管日次,使用多线程可能还是会带来一些好处,尤其是对于网络带宽很低、吞吐量很小的网站。在此主要是为了演示,所以,已经将该服务器做成多线程的了。这里为了简单起见,为每个连接都启用了一个线程,而不是采用线程池。或许更便于理解,但这真的有些浪费系统资源并且显得低效。
import Java.io.BufferedInputStream; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; import java.net.BindException; import java.net.ServerSocket; import java.net.Socket; import java.util.Date; public class Redirector implements Runnable { private int port; private String newSite; public Redirector(String site, int port){ this.port=port; this.newSite=site; } @Override public void run() { try { ServerSocket server=new ServerSocket(port); System.out.println("Redirecting connection on port" +server.getLocalPort()+" to "+newSite); while (true) { try { Socket socket=server.accept(); Thread thread=new RedirectThread(socket); thread.start(); } catch (IOException e) { // TODO: handle exception } } } catch (BindException e) { System.err.println("Could not start server. Port Occupied"); }catch (IOException e) { System.err.println(e); } } class RedirectThread extends Thread { private Socket connection; RedirectThread(Socket s) { this.connection=s; } public void run() { try { Writer out=new BufferedWriter( new OutputStreamWriter(connection.getOutputStream(),"ASCII")); Reader in=new InputStreamReader( new BufferedInputStream(connection.getInputStream())); StringBuffer request=new StringBuffer(80); while (true) { int c=in.read(); if (c=='\t'||c=='\n'||c==-1) { break; } request.append((char)c); } String get=request.toString(); int firstSpace=get.indexOf(' '); int secondSpace=get.indexOf(' ', firstSpace+1); String theFile=get.substring(firstSpace+1, secondSpace); if (get.indexOf("HTTP")!=-1) { out.write("HTTP/1.0 302 FOUND\r\n"); Date now=new Date(); out.write("Date: "+now+"\r\n"); out.write("Server: Redirector 1.0\r\n"); out.write("Location: "+newSite+theFile+"\r\n"); out.write("Content-Type: text/html\r\n\r\n"); out.flush(); } //并非所有的浏览器都支持重定向, //所以我们需要生成一个适用于所有浏览器的HTML文件,来描述这一行为 out.write("<HTML><HEAD><TITLE>Document moved</TITLE></HEAD>\r\n"); out.write("<BODY><H1>Document moved</H1></BODY>\r\n"); out.write("The document "+theFile +" has moved to \r\n<A HREF=\""+newSite+theFile+"\">" +newSite+theFile +"</A>.\r\n Please update your bookmarks"); out.write("</BODY></HTML>\r\n"); out.flush(); } catch (IOException e) { }finally{ try { if (connection!=null) { connection.close(); } } catch (IOException e2) { } } } } /** * @param args */ public static void main(String[] args) { int thePort; String theSite; try { theSite=args[0]; //如果结尾有'/',则去除 if (theSite.endsWith("/")) { theSite=theSite.substring(0,theSite.length()-1); } } catch (Exception e) { System.out.println("Usage: java Redirector port"); return; } try { thePort=Integer.parseInt(args[1]); } catch (Exception e) { thePort=80; } Thread t=new Thread(new Redirector(theSite, thePort)); t.start(); } }
HTTP测试:侦听8010端口,此处重定向到百度:
main()方法提供一个非常简单的界面,读取新网站的URL(为了把链接重定向到该URL)和监听本地端口。它使用这些信息构造了一个Rredirector对象。然后它使用所生成的Runnable对象(Redirector实现了Runnable)来生成一个新线程并启动。如果没有指定端口,Rredirector则会监听80端口。