TCP/IP协议(Socket)做服务器,HTTP协议做客户端

来源:互联网 发布:台湾清华大学知乎 编辑:程序博客网 时间:2024/04/30 23:19
前几天在本区看到一个贴子,有人问,在Socket做服务器,在手机上用Http访问,如何实现。这个贴子,有十来个人回复了,可惜回复的都是:Socket使用TCP/IP协议,客户端用HTTP协议,不同协议不可能实现通讯。再可惜,那个贴子结了,要不然,我就可以回复了!在这里拿出来说一下,让大家不要再误会了(TCP/IP与HTTP不可通讯) 
因为目前很多手机仍不支持MIDP2.0,只支持MIDP1.0,而Socket技术只在MIDP2.0才提供支持,所以,一般的Java   ME程序的如果要实现C/S结构,都会选用Tomcat等服务器、sevlet或JavaBean等Java   EE架构实现。不过,考虑到响应速度与性能的问题,Tomcat等Java   EE架构可能满足不了业务要求,这样,我们就要用到下面将要说的自已写服务器的技术了。       
一般的C/S结构程序,一般程序员都会写,不过,这里一般程序员刚接触Socket写服务器,Http写客户端都会头大——不可能吧,Socket用TCP/IP协议,客户端用Http协议,不同协议间,怎么可能通讯呢!       
本文要说的就是这个问题了。       
大家一定都知道,网络系统一共分7层,在这七层中,Http协议要高于TCP/IP协议(因为在互联网中,计算机是通过IP定位的,也就是用TCP/IP协议了),对网络操作系统有了解的人,一定不会忘记,我们用Http访问www的时候,用的是域名,而域名,最终还是要通过DNS转换成IP地址的。这就对了——HTTP协议基于TCP/IP协议!而Socket正是基于TCP/IP协议,这样一来,它们就有了共同之外了!有了以上的认识,理论方面就没问题了。       
我们再讨论一下实现:       
服务器:       
和一般的C/S结构一样,用Socket(java中用ServerSocket)监听。监听、读写消息的方面与一般的C/S服务器一模一样。不同的是,考虑到客户端只支持http协议,所以,读客户端消息的时候,读到的将是http头+消息,那么,我们便要用程序分析并去掉http头,只用消息。发消息的时候正好相反,在发送的消息前面,自己加上http头(其实就是一个包含一定内容的字符串),这样再发出去,客户端就可以收到并读取了。   
客户端:       
用Http连接,在java中,用的是HttpConnection.open( "http:// "+IP+ ": "+Port)访问服务器,这样,就可以向ServerSocket请求连接了。       
在open之后,再向HttpConnection对象的输出流写入消息,然后刷新流再关闭HttpConnection就可以了,客户端因为本来用的就是http协议,所以不用自行加http头,底层会处理的;服务器在Accept()之后,就可以从Socket的输入流读到消息了。当然,如果要读服务器的消息的话,可以在HttpConnection关闭前读它的输入流(读的时候,如果还没有收到服务器消息,会阻塞当前线程的,直到读到为止,不怕读不到)。客户端读到的消息,是不包括http头的,所以,也就不用我们自行处理了。   

要注意的是,HttpConnetion.open后,只能用一次,刷新后,它就无效了,得重新调用open方法再次建立连接。(服务器最好使用线程建立Socket与客户端连接,连接一次一个线程。) 

服务器示例代码:(共三个类) 

