HttpClient 使用socks代理

      HttpClient使用HTTP代理很简单,但是用socks代理就稍微复杂点。下面是参考HttpClient官方的例子,在其基础上增加了代理验证。

import java.io.IOException;
import java.net.Authenticator;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;

public class SocksProxy {
   
    public static void main(String[] args) throws Exception {       
        DefaultHttpClient httpclient = new DefaultHttpClient();
       
        try {
            Authenticator.setDefault(new SocksAuthenticator("user", "pwd"));
       
            httpclient.getParams().setParameter("socks.host", "socksHost");
            httpclient.getParams().setParameter("socks.port", sockPort);
       
            httpclient.getConnectionManager().getSchemeRegistry().register(
                    new Scheme("http", 80, new SocksSchemeSocketFactory()));
           
            HttpGet get = new HttpGet("http://city.ip138.com/city.asp");
            HttpResponse rsp = httpclient.execute(get);
            HttpEntity entity = rsp.getEntity();
            System.out.println(rsp.getStatusLine());
            Header[] headers = rsp.getAllHeaders();
            for (int i = 0; i < headers.length; i++) {
                System.out.println(headers[i]);
            }
            System.out.println("——————————");
           
            if (entity != null) {
                System.out.println(EntityUtils.toString(entity, "gb2312"));
            }
        } finally {
            httpclient.getConnectionManager().shutdown();
        }
       
    }
   
    static class SocksSchemeSocketFactory implements SchemeSocketFactory {

        @Override
        public Socket connectSocket(final Socket socket, final InetSocketAddress remoteAddress,
                final InetSocketAddress localAddress, final HttpParams params) throws IOException,
                UnknownHostException, ConnectTimeoutException {
            // TODO Auto-generated method stub
            if (remoteAddress == null) {
                throw new IllegalArgumentException("Remote address may not be null");
            }
            if (params == null) {
                throw new IllegalArgumentException("HTTP parameters may not be null");
            }
            Socket sock;
            if (socket != null) {
                sock = socket;
            } else {
                sock = createSocket(params);
            }
            if (localAddress != null) {
                sock.setReuseAddress(HttpConnectionParams.getSoReuseaddr(params));
                sock.bind(localAddress);
            }
            int timeout = HttpConnectionParams.getConnectionTimeout(params);
            try {
                sock.connect(remoteAddress, timeout);
            } catch (SocketTimeoutException ex) {
                throw new ConnectTimeoutException("Connect to " + remoteAddress.getHostName() + "/" + remoteAddress.getAddress() + " time out");
            }
            return sock;
        }

        @Override
        public Socket createSocket(final HttpParams params) throws IOException {
            // TODO Auto-generated method stub
            if (params == null) {
                throw new IllegalArgumentException("Http parameters may not be null");
            }
            String proxyHost = (String) params.getParameter("socks.host");
            Integer proxyPort = (Integer) params.getParameter("socks.port");
           
            InetSocketAddress socksAddr = new InetSocketAddress(proxyHost, proxyPort);
            Proxy proxy = new Proxy(Proxy.Type.SOCKS, socksAddr);
            return new Socket(proxy);
        }

        @Override
        public boolean isSecure(final Socket sock) throws IllegalArgumentException {
            // TODO Auto-generated method stub
            return false;
        }   
       
    }
   
    static class SocksAuthenticator extends Authenticator {
        private String username;
        private String    password;

        public SocksAuthenticator(final String user, final String pass) {
            username = user;
            password = pass;
        }

        protected PasswordAuthentication getPasswordAuthentication() {
            if (username != null && password != null) {
                return new PasswordAuthentication(username, password.toCharArray());
            }
            else {
                return null;
            }
        }
    }
}

Socks验证使用的方式和使用Java全局的Socks代理验证方式是一样的。

修改Apache XmlRpc支持HttpClient 4.1.3

xmlrpc-client-3.1.3_rs

        好不容易找到了解决XmlRpc支持自定义HttpClient的方法,结果发现支持的是3.x的。HtppClient 3.x已经不被推荐使用了。HttpClient更新到4.x之后同之前的结构有很大的区别,修改起来还是很痛苦的。花了一天时间,终于改好了。

        修改的文件只有两个:XmlRpcCommonsTransport.java 和 XmlRpcCommonsTransportFactory.java 。主要的修改在 XmlRpcCommonsTransport.java 中。代码我贴上来了。可以用来作为 HttpClient 从3.x升级到4.x的参考。

(more…)

java xmlrpc 设置代理

        用apche的xmlrpc做客服端,居然一个代理把我难道了。用java系统代理,换代理太痛苦了,也不知道他是时候生效。百度google一圈下来就是没找到解决办法,和朋友说起这事,他居然一下子就找到了解决方法。其实也挺简单的。

XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
config.setServerURL( serverURL );

