About neohope

一直在努力,还没想过要放弃...

正向代理和反向代理

1、forward proxy
正向代理是一个位于client和origin server之间的proxy,为了从origin server取得内容,client向proxy发送一个请求并指定目标(origin server),然后proxy向origin server转交request并将获得的resopnse返回给client。client必须要进行一些特别的设置才能使用正向代理。

2、reverse proxy
反向代理对于client而言就像是origin server,并且clinet不需要进行任何特别的设置。client向反proxy发送普通请求,接着proxy将判断向何处(origin server)转交request,并将response返回给client,proxy在client看起来就像origin server一样。

3、两者区别
从网络角色来讲:
正向代理隐藏的是client,clinet可以感觉到正向代理的存在,proxy对server隐藏了client的细节。
反向代理隐藏的是origin server,client感觉不到反向代理的存在,proxy对clinet隐藏了server的细节。

从用途上来讲:
正向代理的典型用途是为在防火墙内的局域网客户端提供访问Internet的途径,正向代理还可以使用缓冲特性减少网络使用率。
反向代理的典型用途是将防火墙后面的服务器提供给Internet用户访问,反向代理还可以为后端的多台服务器提供负载平衡,或为后端较慢的服务器提供缓冲服务。另外,反向代理还可以启用高级URL策略和管理技术,从而使处于不同web服务器系统的web页面同时存在于同一个URL空间下。

从安全性来讲:
正向代理允许client通过它访问任意网站并且隐藏client自身,因此你必须采取安全措施以确保仅为经过授权的客户端提供服务。
反向代理对clinet都是透明的,clinet并不知道自己访问的是一个代理。

4、透明代理
透明代理技是指客户端感觉不到代理的存在,不需要在浏览器中设置任何代理,客户只需要设置缺省网关,客户的访问外部网络的数据包被发送到缺省网关,而这时缺省网关运行有一个代理服务器,数据实际上被被重定向到代理服务器的代理端口,即由本地代理服务器向外请求所需数据然后拷贝给客户端。理论上透明代理可以对任何协议通用。一般透明代理用于防火墙技术比较多。

Nginx中的upstream

Nginx中upstream有以下几种方式:

1、轮询(weight=1)
默认选项,当weight不指定时,各服务器weight相同,
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。

upstream bakend {
server 192.168.1.10;
server 192.168.1.11;
}

2、weight
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
如果后端服务器down掉,能自动剔除。
比如下面配置,则1.11服务器的访问量为1.10服务器的两倍。

upstream bakend {
server 192.168.1.10 weight=1;
server 192.168.1.11 weight=2;
}

3、ip_hash
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session不能跨服务器的问题。
如果后端服务器down掉,要手工down掉。

upstream resinserver{
ip_hash;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
}

4、fair(第三方插件)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。

upstream resinserver{
server 192.168.1.10:8080;
server 192.168.1.11:8080;
fair;
}

5、url_hash(第三方插件)
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存服务器时比较有效。
在upstream中加入hash语句,hash_method是使用的hash算法

upstream resinserver{
server 192.168.1.10:8080;
server 192.168.1.11:8080;
hash $request_uri;
hash_method crc32;
}

设备的状态有:
1.down 表示单前的server暂时不参与负载
2.weight 权重,默认为1。 weight越大,负载的权重就越大。
3.max_fails 允许请求失败的次数默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误
4.fail_timeout max_fails次失败后,暂停的时间。
5.backup 备用服务器, 其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。

双击运行的jar包

让jar包可以双击运行,其实很简单

1.写一个manifest.mf文件,里面只有两行
第一行为Main-Class
第二行为空行
注意冒号后面有一个空格

Main-Class: YourClassName

2.用jar命令打包

jar -cvfm xxx.jar xxx.mf classfiles

3.然后就可以运行了

要注意,双击运行jar包时,
系统会调用javaw而不是java,
因此命令行输出是看不到的。

About Unix

三大UNIX为:
IBM AIX, HP UNIX,SUN Solaris

UNIX,BSD,Linux被统称为×nix系统。

BSD与Linux系统的区别:
BSD is what you get when a bunch of UNIX hackers sit down to try to port a UNIX system to the PC.
Linux is what you get when a bunch of PC hackers sit down and try to write a UNIX system for the PC.

JNI简单例子1

1.Java代码CallApi.java

class CallApi{
    private native String showMessageBox(String msg);
    private native double getRandomDouble();

    static{
        try{
            System.loadLibrary("CallApi");
            System.out.println("Loaded CallApi");
        }catch(UnsatisfiedLinkError e){
            //nothing to do
            System.out.println("Couldn't load CallApi");
            System.out.println(e.getMessage());
        }
    }

    public static void main(String args[]){
        CallApi api = new CallApi();
        double randomNumber = api.getRandomDouble();
        String retval = api.showMessageBox("Hello from Java!\n"+
            "The native random number: "+randomNumber);
            System.out.println("The native string: "+retval);
    }
}