//HttpServer.java package   testnetserver; public   class   HttpServer{ public   HttpServer()   { } public   static   void   main(String[]   aregs){ HttpServerSocket   hss=new   HttpServerSocket(); hss.start(); } } //HttpServerSocket.java package   testnetserver; import   java.net.ServerSocket; import   java.io.*; public   class   HttpServerSocket   extends   Thread{ ServerSocket   ss=null; private   static   final   int   port=2222; public   HttpServerSocket()   { } public   void   run(){ try   { ss   =   new   ServerSocket(port); } catch   (IOException   ex)   { System.out.println( "ServerSocket   can   not   listen "); System.out.println( "Error   on   ServerSocket   bind   port "); ex.printStackTrace(); ss=null; return; } //循环监听 while(true){ HttpSocket   hs=null; try   { hs=new   HttpSocket(); hs.s=ss.accept(); System.out.println( "have   a   client   connect "); hs.start(); } catch   (IOException   ex1)   { System.out.println( "Error   on   accept "); } } } } //HttpSocket.java package   testnetserver; import   java.net.Socket; import   java.io.*; public   class   HttpSocket extends   Thread   { public   Socket   s   =   null; String   msg   =   " "; public   HttpSocket()   { } public   void   run()   { BufferedReader   is   =   null; PrintWriter   os   =   null; try   { //由Socket对象得到输入流,并构造相应的BufferedReader对象 is   =   new   BufferedReader(new   InputStreamReader(s.getInputStream())); //由Socket对象得到输出流,并构造PrintWriter对象 os   =   new   PrintWriter(s.getOutputStream()); } catch   (IOException   ex)   { System.out.println( "Error   on   get   Buffere "); } String   temp   =   " "; try   { temp   =   is.readLine(); while   (temp   !=   null)   { msg   +=   temp; if   (temp.length()   >   4   && temp.substring(temp.length()   -   4).equals( "/End "))   { temp   =   is.readLine();   //虚读 temp   =   null; break; } msg   +=   "\r\n "; temp   =   is.readLine(); } getMsg(); //立刻回发消息 msg   =   "Begin/ "   +   msg   +   "/End "; os.write( "HTTP/1.1   200   OK\r\n "); os.write( "Content-Type:   text;   charset=utf\r\n "); os.write(   ( "Content-Length:   "   +   msg.length()   +   "\r\n ")); os.write( "\r\n "); os.write(msg); os.flush(); msg   =   " "; } catch   (IOException   ex1)   { System.out.println( "Error   on   read   or   write   Buffered "); ex1.printStackTrace(); } try   { sleep(100); } catch   (InterruptedException   ex2)   { System.out.println( "Error   on   HttpSocket   sleep "); } } //去掉协议头,取出纯消息 private   void   getMsg()   { int   begin   =   msg.indexOf( "Begin/ "); int   end   =   msg.indexOf( "/End "); if   (begin   > =   0   &&   end   >   0   &&   msg.length()> "Begin/ ".length())   { msg   =   msg.substring(begin   +   "Begin/ ".length(),   end); System.out.println(msg); } else   { msg   =   " "; } } } 

客户端示例代码(主要部份):

public   void   run()   { HttpConnection   conn   =   null; DataInputStream   dis   =   null; DataOutputStream   dos   =   null; int   begin   =   0,   end   =   0; byte   temp[]   =   new   byte[10000]; int   len   =   0; try   { conn   =   (HttpConnection)   Connector.open( "http:// "   +   IP   +   ": "   + port);                         //写输出流(向服务器发送信息) dos   =   conn.openDataOutputStream(); msg   =   "Begin/ "   +   msg+ "/End "; //dos.writeUTF(msg); dos.write(msg.getBytes()); dos.flush(); dos.close(); if   (!isTestConnectTime)   { dataLenght   =   msg.length(); } backTime   =   0; //读输入流(读服务器消息) dis   =   conn.openDataInputStream(); len   =   dis.read(temp); if   (len   >   0)   { receiveMsg   =   " "; for   (int   i   =   0;   i   <   len;   i++)   { receiveMsg   +=   (char)   temp[i]; } } if   (receiveMsg.length()   >   0)   { begin   =   receiveMsg.indexOf( "Begin/ "); end   =   receiveMsg.indexOf( "/End "); if   (begin   > =   0   &&   end   >   0)   { receiveMsg   =   receiveMsg.substring(begin   + "Begin/ ".length(),   end); if   (receiveMsg   !=   null   &&   receiveMsg.trim()   !=   " "   && receiveMsg.length()   >   0)   { System.out.println(receiveMsg); testCount++; if   (!isTestConnectTime)   { allDataLenght   +=   dataLenght; } } } } //dos.close(); dis.close(); conn.close(); } catch   (Exception   ex1)   { System.out.println( "Error   on   send   message "); ex1.printStackTrace(); } }

转载http://topic.csdn.net/t/20060918/23/5030821.html