注册本站  论坛  繁體中文

电脑技巧
手机 | MP3 | MP4 | 显卡 | 主板 | 显示器 | 光存储 | 笔记本 | 网络设备 | 移动存储 | 数码相机
键鼠 | CPU | 音箱 | GPS | 电视 | 服务器 | 投影机 | 机箱电源 | 品牌电脑 | 办公打印 |
| 网站首页 | Cisco | Windows | Linux | Java | Dotnet | Oracle | 网页设计 | 平面设计 | 安全 | 软件应用 | 电脑维修 | 办公维修 |
您现在的位置: 电脑技巧 >> Java >> J2ME >> 核心技术 >> Java正文

关于socket里chunk问题的解决

文章来源:csdn 作者:佚名 更新时间:2008-8-23 14:39:31 【 】 【加入收藏

    前一段时间有人说自己碰到了http协议里的chunk问题,其实你自己实现chunk也可以,就是做个状态位的判断是了。本人实现过,在WTK虚拟机还没有公开的时候,但是wtk公开了你就用wtk里面的源马吧,写的很好,不过公开的代码里竟然少了行代码,这是在让我纳闷,不知道sun是故意的还是粗心,下面的代码增加了proxy支持,实在原有基础上改的,此代码已经应用很多应用,各位网友放心使用,有问题欢迎交流。

    支持MIDP1.0和MIDP2.0,如果连接80或者8080端口,请申请证书,代码很多我给注释了,如果需要使用,请自行打开。

    用法跟HttpConnection一样,只是在初始化的时候,我给修改成了openX,如果设置proxy,可以直接调用setProxyHost,注意的是,在放置url的时候不要忘记写好端口号。

SocketConnectionExt socktCon = SocketConnectionExt.openX(URL, Connector.READ_WRITE, true);
  System.out.println("URL: " + mURL);
  //socktCon.open(mURL, Connector.READ_WRITE, true);
  if(useProxy) socktCon.setProxyHost("10.0.0.172:80");



import javax.microedition.io.StreamConnection;
/**//*
 * Copyright (c) 1999-2001 Sun Microsystems, Inc. All Rights Reserved.
 *
 * This software is the confidential and proprietary information of Sun
 * Microsystems, Inc. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Sun.
 *
 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
 * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
 * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
 * THIS SOFTWARE OR ITS DERIVATIVES.
 * Use is subject to license terms.
 */

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.ByteArrayOutputStream;

import java.util.Hashtable;
import java.util.Enumeration;

import javax.microedition.io.Connector;

/** *//**
 * This class implements the necessary functionality
 * for an HTTP connection.
 */
public class SocketConnectionExt...{
    
    private int index; // used by URL parsing functions
    private String url;
    private String protocol;
    private String host;
    private String file;
    private String ref;
    private String query;
    private int port = 80;
    private int responseCode;
    private String responseMsg;
    private Hashtable reqProperties;
    private Hashtable headerFields;
//    private String[] headerFieldNames;
//    private String[] headerFieldValues;
    private String method;
    private int opens;
    private int mode;
    private String proxyHost;
    private boolean proxy = false;
    private boolean connected;

    /**//*
     * In/out Streams used to buffer input and output
     */
    private PrivateInputStream in;
    private PrivateOutputStream out;

    /**//*
     * The data streams provided to the application.
     * They wrap up the in and out streams.
     */
    private DataInputStream appDataIn;
//    private DataOutputStream appDataOut;

    /**//*
     * The streams from the underlying socket connection.
     */
    private StreamConnection streamConnnection;
    private DataOutputStream streamOutput;
    private DataInputStream streamInput;

    /**//*
     * A shared temporary buffer used in a couple of places
     */
    private StringBuffer stringbuffer;
    private String http_version = "HTTP/1.1";

    /** *//**
     * Create a new instance of this class.
     * We are initially unconnected.
     */
    public SocketConnectionExt() ...{
        reqProperties = new Hashtable();
        headerFields = new Hashtable();
        stringbuffer = new StringBuffer(32);
        opens = 0;
        connected = false;
        method = "GET";
        responseCode = -1;
        protocol = "http";
    }
    