2.生成dll的CallApi.h文件

javah -classpath . -jni CallApi
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class CallApi */

#ifndef _Included_CallApi
#define _Included_CallApi
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     CallApi
 * Method:    showMessageBox
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_CallApi_showMessageBox
  (JNIEnv *, jobject, jstring);

/*
 * Class:     CallApi
 * Method:    getRandomDouble
 * Signature: ()D
 */
JNIEXPORT jdouble JNICALL Java_CallApi_getRandomDouble
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

3.手写dll的CallApi.c文件

#include"CallApi.h"
#include <windows.h>
#include <time.h>

//#pragma comment(lib,"user32.lib")

JNIEXPORT jstring JNICALL Java_CallApi_showMessageBox
  (JNIEnv *env, jobject thisObject, jstring js)
{
    //first convert jstring to const char for use in MessageBox
    const jbyte* argvv = (*env)->GetStringUTFChars(env, js, NULL);
    char* argv =(char *) argvv;

    //Call MessageBoxA
    MessageBox(NULL, argv, "Called from Java!", MB_ICONEXCLAMATION | MB_OK);
    return js;

}


JNIEXPORT jdouble JNICALL Java_CallApi_getRandomDouble
  (JNIEnv *env, jobject thisObject)
{
    double num1;
    srand((unsigned)(time(0)));
    num1 = ((double)rand()/(double)RAND_MAX);

    return num1;
}

4.编译
注意1:要引用jdk下的include目录下文件,因此要增加引用文件路径
注意2:用MT而不是MD

5.运行

java -Djava.library.path=. CallApi

创建进程API

Winexec
UINT WinExec(
LPCSTR lpCmdLine, 
UINT uCmdShow ); 

ShellExecute
HINSTANCE ShellExecute(
HWND hwnd, 
LPCTSTR lpOperation, 
LPCTSTR lpFile,
LPCTSTR lpParameters, 
LPCTSTR lpDirectory,
INT nShowCmd ); 

CreateProcess
BOOL CreateProcess(LPCTSTR lpApplicationName, 
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo, 
LPPROCESS_INFORMATION lpProcessInformation
); 

CPP类型转换

1、static_cast

这是应该首先选用的转换方式,一般用于在相关类型间进行转换或在继承链中进行转换。
其运作方式类似于隐式转换 (比如int转为float,或指针转换为 void*), 而且它可以调用显示转换(当然包括隐式转换)。

在很多情况下, 显示声明static_cast是不必要的,
但有一点需要指出的是应当尽量避免type(XXX) 与(type)XXX 语法(详情见下文)。
然而type(XXX,YYY) 是安全的,而且一定会去调用构造函数。

static_cast也可以在父类及子类之间进行。 当子类向父类转换时是可以顺利进行的。但父类向子类转换时,只要子类没有继承virtual父类,就可以一直进行。但是它从父类转为子类时,不会做任何检查,即使类型不完全匹配。

2、const_cast

用来向一个变量增加或删除const属性。 其他任何C++ casts都无法完成此任务。
需要指出的是,当变量为const,该操作符是未定义的。

用它来声明一个非const类型的const引用是安全的。
当重载const类型的类成员变量时,该转换十分有用。
它也可以用来把一个对象增加const属性,比如调用重载的方法。

const_cast也适用于volatile,但很少见。

3、dynamic_cast

一般用来解决多态问题。你可以把指针或参考转换为任何继承链上的类型。
(一个多态类型至少用一个虚函数,无论是声明还是继承的)。
当从子类转换为父类时,dynamic_cast一定会成功。但从父类转换为子类,dynamic_cast会确保对象为子类的一个完全实现。

dynamic_cast将返回其是否可能。如果无法转换,他将返回NULL(对指针),或抛出std::bad_cast异常(对参考)。

dynamic_cast有一些限制:
如果在继承链中,同一类型有多个对象(dreaded diamond)同时你没有使用虚接口,转换不会进行。
他也只能应用于public继承,当protect或private继承时,会失败。

注意:
dynamic_cast需要编译器支持RTTI(运行时类型识别)。

4、reinterpret_cast

这是最危险的转换方式,慎用。 它直接把一种类型转换为另一种
(比如把值从一种指针转换为另一种指针,或把指针储存在int中, 或其他让人讨厌的事情)

使用reinterpret_cast,唯一能保证的是,当你从结构转回为原类型时,你能得到相同的结果。
当然,reinterpret_cast也有一些转换无法进行。

他通常用于比较奇怪的转换,或bit操作,比图把raw数据流转换为实际数据,或把数据储存在对齐指针的低字节。
当其他转换无法使用时,可以尝试reinterpret_cast

