java的ssl的一点问题,没搞定

服务端是一个基于mina开发的socket server, 连接采用ssl加密。 在服务端即配置了mina的SSLFilter.

客户端的c程序访问的时候,是一切正常的。 而使用java作为客户端,不论是用mina还是直接自己写SSlContext获得socketFactory,结果都一样,有2个怪异的现象。
1. tcp的3次握手完成之后,应该开始进行ssl握手,但是客户端发出的clientHello包却经过了明显的延迟(170ms左右)才发出来。
2. 最后的结束,不是正确的tcp 4次挥手 fin/ack/fin/ack。 而是最后以rst结束。 (猜测是ssl的 close_notify包处理的不正确?)
尽管有这2个现象的存在,但数据的交互却完全是正常的。 如果不是用tcpdump去抓包的话,甚至不会知道底下出现了这样怪异的现象。google也找不到有用的信息。

tcpdump抓包结果如下:

20:12:31.895990 IP 10.18.65.39.47552 > 10.108.90.237.8080: S 1674804305:1674804305(0) win 29200 <mss 1460,sackOK,timestamp 7589134 0,nop,wscale 7>
20:12:31.896079 IP 10.108.90.237.8080 > 10.18.65.39.47552: S 1592612872:1592612872(0) ack 1674804306 win 14480 <mss 1460,sackOK,timestamp 1355739116 7589134,nop,wscale 7>
20:12:31.896521 IP 10.18.65.39.47552 > 10.108.90.237.8080: . ack 1 win 229 <nop,nop,timestamp 7589134 1355739116>
20:12:32.066097 IP 10.18.65.39.47552 > 10.108.90.237.8080: P 1:155(154) ack 1 win 229 <nop,nop,timestamp 7589177 1355739116>
20:12:32.066192 IP 10.108.90.237.8080 > 10.18.65.39.47552: . ack 155 win 122 <nop,nop,timestamp 1355739287 7589177>
20:12:32.095820 IP 10.108.90.237.8080 > 10.18.65.39.47552: P 1:1192(1191) ack 155 win 122 <nop,nop,timestamp 1355739316 7589177>
20:12:32.096437 IP 10.18.65.39.47552 > 10.108.90.237.8080: . ack 1192 win 251 <nop,nop,timestamp 7589184 1355739316>
20:12:32.114039 IP 10.18.65.39.47552 > 10.108.90.237.8080: P 155:230(75) ack 1192 win 251 <nop,nop,timestamp 7589189 1355739316>
20:12:32.114100 IP 10.18.65.39.47552 > 10.108.90.237.8080: P 230:236(6) ack 1192 win 251 <nop,nop,timestamp 7589189 1355739316>
20:12:32.114124 IP 10.18.65.39.47552 > 10.108.90.237.8080: P 236:289(53) ack 1192 win 251 <nop,nop,timestamp 7589189 1355739316>
20:12:32.114572 IP 10.108.90.237.8080 > 10.18.65.39.47552: . ack 289 win 122 <nop,nop,timestamp 1355739335 7589189>
20:12:32.124198 IP 10.108.90.237.8080 > 10.18.65.39.47552: P 1192:1198(6) ack 289 win 122 <nop,nop,timestamp 1355739345 7589189>
20:12:32.161404 IP 10.18.65.39.47552 > 10.108.90.237.8080: . ack 1198 win 251 <nop,nop,timestamp 7589201 1355739345>
20:12:32.161459 IP 10.108.90.237.8080 > 10.18.65.39.47552: P 1198:1251(53) ack 289 win 122 <nop,nop,timestamp 1355739382 7589201>
20:12:32.161926 IP 10.18.65.39.47552 > 10.108.90.237.8080: . ack 1251 win 251 <nop,nop,timestamp 7589201 1355739382>
20:12:32.163208 IP 10.18.65.39.47552 > 10.108.90.237.8080: P 289:406(117) ack 1251 win 251 <nop,nop,timestamp 7589201 1355739382>
20:12:32.171213 IP 10.108.90.237.8080 > 10.18.65.39.47552: P 1251:1336(85) ack 406 win 122 <nop,nop,timestamp 1355739392 7589201>
20:12:32.186214 IP 10.18.65.39.47552 > 10.108.90.237.8080: P 406:752(346) ack 1336 win 251 <nop,nop,timestamp 7589207 1355739392>
20:12:32.226172 IP 10.108.90.237.8080 > 10.18.65.39.47552: . ack 752 win 130 <nop,nop,timestamp 1355739447 7589207>
20:12:32.228869 IP 10.108.90.237.8080 > 10.18.65.39.47552: P 1336:1554(218) ack 752 win 130 <nop,nop,timestamp 1355739449 7589207>
20:12:32.232552 IP 10.18.65.39.47552 > 10.108.90.237.8080: P 752:789(37) ack 1554 win 270 <nop,nop,timestamp 7589218 1355739449>
20:12:32.232613 IP 10.108.90.237.8080 > 10.18.65.39.47552: . ack 789 win 130 <nop,nop,timestamp 1355739453 7589218>
20:12:32.232795 IP 10.18.65.39.47552 > 10.108.90.237.8080: F 789:789(0) ack 1554 win 270 <nop,nop,timestamp 7589218 1355739449>
20:12:32.233915 IP 10.108.90.237.8080 > 10.18.65.39.47552: P 1554:1591(37) ack 790 win 130 <nop,nop,timestamp 1355739454 7589218>
20:12:32.234091 IP 10.108.90.237.8080 > 10.18.65.39.47552: F 1591:1591(0) ack 790 win 130 <nop,nop,timestamp 1355739454 7589218>
20:12:32.234515 IP 10.18.65.39.47552 > 10.108.90.237.8080: R 1674805095:1674805095(0) win 0
20:12:32.234594 IP 10.18.65.39.47552 > 10.108.90.237.8080: R 1674805095:1674805095(0) win 0