    public void setProxyHost(String proxyHost)...{
        this.proxyHost = proxyHost;
        proxy = true;
    }

    public void open(String url, int mode, boolean timeouts)
        throws IOException ...{

        if (opens > 0) ...{
            throw new IOException("already connected");
        }

        opens++;

        if (mode != Connector.READ && mode != Connector.WRITE
            && mode != Connector.READ_WRITE) ...{
            throw new IOException("illegal mode: " + mode);
        }

        this.url = url;
        this.mode = mode;

        parseURL();
    }
    
    public static SocketConnectionExt openX(String url, int mode, boolean timeouts) throws IOException...{
        SocketConnectionExt hcp = new SocketConnectionExt();
        hcp.open(url, mode, timeouts);
        return hcp;
    }

    public void close() throws IOException ...{
        if (--opens == 0 && connected) ...{
            disconnect();
        }
    }

    /**//*
     * Open the input stream if it has not already been opened.
     * @exception IOException is thrown if it has already been
     * opened.
     */
    public InputStream openInputStream() throws IOException ...{

        if (in != null) ...{
            throw new IOException("already open");
        }

        // If the connection was opened and closed before the
        // data input stream is accessed, throw an IO exception
        if (opens == 0) ...{
            throw new IOException("connection is closed");
        }

        // Check that the connection was opened for reading
        if (mode != Connector.READ && mode != Connector.READ_WRITE) ...{
            throw new IOException("write-only connection");
        }

        connect();
        opens++;

        in = new PrivateInputStream();
        return in;
    }

    public DataInputStream openDataInputStream() throws IOException ...{

        if (appDataIn != null) ...{
            throw new IOException("already open");
        }

        // TBD: throw in exception if the connection has been closed.
        if (in == null) ...{
            openInputStream();
        }

        appDataIn = new DataInputStream(in);
        return appDataIn;
    }

    public OutputStream openOutputStream() throws IOException ...{

        if (mode != Connector.WRITE && mode != Connector.READ_WRITE) ...{
            throw new IOException("read-only connection");
        }

        // If the connection was opened and closed before the
        // data output stream is accessed, throw an IO exception
        if (opens == 0) ...{
            throw new IOException("connection is closed");
        }

        if (out != null) ...{
            throw new IOException("already open");
        }

        opens++;
        out = new PrivateOutputStream();
        return out;
    }

    public DataOutputStream openDataOutputStream() throws IOException ...{

        if (mode != Connector.WRITE && mode != Connector.READ_WRITE) ...{
            throw new IOException("read-only connection");
        }

        // If the connection was opened and closed before the
        // data output stream is accessed, throw an IO exception
        if (opens == 0) ...{
            throw new IOException("connection is closed");
        }

        if (out != null) ...{
            throw new IOException("already open");
        }

        opens++;
        out = new PrivateOutputStream();
        return new DataOutputStream(out);
    }

    /** *//**
     * PrivateInputStream to handle chunking for HTTP/1.1.
     */
    class PrivateInputStream extends InputStream ...{

        int bytesleft;   // Number of bytes left in current chunk
        int bytesread;   // Number of bytes read since the stream was opened
        boolean chunked; // True if Transfer-Encoding: chunked
        boolean eof;     // True if EOF seen

        PrivateInputStream() throws IOException ...{
            bytesleft = 0;
            bytesread = 0;
            chunked = false;
            eof = false;

            // Determine if this is a chunked datatransfer and setup
            String te = (String)headerFields.get("transfer-encoding");
            if (te != null && te.equals("chunked")) ...{
                chunked = true;
                bytesleft = readChunkSize();
                eof = (bytesleft == 0);
            }
        }

        /** *//**
         * Returns the number of bytes that can be read (or skipped over)
         * from this input stream without blocking by the next caller of
         * a method for this input stream.
         *
         * This method simply returns the number of bytes left from a
         * chunked response from an HTTP 1.1 server.
         */
        public int available() throws IOException ...{

            if (connected) ...{
                return bytesleft ;
            } else ...{
                throw new IOException("connection is not open");
            }
        }