5、C-style cast
C-style cast 是使用(type)object 或 type(object)的转换方式。
C-style cast 被定义为下列转换中第一个成功返回的:
const_cast
static_cast
static_cast, then const_cast
reinterpret_cast
reinterpret_cast, then const_cast

在一些时候,他可以被用来替代其他casts,但用于他最后可能会调用reinterpret_cast(应显示调用),因此C-style cast是十分危险的。
除非你能保证,不会调用reinterpret_cast,或者reinterpret_cast一定会失败,否则不要轻易使用。即使如此,也应该考虑显示调用上面的转换。

当使用static_cast时,C-style casts 也可以忽略权限控制,这意味着他可以进行其他cast无法进行的操作。
这是避免C-style casts的一个不错的理由。

(翻译自Stack Overflow的一个帖子,水平有限,哈哈)

参考资料:
http://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-and-reinterpret-cast-be-used
http://www.cplusplus.com/doc/tutorial/typecasting/
http://en.wikibooks.org/wiki/C%2B%2B_Programming/Programming_Languages/C%2B%2B/Code/Statements/Variables/Type_Casting

统计Excel工时的VBA脚本

很久很久以前,用于统计公司工时的一个VBA脚本,只使用了一小段时间。
代码写的有些傻傻的,哈哈哈。

Sub Summary()

    '统计行数
    Dim TotalLine As Integer
    TotalLine = 1
    
    Dim i, j As Integer
    i = 1
    j = 1
    
    Dim name As String
    
    '清空上次统计信息
    Sheet32.Range("A2:F301").ClearContents
    
    '计算人名
    name = Sheet1.Cells(2, 2)
    name = Right(name, Len(name) - 3)

    '遍历所有sheets
    For i = 1 To 31
    
        '每个sheets中有效行数
        For j = 4 To 12
        
            '判断一行是否为空
            If (Worksheets(i).Cells(j, 1) = "" And Worksheets(i).Cells(j, 2) = "" And Worksheets(i).Cells(j, 3) = "" And Worksheets(i).Cells(j, 4) = "" And Worksheets(i).Cells(j, 5) = "") Then
                '空行,不做处理
            Else
                '非空行,进行统计
                TotalLine = TotalLine + 1
                Sheet32.Cells(TotalLine, 1) = Worksheets(i).Cells(j, 4)
                Sheet32.Cells(TotalLine, 2) = Worksheets(i).Cells(j, 5)
                Sheet32.Cells(TotalLine, 3) = name
                
                If (Worksheets(i).Cells(j, 2) = "/") Then
                    Sheet32.Cells(TotalLine, 4) = "0"
                Else
                    Sheet32.Cells(TotalLine, 4) = Worksheets(i).Cells(j, 2)
                End If
                
                If (Worksheets(i).Cells(j, 3) = "/") Then
                    Sheet32.Cells(TotalLine, 5) = "0"
                Else
                    Sheet32.Cells(TotalLine, 5) = Worksheets(i).Cells(j, 3)
                End If

                Sheet32.Cells(TotalLine, 6) = Sheet32.Cells(TotalLine, 4) + Sheet32.Cells(TotalLine, 5)
            End If
        Next j
    Next i
    
    '清空上次统计信息
    Sheet33.Range("A2:F301").ClearContents
    
    '任务行数
    Dim TaskLine As Integer
    TaskLine = 1
    
    '本条记录是否添加
    Dim bFind As Boolean
    
    '效率低下的循环
    For i = 2 To TotalLine
        bFind = False
        For j = 2 To TaskLine
            If (Sheet32.Cells(i, 1) = Sheet33.Cells(j, 1) And Sheet32.Cells(i, 2) = Sheet33.Cells(j, 2)) Then
                Sheet33.Cells(j, 4) = Sheet33.Cells(j, 4) + Sheet32.Cells(i, 4)
                Sheet33.Cells(j, 5) = Sheet33.Cells(j, 5) + Sheet32.Cells(i, 5)
                Sheet33.Cells(j, 6) = Sheet33.Cells(j, 6) + Sheet32.Cells(i, 6)
                bFind = True
                Exit For
            End If
        Next j
        
        If (Not bFind) Then
                TaskLine = TaskLine + 1
                Sheet33.Cells(TaskLine, 1) = Sheet32.Cells(i, 1)
                Sheet33.Cells(TaskLine, 2) = Sheet32.Cells(i, 2)
                Sheet33.Cells(TaskLine, 3) = Sheet32.Cells(i, 3)
                Sheet33.Cells(TaskLine, 4) = Sheet32.Cells(i, 4)
                Sheet33.Cells(TaskLine, 5) = Sheet32.Cells(i, 5)
                Sheet33.Cells(TaskLine, 6) = Sheet32.Cells(i, 6)
        End If
        
    Next i
    
    MsgBox ("任务完成咯 :)")
    
End Sub