//////////////以下读取资源文件b5_1.ndx、b5_1.ndx,原理同读取gb_1.ndx、gb_2.ndx  
tempStr="";
fileLen=0;
           try {
            f = new File("b5_1.ndx"); 
            inBuffer = new BufferedReader(new FileReader(f));  
            while((s = inBuffer.readLine()) != null) { 
tempStr=tempStr+s+",";
fileLen++;
}
            }
 finally { try { if (in!=null) in.close(); } catch (IOException e) {} }st=new StringTokenizer(tempStr,",");
b5_1=new String[fileLen];
b5_2=new String[fileLen];
for(int k=0;st.hasMoreTokens();k++)
{b5_1[k]=st.nextToken();} fileLen=0;
           try {
            f = new File("b5_2.ndx"); 
            inBuffer = new BufferedReader(new FileReader(f));  
            while((s = inBuffer.readLine()) != null) { 
b5_2[fileLen]=s;
fileLen++;
}
            }
 finally { try { if (in!=null) in.close(); } catch (IOException e) {} }//end Read Big5&GB words source
System.out.println();
System.out.println("初始化完毕!");
System.out.println();try {if(SERVER_IP.length()>4){//如果长度大于4,可据此判断配置文件此项非空,则使用此IP,否则使用默认IP,即localhost
int backlog=10; //The maximum queue length for incoming connection indications.
URL SERVER_URL=new URL(SERVER_IP);
server=new ServerSocket(PORT,backlog,InetAddress.getByName(SERVER_URL.getHost())); 
}else{
server=new ServerSocket(PORT); 
}System.out.println("Web Server is listening on port "+server.getLocalPort());
for (;;) {
client=server.accept(); //接受客户机的连接请求
new ConnectionThread(client,i,GbSrc,Big5Src,Gb2Src,Big52Src,WEB_SITE,FlagGB_Big,WEB_PORT,gb_1,gb_2,b5_1,b5_2).start(); 
i++;
}
} catch (Exception e) {System.out.println(e);}
}
}//main/* ConnnectionThread类完成与一个Web浏览器的通信 */
class ConnectionThread extends Thread {
Socket client=null; //连接Web浏览器的socket字
int counter; //计数器
String GbSrc;
String Big5Src;
String Gb2Src;
String Big52Src;
String[] gb_1,gb_2,b5_1,b5_2;
int wordGBLen,wordBig5Len;//此变量为字符串数组gb_1、gb_2、b5_1、b5_2长度,由于前两者,后两都长度分别相等,故此。String WEB_SITE;
String FlagGB_Big;
int WEB_PORT;public ConnectionThread(Socket cl,int c,String GbSrcV,String Big5SrcV,String Gb2SrcV,String Big52SrcV,String WEB_SITEV,String FlagGB_BigV,int WEB_PORTV,String[] gb_1V,String[] gb_2V,String[] b5_1V,String[] b5_2V) throws IOException{
GbSrc=GbSrcV;
Big5Src=Big5SrcV;
Gb2Src=Gb2SrcV;
Big52Src=Big52SrcV;
WEB_SITE=WEB_SITEV;
FlagGB_Big=FlagGB_BigV;
WEB_PORT=WEB_PORTV;
gb_1=gb_1V;
gb_2=gb_2V;
b5_1=b5_1V;
b5_2=b5_2V;
wordGBLen=gb_1.length;
wordBig5Len=b5_1.length;client=cl;
counter=c;
}public void run() //线程体
{
try {
String destIP=client.getInetAddress().toString(); //客户机IP地址
int destport=client.getPort(); //客户机端口号
System.out.println("Connection "+counter+":connected to "+destIP+" on port "+destport+".");
PrintStream outstream=new PrintStream(client.getOutputStream());
BufferedReader instream=new BufferedReader(new InputStreamReader(client.getInputStream()));
String inline=instream.readLine(); //读取Web浏览器提交的请求信息
System.out.println("Received:"+inline);
int methodI=getrequest(inline);//获知客户(浏览器)请求方式
if (methodI>0) { //if the method GET or POST==如果客户请求方式为GET或POST,则处理,否则...
String filename=getfilename(inline);//据客户请求信息第一行(HTTP协议)得到请求的文件名
String fileExe=(filename.substring(filename.lastIndexOf('.')+1)).toLowerCase();//得到文件扩展名
//if not .txt==如果是二进制文件则不处理,关闭连接
if(   (fileExe.equalsIgnoreCase("gif"))||(fileExe.equalsIgnoreCase("exe"))||(fileExe.equalsIgnoreCase("swf"))||(fileExe.equalsIgnoreCase("jpg"))||(fileExe.equalsIgnoreCase("zip"))   ){
client.close();
}else{////////////////do with the data==处理得来的信息
String toString="";
URL WEB_URL;
String WEB_Path="";
String theURL="";
WEB_Path=WEB_SITE + "/" + filename;//得到请求文件服务器路径,以便向服务器请求//get the Path of URL.
int lastIdx=filename.lastIndexOf("/");
if (lastIdx>=0)
{
theURL=WEB_SITE+"/"+filename.substring(0,lastIdx);//得到文件服务器相对路径,以便处理HTML代码中的连接
}else{
theURL=WEB_SITE;
}//Read file from WEB_SERVER
char[] buffer = new char[4096]; 
int len;
WEB_URL=new URL(WEB_Path);
if (methodI==1){//if GET method==如果是GET方式请求,则直接用URL.openStream得到请求内容
BufferedReader inURL=new BufferedReader(new InputStreamReader(WEB_URL.openStream()));
                                       
            while((len = inURL.read(buffer)) != -1) { 
                String s = new String(buffer, 0, len); 
toString=toString+s;
}
inURL.close();
}else if(methodI==2){//if POST method==如果是POST方式请求,则...
//Read all which POST method need
String cmd="";
String cmdF="";
String oneLine="";while((oneLine = instream.readLine())!=null) {//读取头文件部份(HTTP协议相关)
cmdF=cmdF+oneLine+"\r\n";
if(oneLine.equalsIgnoreCase(""))break;
}int conLenIdx=cmdF.indexOf("Content-Length: ")+16;//据头文件信息可得到数据区长度,以及更改此长度后再发送到服务器(IIS)
int conRetIdx=cmdF.indexOf("\r\n",conLenIdx);//因为要对数据区进行转换,可能长度会变,故此。            while((len = instream.read(buffer))!=-1) { // ##here is a bug.==读取数据区,这儿有个BUG尚未解决,请往下看...
                String s = new String(buffer, 0, len); 
                cmd=cmd+s;
                break;//BUG在此,不管有没读完,都被中止,如果不这样,程序就死在这里了,不知道为什么。这个while语句应该是正确的但却不能够正常工作,下面还有类似情况。如果提交的表单内容比较少,一次就可以读完,所以没问题,但如果提交的数据内容比较多,那么就有问题了。
                //if (s.indexOf("\r\n\r\n")>=0)break;
}
// instream.close();cmd=URLDecoder.decode(cmd);//得到的数据区内容被浏览器encode过了,将其decode过来进行编码转换,即繁体->简体。另:这里也有BUG,大大的BUG^-^,如下
/*
关于此处BUG的说明:
在IE提交表单时会将数据Encoder后再提交给服务器,然后服务器应该是对其进行Decoder后再处理的。
Encoder时,对于一般的汉字应该是用两对"%"号后加两个字符表示一个汉字,比如繁体字的"我"应该是%A7%DA,繁体字的"用"则是%A5%CE,可是对于其它少部份汉字竟然会出现这种情况,如繁体字的"称"是Encoder后成了%26%2331216%3B,真是莫名其妙。然后对上边的数据,即"我"对应的%A7%DA,"用"对应的%A5%CE,"称"对应的%26%2331216%3B进行Decoder时,分别得到的数据是:и、ノ、称
对于前面两个汉字--"我"和"用",得到"и","ノ",这确实是繁体字(Big5码)中的"我"和"用",可"称"字竟然成了称这到底是怎么回事呢?应该如何解决呢?真把头都弄大了!*注:之所以提交的是繁体字,是因为网页是繁体版本的,即使在文本框中输入的是简体字,IE会自动将其转换成繁体后再提交。
*/

解决方案 »

  1.   

    int cmdBIdx=0,cmdEIdx=0;
    String cmdTemp="",cmdChange="";
    String oldcmd;/*
    处理数据区,数据区格式为:
    userName=и称ノ&userPWD=key123&userPWD2=key123&[email protected]&register= 猔 
    应该以"="和"&"分段处理,但由于有时候提交的表单中有如以上所说的不正常的Encoder结果,所以得到此不正常的数据区,里边有个称影响数据区的正常处理,那其实就是"称"字。
    直接得到的数据(即未经decode的)为:
    userName=%A7%DA%26%2331216%3B%A5%CE&userPWD=key123&userPWD2=key123&[email protected]&register=+%AA%60+%A5U+
    */
    while ((cmdBIdx=cmd.indexOf("=",cmdBIdx+1))!=-1){
    cmdEIdx=cmd.indexOf("&",cmdBIdx);

    if(cmdEIdx!=-1){
    cmdChange=cmd.substring(cmdBIdx+1,cmdEIdx);//得到数据部份(即除"="号和"&"号外的数据),进行处理
    oldcmd=cmdChange;//保存源始数据
    cmdChange=new String(cmdChange.getBytes("GB2312"),"big5");//利用Java本身的转换内码功能进行首次处理
    cmdChange=changeBig5Str(cmdChange,oldcmd);//用资源文件进行一一对应处理,具体请参见此函数。
    cmdChange=changeWordsGB(cmdChange);//处理习惯用语,见函数
    cmdChange=URLEncoder.encode(cmdChange);//再进行encode
    cmd=cmd.substring(0,cmdBIdx+1)+cmdChange+cmd.substring(cmdEIdx);}else
    {//遇到最后一个"=",处理方式同上
    cmdChange=(cmd.substring(cmdBIdx+1));
    oldcmd=cmdChange;
    cmdChange=new String(cmdChange.getBytes("GB2312"),"big5");
    cmdChange=changeBig5Str(cmdChange,oldcmd);
    cmdChange=changeWordsGB(cmdChange);
    cmdChange=URLEncoder.encode(cmdChange);
    cmd=cmd.substring(0,cmdBIdx+1)+cmdChange;
    }//end if
    }//end whileint nLen=cmd.length();String cmdFF=cmdF.substring(0,conLenIdx);
    String cmdFE=cmdF.substring(conRetIdx);
    cmdF=cmdFF+nLen+cmdFE;//将处理后数据区长度加入头文件中cmd=inline+"\r\n"+cmdF+cmd+"\r\n\r\n";//完整的请求内容
    //POST data to the Server and get feedback data.==将cmd以HTTP协议的POST方法提交给服务器,如(IIS),并得到IIS响应的数据。
    BufferedOutputStream sender;
    Socket client2=null;client2 = new Socket(InetAddress.getByName(WEB_URL.getHost()),WEB_PORT);
    sender = new BufferedOutputStream(client2.getOutputStream());
    sender.write(cmd.getBytes(),0,cmd.length());
    sender.flush();BufferedReader receiver=new BufferedReader(new InputStreamReader(client2.getInputStream()));
    toString="";            while((len = receiver.read(buffer)) != -1) { // 这里也有个读取socket数据的BUG
                    String s = new String(buffer, 0, len);  
    toString=toString+s;
    if (s.indexOf("0\r\n\r\n")>=0)break;//此处由于while语句不能够正常结束,只能以此判断循环结束,因为一般服务器响应的数据结尾有"0\r\n\r\n"这样的一段内容,但如果HTML文件本身也有这样的内容的话,就会判断错误了。
    }
    receiver.close();
    }
    //至此已经得到了客户用GET或者POST方法请求的所有数据,而后进行HTML内容中连接的处理以及简体->繁体转换后发给客户(浏览器)//Change tag as <a href=...> <img src=...>==将HTML文件中所有要转换的连接文件,除js,css,txt外的连接变为正确的相对连接--加上正确的相对路径,以便浏览器再次向本程式请求而非直接向服务器请求,此处js文件本来也应该处理的,但太困难。
    if(!(  (fileExe.equalsIgnoreCase("js"))||(fileExe.equalsIgnoreCase("css"))||(fileExe.equalsIgnoreCase("txt"))    ))
    toString=ChangeLink(toString,theURL);//处理过程请参看函数/////////////////do with the toString and make it to GB<->Big5==以下简体->繁体转换
    //First:use System unicode.
    String oldString=toString;
    toString=new String(toString.getBytes("Big5"));//第一次利用Java内码转换功能进行转换//Second:use GB_Big5 source String to Change all of "?" in the string toString.
    toString=changeGBStr(toString,oldString);//利用资源文件及一一对应原理处理没有正常转换的"?"/////////////end of first changed
    /////////////change words==处理习惯用语
    toString=changeWordsBig5(toString);
    /////////////end of change wordsif(!(  (fileExe.equalsIgnoreCase("js"))||(fileExe.equalsIgnoreCase("css"))||(fileExe.equalsIgnoreCase("txt"))    ))
    toString=changeCharsetGB(toString);//如果是HTML文件或者asp,jsp,php文件等,将文件头部content='text/html; charset=gb2312'改为big5/////////////////output toString to client if (methodI==1){//如果是以GET方式请求的,加上头部
    outstream.println("HTTP/1.0 200 OK");
    outstream.println("MIME_version:1.0");
    outstream.println("Content_Type:text/html");
    outstream.println("Content_Length:"+toString.length()+2);
    outstream.println("");
    }
    //由于以POST方式请求的数据头部已经有的,不必要再加
    //将GET或者POST方式请求的数据反馈给客户(浏览器)
    outstream.println(toString);
    outstream.flush();
    System.out.println("posted!!!");
    } //end if not .txt
    } //if the method GET or POST//////////////waiting…………
    long m1=1; 
    while (m1<11100000) {m1++;} //延时
    client.close();
    } catch (IOException e) {
    System.out.println("Exception:"+e);
    } //end try} //end run()
    /* 获取请求类型是否为"GET"或"POST" */
    int getrequest(String s) { 
    if (s.length()>0)
    {
    String methodString=s.substring(0,3);
    if (methodString.equalsIgnoreCase("GET")) return 1;
    else if (methodString.equalsIgnoreCase("POS")) return 2;
    }
    return 0;
    }/* 获取要访问的文件名 */
    String getfilename(String s) {
    String f=s.substring(s.indexOf(' ')+1);
    f=f.substring(0,f.indexOf(' '));
    try {
    if (f.charAt(0)=='/')
    f=f.substring(1);
    } catch (StringIndexOutOfBoundsException e) {
    System.out.println("Exception:"+e);
    }
    return f;
    }
      

  2.   

    //////////////do with the HTML String.==将HTML文件中连接,即以src、href、background等标签中的连接作必要的更改。
    public static String ChangeLink(String htmlString,String theURL){String rhtml=htmlString;
    int theIdx;theIdx=rhtml.indexOf(" src");
    if (theIdx>=0)
    {
    rhtml=FindIdx(rhtml,theIdx,theURL);//do with FindIdx()
    }
    while (theIdx>=0)
    {
    theIdx=rhtml.indexOf(" src",theIdx+5);
    if (theIdx>=0)
    {
    rhtml=FindIdx(rhtml,theIdx,theURL);//do with FindIdx()
    }
    }//srctheIdx=rhtml.indexOf(" background");
    if (theIdx>=0)
    {
    rhtml=FindIdx(rhtml,theIdx,theURL);//do with FindIdx()
    }
    while (theIdx>=0)
    {
    theIdx=rhtml.indexOf(" background",theIdx+5);
    if (theIdx>=0)
    {
    rhtml=FindIdx(rhtml,theIdx,theURL);//do with FindIdx()
    }
    }//backgroundtheIdx=rhtml.indexOf(" href");
    if (theIdx>=0)
    {
    rhtml=FindIdx(rhtml,theIdx,theURL);//do with FindIdx()
    }
    while (theIdx>=0)
    {
    theIdx=rhtml.indexOf(" href",theIdx+5);
    if (theIdx>=0)
    {
    rhtml=FindIdx(rhtml,theIdx,theURL);//do with FindIdx()
    }
    }//href
    return rhtml;
    }//end ChangeLinkpublic static String FindIdx(String htmlString,int theIdx,String theURL){
    String rhtml="";
    String shtml="";
    String c="'";
    String filePath;
    String fileType;
    String tailTemp;theURL=theURL+"/";int isLink,bIdx,eIdx,isHttp,isHttp2,isHttp3,dotIdx,firstTempIdx;
    isLink=htmlString.indexOf("<",theIdx-30);
    if (isLink<theIdx)
    {
    bIdx=htmlString.indexOf("=",theIdx);
    eIdx=htmlString.indexOf(">",theIdx);
    shtml=((htmlString.substring(bIdx+1,eIdx)).toLowerCase()).trim();
    isHttp=shtml.indexOf("http://");
    isHttp2=shtml.indexOf("javascript:");
    isHttp3=shtml.indexOf("mailto:");if ((isHttp==-1)&&(isHttp2==-1)&&(isHttp3==-1))//如果连接是以http://、javascript:或者mailto:开头的,不进行处理
    {//do with 
    char FirstChar=shtml.charAt(0);
    int havaChar=0;
    if ((FirstChar==c.charAt(0))||(FirstChar=='"'))//对于连接包含在单双引号内的处理
    {
    havaChar=1;//如有单双引号,则标志为1
    filePath=(shtml.substring(1)).trim();
    }else{
    havaChar=0;//如果没有引号,则标起为0,下边会用到
    filePath=shtml;
    }//end if
    firstTempIdx=filePath.indexOf("?");//连接中有问号的处理
    if (firstTempIdx>=0)
    {
    tailTemp=filePath.substring(firstTempIdx);
    filePath=filePath.substring(0,firstTempIdx);
    havaChar=0;
    }else{
    firstTempIdx=filePath.indexOf(" ");
    if (firstTempIdx>=0)
    {
    tailTemp=filePath.substring(firstTempIdx);
    filePath=filePath.substring(0,firstTempIdx);
    }else{
    tailTemp="";
    }
    }dotIdx=filePath.lastIndexOf('.') ;//fileTypefileType=filePath.substring(dotIdx+1);
    fileType=fileType.substring(0,fileType.length()-havaChar);if (!(    fileType.equalsIgnoreCase("html")||fileType.equalsIgnoreCase("htm")||fileType.equalsIgnoreCase("txt")||fileType.equalsIgnoreCase("css")||fileType.equalsIgnoreCase("asp")||fileType.equalsIgnoreCase("php")||fileType.equalsIgnoreCase("jsp")||fileType.equalsIgnoreCase("shtml")||fileType.equalsIgnoreCase("phtml")||fileType.equalsIgnoreCase("xhtml")||fileType.equalsIgnoreCase("js")||fileType.equalsIgnoreCase("xml")||fileType.equalsIgnoreCase("pl")      ))//如果连接文件为以上文件中的一种,则改变连接为相对连接,否则不改变
    {
    rhtml=htmlString.substring(0,bIdx+1)+FirstChar+theURL+filePath+tailTemp+htmlString.substring(eIdx);
    return rhtml;
    }else{
    return htmlString;
    }
    }else{
    return htmlString;
    }//if (isHttp==-1)
    }else{
    return htmlString;
    }//if (isLink<theIdx)
    }//end FindIdx()
    ////////////////////change one GB String to Big5 String
    public String changeGBStr(String toString,String oldString){
    int quIdx=0;
    char oldChar;
    quIdx=toString.indexOf('?');while (quIdx>=0)
    {
    oldChar=oldString.charAt(quIdx);if(!(oldChar=='?')){
    toString=changeGBChar(quIdx,oldChar,toString);
    }
    quIdx=toString.indexOf('?',quIdx+1);
    }return toString;
    }////////////////////change one Big5 String to GB String
    public String changeBig5Str(String toString,String oldString){
    int quIdx=0;
    char oldChar;
    quIdx=toString.indexOf('?');while (quIdx>=0)
    {
    oldChar=oldString.charAt(quIdx);if(!(oldChar=='?')){
    toString=changeBig5Char(quIdx,oldChar,toString);
    }
    quIdx=toString.indexOf('?',quIdx+1);
    }return toString;
    }
    ////////////////////change one GB char to Big5 char
    public String changeGBChar(int quIdx,char oldChar,String toString){
    int charIdx;
    String tempString;
    charIdx=GbSrc.indexOf(oldChar);if(charIdx>=0)
    {
    tempString=toString.substring(0,quIdx)+Big5Src.charAt(charIdx)+toString.substring(quIdx+1);
    }else
    {
    tempString=toString;
    }
    return tempString;
    }//end changeGBChar()////////////////////change one Big5 char to GB char
    public String changeBig5Char(int quIdx,char oldChar,String toString){
    int charIdx;
    String tempString;
    charIdx=Big52Src.indexOf(oldChar);if(charIdx>=0)
    {
    tempString=toString.substring(0,quIdx)+Gb2Src.charAt(charIdx)+toString.substring(quIdx+1);
    }else
    {
    tempString=toString;
    }
    return tempString;
    }//end changeBig5Char()
    ////////////////////change the HTML head to big5
    public String changeCharsetGB(String toString){
    int charsetIdx=toString.indexOf("2312");

    if (charsetIdx>=0){
    int tagIdx=toString.indexOf(">",charsetIdx);
    if (tagIdx-charsetIdx<10)
    toString=toString.substring(0,charsetIdx-2)+"big5  "+toString.substring(tagIdx-1);
    }

    return toString;
    }//end changeCharset()
    ////////////////////change the words in GBString.
    public String changeWordsGB(String GBString){
    //wordGBLen
    StringBuffer theStr=new StringBuffer (GBString);
    for(int i=0;i<wordGBLen;i++){
    String gb1=gb_1[i];
    int bIdx=0;
    while ((bIdx=GBString.indexOf(gb1,bIdx))>=0){
    theStr.replace(bIdx,bIdx+gb1.length(),gb_2[i]);
    bIdx=bIdx+1;
    }//while
    }//for
    return theStr.toString();
    }//end changeWordsGB()////////////////////change the words in big5String.
    public String changeWordsBig5(String big5String){
    //wordBig5Len
    StringBuffer theStr=new StringBuffer (big5String);
    for(int i=0;i<wordBig5Len;i++){
    String bi1=b5_1[i];
    int bIdx=0;
    while ((bIdx=big5String.indexOf(bi1,bIdx))>=0){
    theStr.replace(bIdx,bIdx+bi1.length(),b5_2[i]);
    bIdx=bIdx+1;
    }//while
    }//for
    return theStr.toString();
    }//end changeWordsBig5()
    }
      

  3.   

    谢谢 bobfallen 提供的资料!