client = new XmlRpcClient();
client.setConfig( config );

XmlRpcCommonsTransportFactory transportFactory
= new XmlRpcCommonsTransportFactory( client );

HttpClient httpClient = new HttpClient();
HostConfiguration hostConfiguration = httpClient.getHostConfiguration();
hostConfiguration.setProxy( "proxy.example.com", 8088 );
hostConfiguration.setHost( serviceURL );

transportFactory.setHttpClient( httpClient );
client.setTransportFactory( transportFactory );

        xmlrpc可以设置使用httpclient发送请求,这样就好办多了。httpclient设置代理还是很方便的,要换代理重新new一个httpclient就好了。

解决方案原地址:http://mark.koli.ch/2008/12/howto-using-a-web-proxy-with-xml-rpc-java.html

SVN批量CHECKOUT和COMMIT SELL脚本

        上篇贴的SVN批量CHECKOUT的shell脚本使用是没什么问题,但是伪多线程却又问题。这次新需求添加了COMMIT步骤,结构变化有点大,而且完善了伪多线程。

#!/bin/bash

svnroot=svn
mkdir $svnroot
path=${PWD}

rm -rf tmp
mkdir tmp

file=saeAccount.txt
num=3

cat $file | while read line; do
        appname=`echo "$line" | awk ‘{print $1}’`
        user=`echo "$line" | awk ‘{print $2}’`
        pwd=`echo "$line" | awk ‘{print $3}’`
        svnpath=$svnroot/$appname
        #echo $svnpath
        command="svn checkout https://svn.XXXX.com/$appname $svnpath –username $user –password $pwd –quiet –no-auth-cache"
        run=0
        while [[ $run == 0 ]]; do
                for ((i=0; i<$num; i++)); do
                        #echo "for–"$i
                        if [ ! -f tmp/$i ]
                        then
                                #echo "file="$i
                                echo $1 > tmp/$i
                                {
                                        cur=$i
                                        echo $command
                                        $command >> saeV2.log
                                        mkdir $svnpath/1
                                        cd $svnpath
                                        svn add 1
                    cd $path
                                        rm -f tmp/$cur
                                        #echo "rm="$cur
                                } &
                                run=1
                                break;
                        fi
                done
                #echo sleep 1
                sleep 1
        done
done
wait
run=0
while [[ $run == 0 ]]; do
        for ((i=0; i<$num; i++)); do
                if [ -f tmp/$i ]
                then
                        run=0
                        sleep 1
                        echo "wait thread "$i" finish…"
                        break;
                else
                        run=1
                fi
        done
done
rm -rf tmp
echo "Task Termination!"

(more…)

SVN批量CheckOut shell脚本

        很久没看过写个shell,YokiDe有需求在Linux下批量CheckOut SVN数据,于是花些时间写了一个shell脚本,只要把更新的应用名,账号,密码写到account.txt文本里就可以了。

        这个脚本使用了伪多线程,因为对shell也不怎么熟悉,不知道这个效果怎么样。凑合着用还行吧。脚本比较简单,就不加说明了。

#!/bin/bash

file=account.txt
num=3
jobs=()

for ((i=0; i<$num; i++)); do
    jobs[i]=0
done

cat $file | while read line; do
        command=`echo "$line" | awk ‘{print "svn checkout https\072//svn\056xxxapp\056com/"$1" "$1" –username "$2" –password "$3" –quiet –no-auth-cache";}’`
        #echo $command
    run=0
    while [[ $run == 0 ]]; do
        for ((i=0; i<$num; i++)); do
            if [ ${jobs[$i]} == 0 ]
            then
                {
                    jobs[$i]=$!
                    cur=$i
                    echo $command
                    $command >> checkout.log
                    jobs[$cur]=0
                } &
                run=1
                break;
            fi
        done
        sleep 1
    done
done
wait

卸载重装TCP/IP协议

        有时候需要卸载重装TCP/IP协议,但是TCP/IP协议默然是不能直接卸载的,需要巧妙的修改一下TCP/IP协议的安装配置文件。

        TCP/IP协议的安装配置文件路径是:%windir%\inf\nettcpip.inf

        修改方法:用文本编辑器打开nettcpip.inf文件,查找[MS_TCPIP.PrimaryInstall]字段,再往后就能看到Characteristics = 0xA0,需要修改的就是这个0xA0值,只要把0xA0修改为0×80就可以卸载。

        卸载TCP/IP协议:网上邻居–右键–属性–本地连接–右键–属性,选择TCP/IP协议,可以看到卸载按钮是灰色的。点击安装,选择协议,再选择添加按钮,从硬盘选择,选择刚刚修改的%windir%\inf\nettcpip.inf 文件,然后就可以在列表中看到TCP/IP协议了,选择安装完后就看到卸载按钮已经可以选择了。卸载后重启就卸载完成了,不过卸载后,启动速度会变得很慢。

        安装TCP/IP协议:安装协议和卸载步骤一样,可以先把nettcpip.inf 文件还原,这样安装后也是不可以直接卸载的,不然可以轻易的被卸载。

