j2me中的网络连接

(源自:http://www.j2medev.com/Article/Class1/Class14/200804/5259.html

编辑


    J2me提供了HttpConnection和SocketConnection。前者从API级提供了对http协议的支持,而后者只是单纯的一个socket流API。

    实际上对于使用Http协议的上层应用来说,网络层使用Http或者Socke应该是透明的。作为框架,应该为用户提供方便的选择方式。
    J2me中对HTTP 1.2中定义的KEEPALIVE支持得并不是很好,并不能获得一个http的长连接。对于JSE中http connection的实现还没验证。
    使用Socket的一个好处是可以避免为每个网络请求建立单独的Connection。并且因为socket的inputStream, outputStream是双工的方式工作,所以可以连续的发送网络请求而不必等待网络回应。
    如果让socket的inputStream/outputStream以双工的方式工作(即:通过outputStream发送之后不等待inputStream的response),那么需要应用层的协议进行支持。比如,需要对发出的网络请求进行编号,这样从inputstream中获得response的时候可以把这个回应匹配到正确的请求上。实现双工,很直接的想法是inputStream、outputStream分别由单独的一个线程处理。
  

    这个工具包应该能够做到支持:
  1. Http GET/POST;
  2. File download;
  3. 可以选择使用socket或是Http;
  4. 支持同步/异步(阻塞/非阻塞)发送请求,提供timeout机制;
  5. 清晰的异常定义,方便上层进行错误处理。
  6. 对于socket是否可用连接池?[对于j2me程序似乎没有必要]

    Connection中的receive, send都是阻塞的。如果要实现异步收发,需要在一个单独的线程中处理请求。

    以下是通过把阻塞的API放在一个线程中运行而获得的异步效果。理想状态下,在到达了Timeout事件后,应该把这个线程关闭。但是因为这个线程中存在阻塞方法,所以不能及时地获得停止通知(很难终止这个线程)。这个网络请求很可能会在你设置的timeout时间后获得网络response。为了处理timeout之后仍旧获得网络数据的情况,可以先把异步请求的数据对象放到一个队列中,如果网络回应在timeout之前返回,则从这个队列中查找该对象并移走这个对象;  当timeout之后,也应该把这个对象移走(可考虑放到另一个队列进行其它的特殊处理),这样当延迟的网络回应到来后,从队列中找不到对象,就不做处理。
       
    sendRequestSynch是同步的API。 sendRequest()会调用同步方法,因此放在一个单独的线程中运行。匿名线程t启动之后,通过request.wait()方法,使调用sendRequestSynch()的方法被阻塞。从request.wait()方法恢复之后,判断是否timeout发生。
    public void sendRequestSynch(final NetworkRequest request, long timeout) throws Exception {
        synchronized (request) {
             Thread t = new Thread() {
                 public void run() {
                     try {
                         log.debug("send request in another thread.");
                         sendRequest(request);
                     }catch (Exception e) {
                         log.warn(e.getMessage());
                    }
                    log.debug("Exit the thread.");
                 }
             };
             t.start();   
             
             log.debug("Try to wait for " + timeout);
              request.wait(timeout);
             if (request.isDelayed()) {
                 queue.removeElement(request);
                 timeoutQueue.addElement(request);
                 log.debug("Request TIMEOUT !!!!!!!!!!!!!!!!");
                 log.debug("Stop the network request thread for the timeout.");
             }else {
                 log.debug("Be Notified and wakeup.");
             }
        }
    }

    sendRequestAsynch是异步的API。这个是写作过程中的一个版本。在review之后发现其中存在同步问题。 synchronized (request) 不是在启动孙子线程tt之后执行。问题在于如果sendRequest(request)在执行到最后是发送request.notifyAll()时,可能还没有执行 synchronized (request) 这样就存在request.wait(timeout)不会被唤醒而超时的问题。
    public void sendRequestAsynch(final NetworkRequest request, final long timeout) throws Exception {
         Thread t = new Thread() {
             public void run() {
                 try {
                     log.debug("send request in another thread.");
                     
                     Thread tt = new Thread() {
                         public void run() {
                             try {
                                 log.debug("send request in grandson thread. " + request.getSequenceId());
                                 sendRequest(request);
                             }catch (Exception e) {
                                 log.warn(e.getMessage());
                             }
                         }
                     };
                     tt.start();
                     
                      synchronized (request) {
                         log.debug("Try to wait for " + timeout + "  " + request.getSequenceId());
                          request.wait(timeout);
                         if (request.isDelayed()) {
                             queue.removeElement(request);
                             timeoutQueue.addElement(request);
                             log.debug("Request TIMEOUT !!!!!!!!!!!!!!!!");
                             log.debug("Stop the network request thread for the timeout.");
                         }else {
                             log.debug("Be Notified and wakeup.");
                         }
                     }
                 }catch (Exception e) {
                     log.warn(e.getMessage());
                }
                log.debug("Exit the thread.");
             }
         };
         t.start();   
    }
   
    应当把sendRequest(request) 放到同步块中。改正后的代码:
    public void sendRequestAsynch(final NetworkRequest request, final long timeout) throws Exception {
         Thread t = new Thread() {
             public void run() {
                 try {
                     log.debug("send request in another thread.");
                      synchronized (request) {
                         Thread tt = new Thread() {
                             public void run() {
                                 try {
                                     log.debug("send request in grandson thread. " + request.getSequenceId());
                                     sendRequest(request);
                                 }catch (Exception e) {
                                     log.warn(e.getMessage());
                                 }
                             }
                         };
                         tt.start();
                     
                         log.debug("Try to wait for " + timeout + "  " + request.getSequenceId());
                          request.wait(timeout);
                         if (request.isDelayed()) {
                             queue.removeElement(request);
                             timeoutQueue.addElement(request);
                             log.debug("Request TIMEOUT !!!!!!!!!!!!!!!!");
                             log.debug("Stop the network request thread for the timeout.");
                         }else {
                             log.debug("Be Notified and wakeup.");
                         }
                     }
                 }catch (Exception e) {
                     log.warn(e.getMessage());
                }
                log.debug("Exit the thread.");
             }
         };
         t.start();   
    }

 [原文发布在: http://docs.google.com/Doc?id=dd6zq46t_419gwrb84hk    代码下载: http ://j2mekit.googlecode.com/svn/trunk/ j2mekit-read-only  ]



    
   

编辑此页面(您有权限)
编辑此页面(如果您有权限) | 报告垃圾信息 
Google 文档 - 网络文字处理、演示文稿和电子表格。

你可能感兴趣的:(thread,exception,socket,网络,NetWork,j2me)