在此警告,协议栈代码具有一定危险性,只用于测试,运行于测试环境如虚拟机环境、内网测试环境。切勿用于真实环境或生产环境,如因此造成严重的后果本人一概不负责。
java 手撸TCP协议栈 (1) 调用pcap 完成了操作网卡的api,这是实现tcp协议栈的最重要的基础部分,有了这个基础,就可以飞起来了。
在这里继续介绍在(1)的基础上完整的实现一个简单的静态http服务器。
要完成一个http服务器,首先需要了解底层的协议是什么样子的,这里不贴协议格式了,csdn一搜一大把,各位自己倒杯茶慢慢搜慢慢看。
下面直接贴代码:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.PointerByReference;
public class HttpServerPCap {
static class SocketStruct{
public byte[] remoteMacAddr;
public byte[] remoteAddr;
public int remotePort;
public long identifyId;
public long seqenceId ;
public long acknowlegeId;
public ByteBuffer buffer;
public int status; // 1 received syn 2 estable 3 fin1 4 fin2
}
private static byte[] localMacAddr = {(byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, (byte)0x05, (byte)0x06};
private static byte[] localIp = {(byte)192, (byte)168, (byte)56, (byte)113};
private static int localPort = 8080;
private static Map<String, SocketStruct> socketStructMap = new ConcurrentHashMap<String, SocketStruct>();
private static Random random = new Random();
private static final int TcpDataMaxLen = 1460;
public static void main(String[] args) {
NativeMapping.PcapErrbuf errbuf = new NativeMapping.PcapErrbuf();
Pointer handle = NativeMapping.pcap_open_live("\\Device\\NPF_{C8E924E8-3C99-411D-8A9B-5A13CCC5E393}", 65536, 1, 1000, errbuf);
if (handle == null) {
System.out.println("Open device failed");
System.exit(-1);
}
NativeMapping.bpf_program prog = new NativeMapping.bpf_program();
String filterStr = String.format("ether dst %02X:%02X:%02X:%02X:%02X:%02X",
localMacAddr[0], localMacAddr[1], localMacAddr[2], localMacAddr[3], localMacAddr[4], localMacAddr[5]);
int rc = NativeMapping.pcap_compile(handle, prog, filterStr, 1, -1);
NativeMapping.pcap_freecode(prog);
long timeStart = System.currentTimeMillis();
while (true) {
receiveTcpData(handle);
for(String key : socketStructMap.keySet()){
SocketStruct s = socketStructMap.get(key);
if(s.status==2){
if(s.buffer!=null
&& s.buffer.position()==s.buffer.limit()
&& s.buffer.position()<s.buffer.capacity()){
int size = TcpDataMaxLen;
if(s.buffer.capacity()-s.buffer.position()<size){
size = s.buffer.capacity()-s.buffer.limit();
}
sendTcpReply(handle, s.remoteMacAddr, s.remoteAddr, s.remotePort,
s.identifyId, s.seqenceId, s.acknowlegeId,
false, false, false, false, true, true, false, false, false,
s.buffer.array(), 0, size);
s.buffer.limit(s.buffer.limit()+size);
}
}
}
}
}
private static int receiveTcpData(Pointer handle) {
int rc;
PointerByReference headerPP = new PointerByReference();
PointerByReference dataPP = new PointerByReference();
rc = NativeMappi