视频请移步:http://jinda.tv/v/1580

不用分支语句求整数的绝对值

/*
*    不用分支语句求整数的绝对值
*/
int compute_int_abs_whihout_branching(int v)
{
    unsigned int r;
    //右移保存v的符号位到mask
    int const mask = v >> sizeof(int) * CHAR_BIT - 1;

    printf("mask<%d>\n", mask);
   
    //method 1
    //v>=0, mask=0, (v+0)^0=v
    //v<0, mask=-1,(v+(-1))^(-1)=减一取反
    r = (v + mask) ^ mask;
    printf("1:r<%d>\n", r);
   
    //method 2
    //v>=0, mask=0,(v^0)-0=v-0=v
    //v<0,mask=-1,(v^-1)-(-1)=取反加一
    r = (v ^ mask) - mask;
    printf("2:r<%d>\n", r);
   
    //method 3
    //最前面的()里同compute_int_sign种的method 4,根据符号值返回+1,-1
    //正正得正,负负得正
    r = (+1 | (v >> (sizeof(int) * CHAR_BIT - 1))) * v;
    printf("3:r<%d>\n", r);
   
    //method 4
    //使用了分支
    r = (v < 0) ? (1 + ((unsigned)(-1 - v))) : (unsigned)v;
    printf("4:r<%d>\n", r);

    return r;
}

检测两个整数的符号是否不同

/*
*    检测两个整数的符号是否不同
*  如果不同,返回1
*  如果相同,返回0
*/
int detect_two_int_hava_opposite_sign(int x, int y)
{
    //实际只需看符号位的异或运算结果
    //异或是相同为0,不同为1
    //所以x^y相同结果为整数,不同为负数
    //即x,y相同大于0,不同小于0
    return ((x^y) < 0);
}

判断整数的符号性质

#include <stdio.h>
#include <LIMITS.H>

/*
*    判断整数的符号性质
*/
int compute_int_sign(int v)
{
    int sign;

    //v = 0xFFFFFFFF;
    //v = 0;
    //v = 0x7FFFFFFF;

    //method 1
    //最简单的直接用v和0比较
    //负数sign=-1,非负数sign=0
    sign = -(v < 0);
    printf("1:sign<%d>\n", sign);

    //method 2
    //先把v强制成无符号型后移位只保留v的符号位,移位后转成int型再取反
    //由于无符号型移位都是补0,移植性很强
    //负数sign=-1,非负数sign=0
    sign = -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));
    printf("2:sign<%d>\n", sign);

    //method 3
    //直接移位只保留v的符号位,移植性没上一个好
    //负数sign=-1,非负数sign=0
    sign = v >> (sizeof(int) * CHAR_BIT - 1);
    printf("3:sign<%d>\n", sign);

    //method 4
    //同method 3
    //把结果|上了1,改变了结果使得:
    //负数sign=-1,非负数sign=1
    sign = +1 | (v >> (sizeof(int) * CHAR_BIT - 1));
    printf("4:sign<%d>\n", sign);

    //method 5
    //|之后的内容同 method 2 一样
    //|(v != 0)只是为了改变v>=0时的结果
    //v>0, 1|0 = 1
    //v=0, 0|0 = 0
    //所以改变结果后:
    //v大于0,sign=1
    //v等于0,sign=0
    //v小于0,sign=-1
    sign = (v != 0) | -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));
    printf("5:sign<%d>\n", sign);

    //method 6
    //|之后的内容同 method 3 一样
    //|(v != 0)同 method 5
    //v大于0,sign=1
    //v等于0,sign=0
    //v小于0,sign=-1
    sign = (v != 0) | (v >> (sizeof(int) * CHAR_BIT - 1));
    printf("6:sign<%d>\n", sign);

    //method 7
    //v大于0,sign=1-0=1
    //v等于0,sign=0-0=0
    //v小于0,sign=0-1=-1
    sign = (v > 0) - (v < 0);
    printf("7:sign<%d>\n", sign);

    return sign;
}

时间转换—-整数型(s)转tm类型

可用于java的整形时间转c的tm类型时间。java的时间精确度是ms。

——————————————————————————————–

lhtime.h

#ifndef __LHTIME_H__
#define __LHTIME_H__

/************************************************************************/
/* 时间处理函数                                                         */
/* lh_tm结构来自glibc中的tm结构                                         */
/* lhtime_Covent函数摘自glibc中的__offtime函数                          */
/* 精确度为s,而不是ms                                                  */
/************************************************************************/