怪事。 如果客户端不调用socket.close(),在客户端java进程结束的时候, 却是以正常的fin/ack结束连接。

(全文完)

Java发送ios推送消息(APN)的代码示例

实际项目应用中,应该考虑使用开源项目java-apns:https://github.com/notnoop/java-apns
千万不要用一个叫JAVAPNS的项目。这个开源项目的代码非常烂,每次发送消息都重新建立socket连接。在apple的文档中,都明确的说了会把这种行为当作dos攻击行为。性能差就更不用说了。
ios手机上要安装对应的应用。该应用与.p12证书文件应该匹配。
apple官方的,关于APN服务,和apn的feedback的文档在这个地方:https://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/CommunicatingWIthAPS.html#//apple_ref/doc/uid/TP40008194-CH101-SW3
java版本发送apn推送代码示例:
继续阅读“Java发送ios推送消息(APN)的代码示例”

多线程情况下HttpClient的使用

3.x版本的httpclient属于apache的commons项目。 从4.x开始,httpclient被转移到了httpcomponent项目下。 api也发生了重大的变化。 http 3.x已经不推荐使用。使用3.x版本的地方,官方建议都升级到4.x版本。

本文的api也都基于4.x版本。下面是一个最simple的案例:

继续阅读“多线程情况下HttpClient的使用”

java中的CountDownLatch

java中的CountDownLatch是一个倒计数,它位于java.util.concurrent包中。构造一个CountDownLatch对象的时候,可以指定一个倒计数的起点,即指定一个整数的count,每次对象的countDown()方法被调用,count就减一。 在count减到0之前,任何调用了CountDownLatch对象的await方法的对象都被阻塞。
继续阅读“java中的CountDownLatch”

java中的Future

有这样一种需求,需要调用某一个耗时的方法,但又不希望当前线程无限期的等待下去,希望设置一个过期时间,比如设置为2000ms,那么就只等待2000ms,当然如果方法很快就返回了就可以立即继续执行下面的代码。这是一个标准的java的Future。Future位于java.util.concurrent包中。代码示例如下:


    public static void main(String[] args) {

        ExecutorService executor = Executors.newSingleThreadExecutor();

        Future<String> future = executor.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return doStaff();
            }
        });

        // we can do someting here while waiting.

        String result = null;
        try {
            result = future.get(1000, TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println(result);
        executor.shutdown();
    }

    public static String doStaff() {
        try {
            Thread.sleep(800);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "this is result.";
    }

在上述的代码中,main方法线程只会等待1000ms。如果再1000ms内doStaff方法没有返回,那么就会抛出一个java.util.concurrent.TimeoutException。关于Future的用法,可以参看java源代码中的注释。此外Future接口还有一个实现是FutureTask,可以参考。
(全文完)