因为目前很多手机仍不支持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();
- }
- }