#define    SECS_PER_HOUR    (60 * 60)
#define    SECS_PER_DAY    (SECS_PER_HOUR * 24)

typedef struct lh_tm
{
    int tm_sec;     /* seconds after the minute – [0,59] */
    int tm_min;     /* minutes after the hour – [0,59] */
    int tm_hour;    /* hours since midnight – [0,23] */
    int tm_mday;    /* day of the month – [1,31] */
    int tm_mon;     /* months since January – [0,11] */
    int tm_year;    /* years since 1900 */
    int tm_wday;    /* days since Sunday – [0,6] */
    int tm_yday;    /* days since January 1 – [0,365] */
    int tm_isdst;   /* daylight savings time flag */
}lh_tm;

# define __isleap(year)    \
    ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))

/*
*    设置时区,默认为东八区,+8
*/
void lhtime_setTimeZone(int16 zone);

/*
*    从秒数创建lh_tm结构
*/
lh_tm* lhtime_create(int32 ms);

/*
*    释放lh_tm结构
*/
#define lhtime_delete(lhtime)    FREE(lhtime)

/*
*    获取平常显示的年份
*/
#define lhtime_delete_getYear(lhtime)   (1900+((lh_tm*)(lhtime))->tm_year)

/*
*    获取平常显示的月份
*/
#define lhtime_delete_getMon(lhtime)   (1+((lh_tm*)(lhtime))->tm_mon)

#endif  /* __LHTIME_H__ */

lhtime.c

#include "lhtime.h"

const unsigned short int __mon_yday[2][13] =
{
    /* Normal years.  */
    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
        /* Leap years.  */
    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
};

int16 time_zone_offset = 8*SECS_PER_HOUR;

/* Compute the `struct tm’ representation of *T,
   offset OFFSET seconds east of UTC,
   and store year, yday, mon, mday, wday, hour, min, sec into *TP.
   Return nonzero if successful.  */
int8 lhtime_Covent (const int32* t, long int offset, lh_tm* tp)
{
    long int days, rem, y;
    const unsigned short int *ip;
   
    days = *t / SECS_PER_DAY;
    rem = *t % SECS_PER_DAY;
    rem += offset;
    while (rem < 0)
    {
        rem += SECS_PER_DAY;
        days;
    }
    while (rem >= SECS_PER_DAY)
    {
        rem -= SECS_PER_DAY;
        ++days;
    }
    tp->tm_hour = rem / SECS_PER_HOUR;
    rem %= SECS_PER_HOUR;
    tp->tm_min = rem / 60;
    tp->tm_sec = rem % 60;
    /* January 1, 1970 was a Thursday.  */
    tp->tm_wday = (4 + days) % 7;
    if (tp->tm_wday < 0)
        tp->tm_wday += 7;
    y = 1970;
   
#define DIV(a, b) ((a) / (b) – ((a) % (b) < 0))
#define LEAPS_THRU_END_OF(y) (DIV (y, 4) – DIV (y, 100) + DIV (y, 400))
   
    while (days < 0 || days >= (__isleap (y) ? 366 : 365))
    {
        /* Guess a corrected year, assuming 365 days per year.  */
        long int yg = y + days / 365 - (days % 365 < 0);
       
        /* Adjust DAYS and Y to match the guessed year.  */
        days -= ((yg - y) * 365
            + LEAPS_THRU_END_OF (yg - 1)
            - LEAPS_THRU_END_OF (y - 1));
        y = yg;
    }
    tp->tm_year = y - 1900;
    if (tp->tm_year != y - 1900)
    {
        /* The year cannot be represented due to overflow.  */
        //__set_errno (EOVERFLOW);
        return FALSE;
    }
    tp->tm_yday = days;
    ip = __mon_yday[__isleap(y)];
    for (y = 11; days < (long int) ip[y]; y)
        continue;
    days -= ip[y];
    tp->tm_mon = y;
    tp->tm_mday = days + 1;
    return TRUE;
}

/*
*    设置时区,默认为东八区,+8
*/
void lhtime_setTimeZone(int16 zone)
{
    time_zone_offset = zone*SECS_PER_HOUR;
}

/*
*    从秒数创建lh_tm结构
*/
lh_tm* lhtime_create(int32 ms)
{
    lh_tm* lhtime = NULL;

    MALLOC(&lhtime, sizeof(lh_tm));

    if (lhtime_Covent(&ms, time_zone_offset, lhtime) != TRUE)
    {
        lhtime_delete(&lhtime);
    }

//     if (lhtime != NULL)
//     {
//         PRINT("%d = %d year, %d mon, %d day, %d hour, %d min, %d sec", ms, 1900 + lhtime->tm_year, 1+lhtime->tm_mon, lhtime->tm_mday, lhtime->tm_hour, lhtime->tm_min, lhtime->tm_sec);
//     }

    return lhtime;
}