我认为LengthFieldBasedFrameDecoder的正确使用方式

LengthFieldBasedFrameDecoder是Netty提供的便于编写一般基于长度的协议解码器,最近我发现在搜索引擎上搜到的使用方式代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Override
protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
if (in == null) {
return null;
}
//HEADER_SIZE 包头大小
if (in.readableBytes() < HEADER_SIZE) {
throw new Exception("readable bytes length less than header size");
}
int length = in.readInt();
if (in.readableBytes() < length) {
throw new Exception("body length less than length declared in header");
}
ByteBuf buf = in.readBytes(length);
byte[] req = new byte[buf.readableBytes()];
buf.readBytes(req);
String body = new String(req, "UTF-8");
Message msg = new Message(flag, type, body);
return msg;
}

继续阅读全文 »

tcpcopy在阿里云ECS中的使用

tcpcopy是一个用于回放现网流量的工具,关于她的介绍和原理移步tcpcopy
官方文档也不多,别管理解多少看还是要看的。
tcpcopy的使用离不开tcpdump,离线模式下要用tcpdump抓取tcp包用于回放,在使用是也要用tcpdump进行抓包调试使tcpcopy能正常工作。
安装tcpcopy时需注意一点如果使用离线模式要在configure时加上–offline。
现在我已经用tcpdump -i eth0 tcp and dst port 38810 -w online.pcap从现网机器dump下来的tcp流量。
先在我的虚拟机上试一下,我是在一台机器上跑intercept和tcpcopy,用的虚拟机软件是VMware。网络使用的NAT模式

先启动intercept
/usr/local/intercept/sbin/intercept -i eno16777736 -F ‘tcp and src port 38810’ -l intercept.log
查看日志没有错误

然后启动tcpcopy(参数意义可以通过tcpcopy -h 查看)
/usr/local/tcpcopy/sbin/tcpcopy -x 38810-192.168.95.130:38810 -s 192.168.95.130 -c 192.168.10.123 -i online.pcap -a 10 -n 5 -l tcpcopy.log

继续阅读全文 »

造轮子之HttpServer(一)

这里的HttpServer就是一个解析http协议的程序,大家都知道http协议是基于tcp/ip协议的。tcp/ip算是比较底层的了,操作系统基本都通过socket对其进行管理,用java很容易就能写一个简单的server

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package cc.vicp.vncnliu.attackServer;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

/**
* 简单的http解析器
* created on 2016/8/10 15:11.
*
* @author vncnliu
* @version default 1.0.0
*/
public class HttpServer {

public static void main(String[] args) {
try {
//绑定端口
ServerSocket serverSocket = new ServerSocket(8080);
while (true){
Socket socket = serverSocket.accept();
new Thread(new MessageHandle(socket)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}

static class MessageHandle implements Runnable {

Socket socket;
MessageHandle(Socket socket){
this.socket = socket;
}

public void run() {
StringBuilder echo = new StringBuilder();
BufferedReader in = null;
PrintWriter out = null;
try {
in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
out = new PrintWriter(this.socket.getOutputStream(),true);
String body = null;
while(true) {
body = in.readLine();
if(body==null){
break;
}
System.out.println(body);
}
echo.append("HTTP/1.1 200 \r\n");
echo.append("Content-Type: text/html\r\n");
echo.append("Content-Length: 109\r\n");
echo.append("\r\n");
echo.append("<html>");
echo.append("<head>");
echo.append("<title>hello</title>");
echo.append("</head>");
echo.append("<body>");
echo.append("<center>");
echo.append("<b1>Welcome to my home page.</b1>");
echo.append("</center>");
echo.append("</body>");
echo.append("</html>");
out.println(echo.toString());
} catch (Exception e) {
e.printStackTrace();
}
finally {
System.out.println("链接关闭");
if(in!=null){
try {
in.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
if(out!=null){
out.close();
}
if(this.socket!=null){
try {
this.socket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
this.socket=null;
}
}
}
}
}

继续阅读全文 »

java读取部分excel文件实现excel文件的预览

一个报表导入的需求要求在保存导入数据前可以预览部分数据,本来直接用poi从文件得到workbook后直接取前十行返回预览。做完后发现在excel表格非常大的时候从流构建workbook要挺长时间,体验有点不好。要是能读取部分流展示就完美了。看了一下poi构建workbook的源码,自己写了个测试用例结果失败了……好在有google找到了这个Excel Streaming Reader使用起来还是比较简单的
添加maven库

1
2
3
4
5
6
7
<dependencies>
<dependency>
<groupId>com.monitorjbl</groupId>
<artifactId>xlsx-streamer</artifactId>
<version>0.2.12</version>
</dependency>
</dependencies>

继续阅读全文 »

junit多线程测试

工作中难免要考虑一些方法是不是线程安全的,这时可以用junit进行简单的多线程测试。方式有很多种,可以使用grobo-utils不过grobo-utils没有放到maven公共仓库里,所以在maven项目中使用时还要把jar包打到本地仓库里,难免有些麻烦。
其实还可以通过CountDownLatch很方便的实现。比如我写一个基于LinkedList简单的队列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package common;

import com.google.common.base.Strings;

import java.util.LinkedList;
import java.util.List;

/**
* All right reserved.
* Created by vncnliu@gmail.com on 2016/4/12.
*/
public class LightQueueSynced {

private static List<String> QUEUE_LIST = new LinkedList<String>();

public static List<String> getQueueList(){
return QUEUE_LIST;
}

public static synchronized void queue(String key){
//System.out.println("add:"+seatNo);
if(!Strings.isNullOrEmpty(key)&&!QUEUE_LIST.contains(key)){
QUEUE_LIST.add(key);
}
}

public static synchronized void remove(String key){
QUEUE_LIST.remove(key);
}

public static synchronized String pollFirst(){
if(QUEUE_LIST.size()==0){
return null;
}
String seatNo = QUEUE_LIST.get(0);
if(!Strings.isNullOrEmpty(seatNo)){
QUEUE_LIST.remove(0);
}
return seatNo;
}
}

继续阅读全文 »