        /** *//**
         * Reads the next byte of data from the input stream.
         * The value byte is returned as an <code>int</code> in
         * the range <code>0</code> to <code>255</code>.
         * If no byte is available because the end of the stream
         * has been reached, the value <code>-1</code> is returned.
         * This method blocks until input data is available, the
         * end of the stream is detected, or an exception is thrown.
         *
         * <p> A subclass must provide an implementation of this method.
         *
         * @return     the next byte of data, or <code>-1</code>
         *             if the end of the stream is reached.
         * @exception  IOException  if an I/O error occurs.
         */
        public int read() throws IOException ...{

            // Be consistent about returning EOF once encountered.
            if (eof) ...{
                return -1;
            }

            /**//* If all the current chunk has been read and this
             * is a chunked transfer then read the next chunk length.
             */
            if (bytesleft <= 0 && chunked) ...{
                readCRLF();    // Skip trailing 

                bytesleft = readChunkSize();
                if (bytesleft == 0) ...{
                    eof = true;
                    return -1;
                }
            }

            int ch = streamInput.read();
            eof = (ch == -1);
            bytesleft--;
            bytesread++;
            return ch;
        }

        /** *//**
         * Reads some number of bytes from the input stream and
         * stores them into the buffer array <code>b</code>.
         * The number of bytes actually read is returned as an integer.
         * This method blocks until input data is available, end of
         * file is detected, or an exception is thrown.
         * (For HTTP requests where the content length has been
         * specified in the response headers, the size of the read
         * may be reduced if there are fewer bytes left than the
         * size of the supplied input buffer.)
         *
         * @param      b   the buffer into which the data is read.
         * @return     the total number of bytes read into the buffer,
         *             or <code>-1</code> is there is no more data
         *             because the end of the stream has been reached.
         * @exception  IOException  if an I/O error occurs.
         * @see        java.io.InputStream#read(byte[])
         */
        public int read(byte[]b) throws IOException ...{
            long len = getLength();

            if (len != -1) ...{
                // More bytes are expected
                len -= bytesread;
            } else ...{
                // Buffered reading in chunks
                len = b.length;
            }

            if (len == 0) ...{
                eof = true ;
                // All expected bytes have been read
                return -1;
            }

            return read (b, 0, (int)(len < b.length ? len : b.length)) ;
        }

        /**//* Read the chunk size from the input.
         * It is a hex length followed by optional headers (ignored)
         * and terminated with <cr><lf>.
         */
        private int readChunkSize() throws IOException ...{
            int size = -1;
            try ...{
                String chunk = readLine(streamInput);
                if (chunk == null) ...{
                    throw new IOException("No Chunk Size");
                }

                int i;
                for (i=0; i < chunk.length(); i++) ...{
                    char ch = chunk.charAt(i);
                    if (Character.digit(ch, 16) == -1)
                        break;
                }

                /**//* look at extensions?.... */
                size = Integer.parseInt(chunk.substring(0, i), 16);

            } catch (NumberFormatException e) ...{
                throw new IOException("Bogus chunk size");
            }

            return size;
        }

        /**//*
         * Read <cr><lf> from the InputStream.
         * @exception IOException is thrown if either <CR> or <LF>
         * is missing.
         */
        private void readCRLF() throws IOException ...{
            int ch;

            ch = streamInput.read();
            if (ch != ' ') ...{
                throw new IOException("missing CRLF");
            }

            ch = streamInput.read();
            if (ch != ' ') ...{
                throw new IOException("missing CRLF");
            }
        }

        public void close() throws IOException ...{
            if (--opens == 0 && connected) disconnect();
        }

    } // End of class PrivateInputStream

    /** *//**
     * Private OutputStream to allow the buffering of output
     * so the "Content-Length" header can be supplied.
     */
    class PrivateOutputStream extends OutputStream ...{
        private ByteArrayOutputStream output;

        public PrivateOutputStream() ...{
            output = new ByteArrayOutputStream();
        }

        public void write(int b) throws IOException ...{
            output.write(b);
        }

        public void write(byte[] b) throws IOException...{
            // Create the headers
            reqProperties.put("Content-Length", "" + b.length);

            String reqLine = method + " " + getFile()
                + (getRef()&n