主体类
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URLConnection;
import java.net.URL;
import java.util.concurrent.Executors;
import javax.net.ssl.HttpsURLConnection;
import java.io.IOException;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.Reader;
import java.io.InputStreamReader;
import java.util.concurrent.*;
/**
* 测试连接可用性的类
* 功能:
*
* 1·接受数据
* 接受用户输入的URL;
* 连接方式 ;
* 是否自动执行3**跳转;
* 指定的是否登录的标记以及登录需要的账户、密码和登录页面;
* 用户指定的模拟并发数和单个并发的访问数;
*
* 2·测试url是否可用
* 测试url的连接是否可以正常连接;
*
* 3·获取url的相关信息
* 获取服务器的类型;
* 获取url的路径;
* 获取url内容长度;
* 获取url对应的ip地址
*
* 4·获取登录信息
* 获取登录需要的cookie
*
* */
public class GetHttpInfor {
//基本参数
private String urlToLink;//要连接的url
private boolean linkType;//连接的类型,为true则是http,为false则是https
private boolean requestType;//数据发送的方式,为true则是 get,为false则是post
private int timeOut; //设置超时时间限制
private short condition;//url状态,通常为0 ,不通 为1;需要登录的页面无法获取cookie为 2 ;
private int numForLink;//连接的次数
private int numRequestForOne;//但是连接的请求数
//登录页面参数
private String urlToLogin;//登录所需的url
private boolean linkTypeLogin;//登录页面的连接类型,为true则是http;为false则是https
private boolean requestTypeLogin;//登录页面的数据发送类型,为true则是get,为false则是post
private String username;//登录需要的账户
private String poassword;//登录需要的密码
private String cookie;//登录后获取到的cookie
private int timeOutLogin;//登录页面的页面超时时间限制
//url信息参数
private String serviceType;//url的所对应的服务器类型
private String path;//url的内容路径
private String lenght;//url上内容的长度
private String ip;//url对应的ip地址
//并发请求时间
private double allTime;//请求的总时间
private double singleTime;//单个请求的时间
//构造函数
/**
* 获取用户传递的url,请求方式类型,请求的并发数和每个并发请求的次数
*
* */
GetHttpInfor(String urlTemp,String linkTypeTemp,int numForLink,int numRequestForOne,int timeOut){
linkTypeTemp = linkTypeTemp.toLowerCase();
String[] urlPieces = urlTemp.split("://");
this.numForLink = numForLink;
this.numRequestForOne = numRequestForOne;
this.urlToLink = urlTemp;
this.timeOut = timeOut;
if(0==urlPieces[0].toLowerCase().compareTo("https")){
this.linkType=false;
}else{
this.linkType=true;
if(1==urlPieces[0].toLowerCase().compareTo("http")){
this.urlToLink="http://"+this.urlToLink;
}
}
if(0==linkTypeTemp.compareTo("post")){
this.requestType=false;
}else{
this.requestType=true;
}
}
//设置是否登录
/**
* 设置是否登录的开关量;设置登录的url,登录需要的用户名和密码
* 返回值:
* 成功获取登录状态,返回true
* 失败则返回false
* */
public void login(String url,String requestTemp,int timeOutForLogin,String username,String password){
//登录的初始化
//从登录的url中获取连接的方式 http 或者 https
String[] urlPieces = url.split("://");
String strPost = "userid="+username+"&password="+password;
if(0==urlPieces[0].toLowerCase().compareTo("https")){
this.linkTypeLogin=false;
}else{
this.linkTypeLogin=true;
if(1==urlPieces[0].toLowerCase().compareTo("http")){
url = "http://"+url;
}
}
//连接类型 get或者post
if(0==requestTemp.toLowerCase().compareTo("post")){
this.requestTypeLogin=false;
}else{
this.requestTypeLogin=true;
}
try {
URL linkUrl = new URL(url);
HttpURLConnection link =(HttpURLConnection)linkUrl.openConnection();
if(!this.linkTypeLogin){
link = (HttpsURLConnection)link;
}
if(this.requestTypeLogin){
link.setRequestMethod("POST");
}else{
link.setRequestMethod("GET");
}
//设置link 的属性,允许写输出
link.setDoOutput(true);
//设置link 的属性,允许读输入
link.setDoInput(true);
//设置link 的属性,允许使用缓存
link.setUseCaches(false);
//设置link 的属性,发送客户端的浏览器类型
link.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Foxy/1; .NET CLR 2.0.50727; MEGAUPLOAD 1.0)");
//设置link 的属性,目的主机
link.setRequestProperty("Host", "http://acm.nyist.net/JudgeOnline/dologin.php?url=http%3A%2F%2Facm.nyist.net%2FJudgeOnline%2Fproblemset.php");
//设置link 的属性,发送内容的长度
link.setRequestProperty("Content-Length",strPost.length()+"");
//设置link 的属性,连接的类型
link.setRequestProperty("Connection", "Keep-Alive");
//设置link 的属性
link.setRequestProperty("Cache-Control", "no-cache");
//设置link 的连接超时时间
link.setConnectTimeout(timeOutForLogin);
//输出内容到目的主机(发送用户的登录名和密码)
link.getOutputStream().write(strPost.getBytes());
link.getOutputStream().flush();
link.getOutputStream().close();
//设置此连接是否自动执行重定向
link.setInstanceFollowRedirects(true);
//执行连接
link.connect();
int code = link.getResponseCode();
if(code!=200){
this.condition = 2;
this.cookie="";
return;
}
this.cookie=link.getHeaderField("Set-Cookie");
/*
BufferedReader out = new BufferedReader(new InputStreamReader(link.getInputStream()));
String oo = out.readLine();
while(oo!=null){
oo = new String(oo.getBytes("GBK"),"utf-8");
System.out.println(oo);
oo=out.readLine();
}
*/
} catch (MalformedURLException e) {
//url 连接不上
this.condition = 2;
this.cookie=null;
} catch (IOException e){
//获取url的连接内容出错
this.condition = 2;
this.cookie=null;
}
}
//测试url是否可通
/**
* 请求url页面,测试url是否可通;
* 记录服务器的类型,url的路径,url上内容的长度,url对应的ip地址;
* 并执行并发请求,记录请求的总时间、单个请求的时间
* 返回值:
* 若url请求不通,或者并发访问期间出现错误,返回false;
* url可通,且并发请求顺利完成,返回true;
* */
public void test(){
try{
URL linkUrl = new URL(this.urlToLink);
HttpURLConnection link = (HttpURLConnection)linkUrl.openConnection();
if(!this.linkType){
link = (HttpsURLConnection)link;
}
//设置相关参数
//连接方式
if(!this.requestType){
link.setRequestMethod("POST");
}else{
link.setRequestMethod("GET");
}
//超时时间
link.setConnectTimeout(this.timeOut);
//是否携带cookie
if(null!=this.cookie){
link.setRequestProperty("Cookie",this.cookie);
}
//执行连接
link.connect();
//如果连接的页面连接不成功,则标记状态为1,并返回
if(200!=link.getResponseCode()){
this.condition = 1;
return;
}
//记录url状态,连同测试同就认为是0
this.condition = 0;
//根据用户的模拟量要求申请线程池
ExecutorService executor = Executors.newFixedThreadPool((this.numForLink/10)>1?this.numForLink:1);
//获取各种记录各种状态值的类对象
NumAcc numAcc = NumAcc.getNumAcc();
NumNoFound numNoFound = NumNoFound.getNumNoFound();
NumTimeout numTimeout = NumTimeout.getNumTimeout();
NumOther numOther = NumOther.getNumOther();
NumSignel numSignel = NumSignel.getNumSignel();
numSignel.numSignel=this.numForLink*this.numRequestForOne;
//创建线程类的实例对象
LinkThread[] runFoundation = new LinkThread[this.numForLink];
Thread[] thread= new Thread[this.numForLink];
for(short i= 0; i<runFoundation.length;i++){
runFoundation[i] = new LinkThread(this.urlToLink,this.numRequestForOne,this.linkType,this.requestType,this.timeOut,this.cookie,numAcc,numNoFound,numTimeout,numOther,numSignel);
thread[i]=new Thread(runFoundation[i]);
}
runFoundation=null;
//记录当前时间,将线程加入到线程池中
long startTime = System.currentTimeMillis();
for(short i = 0;i<thread.length;i++){
executor.execute(thread[i]);
}
executor.shutdown();
//记录结束时间,计算总时间
while(numSignel.numSignel!=0){
//System.out.println(numSignel.numSignel);
}
//结束时间
long endTime = System.currentTimeMillis();
System.out.println(startTime+"----"+endTime);
System.out.println("numAcc: "+numAcc.numAcc+" -- numNoFound:"+numNoFound.numNoFound+" -- numTimeout:"+numTimeout.numTimeout+" -- numOther:"+numOther.numOther);
}catch(IOException e){
//url不通的时候的错误处理
this.condition = 1;
e.printStackTrace();
}
}
public static void main(String[] args){
GetHttpInfor one = new GetHttpInfor("http://www.php100.com/","get",20,30,5000);
one.test();
}
}
然后是线程类
import java.io.IOException;
import java.net.HttpURLConnection;
import javax.net.ssl.HttpsURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.*;
/**
* 线程函数,
* 接受传递过来的参数,模拟连接访问
*
* */
public class LinkThread implements Runnable{
private String url;//要连接的url
private boolean linkType;//连接的方式
private boolean requestType;//请求的方式
private int timeOut;//记录请求超时的时间
private String cookie;//cookie 的值
private int num;//请求次数
private NumAcc numAcc;//记录200 请求的对象
private NumNoFound numNoFound;//记录404 请求的对象
private NumTimeout numTimeout;//记录超时的请求对象
private NumOther numOther;//记录其他请求状态的对象
private NumSignel numSignel;//
/**
* 接收 url , num-访问次数,linktype 访问类型(http/https),requesttype 请求类型(get/post),cookie--登录用的cookie
* numAcc--请求正常的状态记录对象(200),numNoFound--页面未找到的状态记录对象(404),numTimeout--超时的状态记录对象(其实没有用,不知道什么时候才算超时),numOther--之外的状态记录对象
* numSingel--线程数量的记录对象 用于获取线程全部请求完毕这个状态
* */
LinkThread(String url,int num,boolean linkType,boolean RequestType,int timeOut,String cookie,NumAcc numAcc,NumNoFound numNoFound,NumTimeout numTimeout,NumOther numOther,NumSignel numSignel){
this.url=url;
this.linkType=linkType;
this.requestType=requestType;
this.timeOut=timeOut;
this.cookie=cookie;
this.num=num;
this.numAcc=numAcc;
this.numNoFound=numNoFound;
this.numOther=numOther;
this.numSignel=numSignel;
}
/**
* 线程执行的主体
* 模拟一次并发的多次访问,并记录每次请求返回的状态
*
* */
public void run(){
try{
while(0!=this.num--){
URL linkUrl = new URL(this.url);
HttpURLConnection link = (HttpURLConnection)linkUrl.openConnection();
if(!this.linkType){
link = (HttpsURLConnection)link;
}
//设置参数
if(!this.requestType){
link.setRequestMethod("POST");
}else{
link.setRequestMethod("GET");
}
link.setConnectTimeout(this.timeOut);
if(null!=this.cookie){
link.setRequestProperty("cookie", this.cookie);
}
//执行连接
link.connect();
//状态记录
System.out.println(link.getResponseCode());
if(200==link.getResponseCode()){
synchronized(this.numAcc){
this.numAcc.numAcc++;
}
}else if(404==link.getResponseCode()){
synchronized(this.numNoFound){
this.numNoFound.numNoFound++;
}
}else{
synchronized(this.numOther){
this.numOther.numOther++;
}
}
//减去一个线程的计数
synchronized(this.numSignel){
this.numSignel.numSignel--;
}
}
}catch(IOException e){
synchronized(this.numOther){
this.numOther.numOther++;
}
}
}
}
还有几个状态记录的类
/**
* numAcc
* 记录200状态的请求次数
**/
public class NumAcc{
public int numAcc;
private static NumAcc object = new NumAcc();
private NumAcc(){
this.numAcc=0;
}
public static NumAcc getNumAcc(){
return object;
}
}
/**
* numnoFoun
* 记录404状态的请求次数
**/
class NumNoFound{
public int numNoFound;
private static NumNoFound object = new NumNoFound();
private NumNoFound(){
this.numNoFound=0;
}
public static NumNoFound getNumNoFound(){
return object;
}
}
/**
* numOther
* 记录其它状态的请求次数
* */
class NumOther{
public int numOther;
private static NumOther object = new NumOther();
private NumOther(){
this.numOther=0;
}
public static NumOther getNumOther(){
return object;
}
}
/**
* NumSignel
* 创建的线程数
* */
class NumSignel{
public int numSignel;
private static NumSignel object = new NumSignel();
private NumSignel(){
this.numSignel=0;
}
public static NumSignel getNumSignel(){
return object;
}
}
/**
* numTimeout
* 记录超时的请求次数
* */
class NumTimeout{
public int numTimeout;
private static NumTimeout object = new NumTimeout();
private NumTimeout(){
this.numTimeout=0;
}
public static NumTimeout getNumTimeout(){
return object;
}
}
不知道为什么,
请求总是返回405状态码,
说请求的方式不对,
程序里不是已经确定是get请求了,
为什么会出这个状态码??