Package net.solosky.maplefetion.net.http

Source Code of net.solosky.maplefetion.net.http.HttpTransfer$BytesEntry

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* Project  : MapleFetion2
* Package  : net.solosky.maplefetion.net.http
* File     : HttpTransfer.java
* Author   : solosky < solosky772@qq.com >
* Created  : 2010-4-16
* License  : Apache License 2.0
*/
package net.solosky.maplefetion.net.http;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

import net.solosky.maplefetion.net.AbstractTransfer;
import net.solosky.maplefetion.net.TransferException;
import net.solosky.maplefetion.net.buffer.ByteArrayWriter;
import net.solosky.maplefetion.net.buffer.ByteWriter;

/**
*
* HTTP方式传输信令
*
* @author solosky <solosky772@qq.com>
*/
public class HttpTransfer extends AbstractTransfer
{
  private String ssic;
  private String pragma;
  private Thread runThead;
  private int requestId;
  private volatile boolean closeFlag;
  private String url;
  private BlockingQueue<BytesEntry> bytesEntryQueue;
 
  public static final int TYPE_INIT = 0;
  public static final int TYPE_ALIVE = 1;
  public static final int TYPE_DATA = 2;

 
 
  public HttpTransfer(String url,String ssic, String pragma)
  {
    this.ssic = ssic;
    this.url  = url;
    this.pragma = pragma;
    this.requestId = 1;
    this.bytesEntryQueue = new LinkedBlockingQueue<BytesEntry>();
  }
  /* (non-Javadoc)
     * @see net.solosky.maplefetion.net.AbstractTransfer#sendBytes(byte[], int, int)
     */
    @Override
    protected void sendBytes(byte[] buff, int offset, int len)
            throws TransferException
    {
      this.bytesEntryQueue.add(new BytesEntry(buff, offset, len));
    }

  /* (non-Javadoc)
     * @see net.solosky.maplefetion.net.Transfer#startTransfer()
     */
    @Override
    public void startTransfer() throws TransferException
    {
      Runnable r = new Runnable(){
            public void run()
            {
              try{
                  ByteWriter writer =  new ByteArrayWriter();
                  //最开始执行了一个i请求
                  writer.write("SIPP".getBytes());
                  if(!tryExecuteRequest("i", requestId++, writer, 1))
                    raiseException(new TransferException("Init Http Transfer failed.."));
                 
                 
                  while(!closeFlag) {
                    writer.clear();
                    BytesEntry entry = bytesEntryQueue.poll(5,TimeUnit.SECONDS);    //等待五秒,如果没有元素也返回
                    if(entry!=null) {
                      writer.writeBytes(entry.getBytes(), entry.getOffset(), entry.getLength())//
                      while(bytesEntryQueue.size()>0) {
                        entry = bytesEntryQueue.poll();
                        writer.writeBytes(entry.getBytes(), entry.getOffset(), entry.getLength());
                      }
                    }
                    writer.write("SIPP".getBytes());
                   
                    //尝试发送这个请求,如果超过指定次数,传递传输异常
                    if(!tryExecuteRequest("s",requestId++,writer, 3)) {
                      closeFlag = true;
                      raiseException( new TransferException());
                        }
                  }
                 
                 
                  //结束
                  writer.clear();
                  writer.write("SIPP".getBytes());
                  tryExecuteRequest("d", requestId++, writer, 1);
                 
              }catch(Throwable e) {
                raiseException(new TransferException(e));
              }
            }
      };
     
      this.runThead = new Thread(r);
      this.runThead.setName(this.getTransferName());
      this.runThead.start();
    }

  /* (non-Javadoc)
     * @see net.solosky.maplefetion.net.Transfer#stopTransfer()
     */
    @Override
    public void stopTransfer() throws TransferException
    {
      this.closeFlag = true;
    }
  
   
    /**
     * 尝试发起请求,如果失败继续尝试,直到超过指定的尝试次数为止
     * @param writer
     * @param maxRetryTimes
     * @return 执行成功返回true或尝试超过指定次数返回false
     */
    private boolean tryExecuteRequest(String s, int i,ByteWriter writer, int maxRetryTimes)
    {
      int nowRetryTimes = 0;
      while(nowRetryTimes<maxRetryTimes) {
        try {
              this.executeRequest(s, i ,writer);
              return true;      //如果没有出现错误就退出重试循环
            } catch (IOException e) {
              nowRetryTimes++;  //出现错误继续发起请求
            }
      }
      return nowRetryTimes<maxRetryTimes;

    }
   
    /**
     * 执行一个请求
     * @param s
     * @param i
     * @param writer
     * @throws IOException
     */
    private void executeRequest(String s, int i,ByteWriter writer) throws IOException
    {
      String turl = this.url+"?";
      turl += "t="+s;
      turl += "&i="+ Integer.toString(i);
     
      URL realURL = new URL(turl);
      HttpURLConnection connection = (HttpURLConnection) realURL.openConnection();
      connection.setRequestMethod("POST");
      connection.setRequestProperty("User-Agent", "IIC2.0/PC 3.5.2540");
      connection.setRequestProperty("Pragma", this.pragma);
      connection.setRequestProperty("Content-Type", "application/oct-stream");
      connection.setRequestProperty("Accept", "*/*");
      connection.setRequestProperty("Cookie", "ssic="+this.ssic);
      connection.setDoOutput(true);
      OutputStream out = connection.getOutputStream();
      out.write(writer.toByteArray(), 0, writer.size());
      out.flush();
     
      if(connection.getResponseCode()==200) {
          int contentLength = connection.getContentLength();
          if(contentLength>4) {
              InputStream in = connection.getInputStream();
              writer.clear();
              while(contentLength>4){
                writer.writeByte(in.read());
                contentLength--;
              }
              this.bytesRecived(writer.toByteArray(), 0, writer.size());
          }
      }else {
        throw new IOException("Invalid response stateCode="+connection.getResponseCode());
      }
    }
   
    private class BytesEntry
    {
      private byte[] bytes;
      private int offset;
      private int length;
      public BytesEntry(byte[] bytes, int offset, int length)
      {
        this.bytes = bytes;
        this.offset = offset;
        this.length = length;
      }
      public byte[] getBytes()
      {
        return this.bytes;
      }
      public int getOffset()
      {
        return this.offset;
      }
      public int getLength()
      {
        return this.length;
      }
    }

  /* (non-Javadoc)
     * @see net.solosky.maplefetion.net.Transfer#getTransferName()
     */
    @Override
    public String getTransferName()
    {
      return "HttpTransfer - "+this.url;
    }

}
TOP

Related Classes of net.solosky.maplefetion.net.http.HttpTransfer$BytesEntry

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.