PACKET-IN 消息分类模块

Packet-In 消息分类模块

创建对象

IFloodlightProviderService floodlightProvider; //用于注册监听服务
protected static Logger log=LoggerFactory.getLogger(PktInHistory.class); //打印消息
protected IRestApiService restApi; //注册 REST API 服务

字符串用于判断包是什么类型的包

public final static String BROADCAST="broadcast";
public final static String MULTICAST="multicast";
public final static String UNICAST="unicast";

获取模块服务

    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
    // TODO Auto-generated method stub
    Collection<Class<? extends IFloodlightService>> I =new ArrayList<Class<? extends
            IFloodlightService>>();
    I.add(IPktInHistoryService.class);
    return I;
}

获取模块服务实例

public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
    // TODO Auto-generated method stub
    Map<Class<? extends IFloodlightService>,IFloodlightService> m =new HashMap<Class<? extends
            IFloodlightService>,IFloodlightService>();
    m.put(IPktInHistoryService.class,this);
    return m;
}

添加服务依赖

public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
    // TODO Auto-generated method stub
    Collection<Class<? extends IFloodlightService>> I =new ArrayList<Class<? extends
            IFloodlightService>>();
    I.add(IFloodlightProviderService.class);
    I.add(IRestApiService.class);
    return I;
}

init方法

public void init(FloodlightModuleContext context) throws FloodlightModuleException {
    // TODO Auto-generated method stub
    floodlightProvider=context.getServiceImpl(IFloodlightProviderService.class);
    restApi=context.getServiceImpl(IRestApiService.class);
}

实例化 floddlightProvider 对象和 restAPI对象

startUp方法

public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {
    // TODO Auto-generated method stub
    floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
    restApi.addRestletRoutable(new PktInHistoryWebRoutable());
}

将 PACKET-IN 消息类型加入监听,其他类型的消息也是如此的添加
注册 REST API 服务

对 PACKET-IN 消息处理

public net.floodlightcontroller.core.IListener.Command receive(IOFSwitch sw, OFMessage msg,
        FloodlightContext cntx) {
    // TODO Auto-generated method stub
    switch(msg.getType()){
        case PACKET_IN:
            Ethernet eth = IFloodlightProviderService.bcStore.get(cntx,IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
            log.info("OFMessage:{} on switch {} \n" +"srcMac:{}\n"+"dstMac:{}\n"+"EtherType:{}\n",
                new Object[] { msg.getType(), sw.getId(), eth.getSourceMACAddress(),eth.getDestinationMACAddress(),eth.getEtherType()});
            PACKET_IN_COUNT.incrementAndGet();
            PacketInType(sw,msg,eth);
            break;
    default:
            break;
            
    }
    
    return Command.CONTINUE;
}

eth = IFloodlightProviderService.bcStore.get(cntx,IFloodlightProviderService.CONTEXT_PI_PAYLOAD)
用于获取 PACKET-IN 消息的内容
调用 PacketInType 方法打印出 PACKET-IN 消息的信息

PacketInType 方法

public   List<String> PacketInType(IOFSwitch sw, OFMessage m, Ethernet eth) {
        //int l3type = eth.getEtherType().getValue();
        String etherType = eth.getEtherType().toString();
        // L2 Type
        String l2Type = null;
        if (eth.isBroadcast()) {
            l2Type = BROADCAST;
        }
        else if (eth.isMulticast()) {
            l2Type = MULTICAST;
        }
        else {
            l2Type = UNICAST;
        }
        etherType = "EtherType: " + TypeAnalyse.l3TypeAliasMap.get(etherType);
        List<String>list = new ArrayList<String>();
        list.add(l2Type);
        list.add(etherType);
        // L4 counters
        if (eth.getPayload() instanceof IPv4) {
            MacAddress dlAddr = eth.getSourceMACAddress();
            IPv4Address ipv4Src = getSrcIPv4AddrFromARP(eth, dlAddr);
            IPv4Address ipv4Dst = getDstIPv4AddrFromARP(eth, dlAddr);
            IPv4 ipV4 = (IPv4)eth.getPayload();
            String l4name = ipV4.getProtocol().toString();
            l4name = TypeAnalyse.l4TypeAliasMap.get(l4name);
            String ipv4SrcIp=IPv4.fromIPv4Address(ipv4Src.getInt());
            String ipv4DstIp=IPv4.fromIPv4Address(ipv4Dst.getInt());
            list.add("IPV4_"+l4name);
            list.add("IPv4Src:"+ipv4SrcIp);
            list.add("IPv4Dst:"+ipv4DstIp);
        }
        // L4 counters
        else if (eth.getPayload() instanceof IPv6) {
            IPv6 ipv6 = (IPv6)eth.getPayload();
            String l4name = ipv6.getNextHeader().toString();
            if (TypeAnalyse.l4TypeAliasMap != null &&
                    TypeAnalyse.l4TypeAliasMap.containsKey(l4name)) {
                l4name = TypeAnalyse.l4TypeAliasMap.get(l4name);
                if(l4name.equals("L4_UDP")) PACKET_IN_IPV6_COUNT.incrementAndGet();
            }
            else {
                l4name = "IPV6_" + l4name;
            }
            IPv6Address ipv6SrcIp=ipv6.getSourceAddress();
            String ipv6srcIp=ipv6SrcIp.toString();
            IPv6Address ipv6DstIp=ipv6.getDestinationAddress();
            String ipv6dstIp=ipv6DstIp.toString();
            list.add(l4name);
            list.add("srcIP:"+ipv6srcIp);
            list.add("DstIP:"+ipv6dstIp);
          
        }
        //遍历 List,打印内容,(单播、组播、广播)类型、EtherType、源 IP, 目的 IP
        for(Iterator<String> i = list.iterator();i.hasNext(); ){
            String str = (String) i.next();
            System.out.println(str);
        }
        return null;
    }

判断是单播、组播、广播、以太网类型
IPV4还是 IPV6,获得对应的类型,例如是 ICMP 包或者 UDP 包,同时再获取内部的源 IP 地址和目的 IP 地址

类型分析类-TypeAnalyse.java

  • 用于 PacketInType 分析包是属于 ARP 还是 IPV4,IPV6等类型信息

TypeAnalyse.java

package net.floodlightcontroller.pktinhistory;

import java.util.HashMap;
import java.util.Map;

public  class TypeAnalyse {

    public static final Map<String,String> l3TypeAliasMap = 
            new HashMap<String, String>();
    static {
        l3TypeAliasMap.put("0x0599", "L3_V1Ether");
        l3TypeAliasMap.put("0x800", "L3_IPv4");
        l3TypeAliasMap.put("0x806", "L3_ARP");
        l3TypeAliasMap.put("0x8035", "L3_RARP");
        l3TypeAliasMap.put("0x809b", "L3_AppleTalk");
        l3TypeAliasMap.put("0x80f3", "L3_AARP");
        l3TypeAliasMap.put("0x8100", "L3_802_1Q");
        l3TypeAliasMap.put("0x8137", "L3_Novell_IPX");
        l3TypeAliasMap.put("0x8138", "L3_Novell");
        l3TypeAliasMap.put("0x86dd", "L3_IPv6");
        l3TypeAliasMap.put("0x8847", "L3_MPLS_uni");
        l3TypeAliasMap.put("0x8848", "L3_MPLS_multi");
        l3TypeAliasMap.put("0x8863", "L3_PPPoE_DS");
        l3TypeAliasMap.put("0x8864", "L3_PPPoE_SS");
        l3TypeAliasMap.put("0x886f", "L3_MSFT_NLB");
        l3TypeAliasMap.put("0x8870", "L3_Jumbo");
        l3TypeAliasMap.put("0x889a", "L3_HyperSCSI");
        l3TypeAliasMap.put("0x88a2", "L3_ATA_Ethernet");
        l3TypeAliasMap.put("0x88a4", "L3_EtherCAT");
        l3TypeAliasMap.put("0x88a8", "L3_802_1ad");
        l3TypeAliasMap.put("0x88ab", "L3_Ether_Powerlink");
        l3TypeAliasMap.put("0x88cc", "L3_LLDP");
        l3TypeAliasMap.put("0x88cd", "L3_SERCOS_III");
        l3TypeAliasMap.put("0x88e5", "L3_802_1ae");
        l3TypeAliasMap.put("0x88f7", "L3_IEEE_1588");
        l3TypeAliasMap.put("0x8902", "L3_802_1ag_CFM");
        l3TypeAliasMap.put("0x8906", "L3_FCoE");
        l3TypeAliasMap.put("0x9000", "L3_Loop");
        l3TypeAliasMap.put("0x9100", "L3_Q_in_Q");
        l3TypeAliasMap.put("0xcafe", "L3_LLT");
    }
    
    protected static final Map<String,String> l4TypeAliasMap = 
            new HashMap<String, String>();
    static {
        l4TypeAliasMap.put("0x00", "L4_HOPOPT");
        l4TypeAliasMap.put("0x01", "L4_ICMP");
        l4TypeAliasMap.put("0x02", "L4_IGAP_IGMP_RGMP");
        l4TypeAliasMap.put("0x03", "L4_GGP");
        l4TypeAliasMap.put("0x04", "L4_IP");
        l4TypeAliasMap.put("0x05", "L4_ST");
        l4TypeAliasMap.put("0x06", "L4_TCP");
        l4TypeAliasMap.put("0x07", "L4_UCL");
        l4TypeAliasMap.put("0x08", "L4_EGP");
        l4TypeAliasMap.put("0x09", "L4_IGRP");
        l4TypeAliasMap.put("0x0a", "L4_BBN");
        l4TypeAliasMap.put("0x0b", "L4_NVP");
        l4TypeAliasMap.put("0x0c", "L4_PUP");
        l4TypeAliasMap.put("0x0d", "L4_ARGUS");
        l4TypeAliasMap.put("0x0e", "L4_EMCON");
        l4TypeAliasMap.put("0x0f", "L4_XNET");
        l4TypeAliasMap.put("0x10", "L4_Chaos");
        l4TypeAliasMap.put("0x11", "L4_UDP");
        l4TypeAliasMap.put("0x12", "L4_TMux");
        l4TypeAliasMap.put("0x13", "L4_DCN");
        l4TypeAliasMap.put("0x14", "L4_HMP");
        l4TypeAliasMap.put("0x15", "L4_Packet_Radio");
        l4TypeAliasMap.put("0x16", "L4_XEROX_NS_IDP");
        l4TypeAliasMap.put("0x17", "L4_Trunk_1");
        l4TypeAliasMap.put("0x18", "L4_Trunk_2");
        l4TypeAliasMap.put("0x19", "L4_Leaf_1");
        l4TypeAliasMap.put("0x1a", "L4_Leaf_2");
        l4TypeAliasMap.put("0x1b", "L4_RDP");
        l4TypeAliasMap.put("0x1c", "L4_IRTP");
        l4TypeAliasMap.put("0x1d", "L4_ISO_TP4");
        l4TypeAliasMap.put("0x1e", "L4_NETBLT");
        l4TypeAliasMap.put("0x1f", "L4_MFE");
        l4TypeAliasMap.put("0x20", "L4_MERIT");
        l4TypeAliasMap.put("0x21", "L4_DCCP");
        l4TypeAliasMap.put("0x22", "L4_Third_Party_Connect");
        l4TypeAliasMap.put("0x23", "L4_IDPR");
        l4TypeAliasMap.put("0x24", "L4_XTP");
        l4TypeAliasMap.put("0x25", "L4_Datagram_Delivery");
        l4TypeAliasMap.put("0x26", "L4_IDPR");
        l4TypeAliasMap.put("0x27", "L4_TP");
        l4TypeAliasMap.put("0x28", "L4_ILTP");
        l4TypeAliasMap.put("0x29", "L4_IPv6_over_IPv4");
        l4TypeAliasMap.put("0x2a", "L4_SDRP");
        l4TypeAliasMap.put("0x2b", "L4_IPv6_RH");
        l4TypeAliasMap.put("0x2c", "L4_IPv6_FH");
        l4TypeAliasMap.put("0x2d", "L4_IDRP");
        l4TypeAliasMap.put("0x2e", "L4_RSVP");
        l4TypeAliasMap.put("0x2f", "L4_GRE");
        l4TypeAliasMap.put("0x30", "L4_DSR");
        l4TypeAliasMap.put("0x31", "L4_BNA");
        l4TypeAliasMap.put("0x32", "L4_ESP");
        l4TypeAliasMap.put("0x33", "L4_AH");
        l4TypeAliasMap.put("0x34", "L4_I_NLSP");
        l4TypeAliasMap.put("0x35", "L4_SWIPE");
        l4TypeAliasMap.put("0x36", "L4_NARP");
        l4TypeAliasMap.put("0x37", "L4_Minimal_Encapsulation");
        l4TypeAliasMap.put("0x38", "L4_TLSP");
        l4TypeAliasMap.put("0x39", "L4_SKIP");
        l4TypeAliasMap.put("0x3a", "L4_ICMPv6");
        l4TypeAliasMap.put("0x3b", "L4_IPv6_No_Next_Header");
        l4TypeAliasMap.put("0x3c", "L4_IPv6_Destination_Options");
        l4TypeAliasMap.put("0x3d", "L4_Any_host_IP");
        l4TypeAliasMap.put("0x3e", "L4_CFTP");
        l4TypeAliasMap.put("0x3f", "L4_Any_local");
        l4TypeAliasMap.put("0x40", "L4_SATNET");
        l4TypeAliasMap.put("0x41", "L4_Kryptolan");
        l4TypeAliasMap.put("0x42", "L4_MIT_RVDP");
        l4TypeAliasMap.put("0x43", "L4_Internet_Pluribus");
        l4TypeAliasMap.put("0x44", "L4_Distributed_FS");
        l4TypeAliasMap.put("0x45", "L4_SATNET");
        l4TypeAliasMap.put("0x46", "L4_VISA");
        l4TypeAliasMap.put("0x47", "L4_IP_Core");
        l4TypeAliasMap.put("0x4a", "L4_Wang_Span");
        l4TypeAliasMap.put("0x4b", "L4_Packet_Video");
        l4TypeAliasMap.put("0x4c", "L4_Backroom_SATNET");
        l4TypeAliasMap.put("0x4d", "L4_SUN_ND");
        l4TypeAliasMap.put("0x4e", "L4_WIDEBAND_Monitoring");
        l4TypeAliasMap.put("0x4f", "L4_WIDEBAND_EXPAK");
        l4TypeAliasMap.put("0x50", "L4_ISO_IP");
        l4TypeAliasMap.put("0x51", "L4_VMTP");
        l4TypeAliasMap.put("0x52", "L4_SECURE_VMTP");
        l4TypeAliasMap.put("0x53", "L4_VINES");
        l4TypeAliasMap.put("0x54", "L4_TTP");
        l4TypeAliasMap.put("0x55", "L4_NSFNET_IGP");
        l4TypeAliasMap.put("0x56", "L4_Dissimilar_GP");
        l4TypeAliasMap.put("0x57", "L4_TCF");
        l4TypeAliasMap.put("0x58", "L4_EIGRP");
        l4TypeAliasMap.put("0x59", "L4_OSPF");
        l4TypeAliasMap.put("0x5a", "L4_Sprite_RPC");
        l4TypeAliasMap.put("0x5b", "L4_Locus_ARP");
        l4TypeAliasMap.put("0x5c", "L4_MTP");
        l4TypeAliasMap.put("0x5d", "L4_AX");
        l4TypeAliasMap.put("0x5e", "L4_IP_within_IP");
        l4TypeAliasMap.put("0x5f", "L4_Mobile_ICP");
        l4TypeAliasMap.put("0x61", "L4_EtherIP");
        l4TypeAliasMap.put("0x62", "L4_Encapsulation_Header");
        l4TypeAliasMap.put("0x64", "L4_GMTP");
        l4TypeAliasMap.put("0x65", "L4_IFMP");
        l4TypeAliasMap.put("0x66", "L4_PNNI");
        l4TypeAliasMap.put("0x67", "L4_PIM");
        l4TypeAliasMap.put("0x68", "L4_ARIS");
        l4TypeAliasMap.put("0x69", "L4_SCPS");
        l4TypeAliasMap.put("0x6a", "L4_QNX");
        l4TypeAliasMap.put("0x6b", "L4_Active_Networks");
        l4TypeAliasMap.put("0x6c", "L4_IPPCP");
        l4TypeAliasMap.put("0x6d", "L4_SNP");
        l4TypeAliasMap.put("0x6e", "L4_Compaq_Peer_Protocol");
        l4TypeAliasMap.put("0x6f", "L4_IPX_in_IP");
        l4TypeAliasMap.put("0x70", "L4_VRRP");
        l4TypeAliasMap.put("0x71", "L4_PGM");
        l4TypeAliasMap.put("0x72", "L4_0_hop");
        l4TypeAliasMap.put("0x73", "L4_L2TP");
        l4TypeAliasMap.put("0x74", "L4_DDX");
        l4TypeAliasMap.put("0x75", "L4_IATP");
        l4TypeAliasMap.put("0x76", "L4_ST");
        l4TypeAliasMap.put("0x77", "L4_SRP");
        l4TypeAliasMap.put("0x78", "L4_UTI");
        l4TypeAliasMap.put("0x79", "L4_SMP");
        l4TypeAliasMap.put("0x7a", "L4_SM");
        l4TypeAliasMap.put("0x7b", "L4_PTP");
        l4TypeAliasMap.put("0x7c", "L4_ISIS");
        l4TypeAliasMap.put("0x7d", "L4_FIRE");
        l4TypeAliasMap.put("0x7e", "L4_CRTP");
        l4TypeAliasMap.put("0x7f", "L4_CRUDP");
        l4TypeAliasMap.put("0x80", "L4_SSCOPMCE");
        l4TypeAliasMap.put("0x81", "L4_IPLT");
        l4TypeAliasMap.put("0x82", "L4_SPS");
        l4TypeAliasMap.put("0x83", "L4_PIPE");
        l4TypeAliasMap.put("0x84", "L4_SCTP");
        l4TypeAliasMap.put("0x85", "L4_Fibre_Channel");
        l4TypeAliasMap.put("0x86", "L4_RSVP_E2E_IGNORE");
        l4TypeAliasMap.put("0x87", "L4_Mobility_Header");
        l4TypeAliasMap.put("0x88", "L4_UDP_Lite");
        l4TypeAliasMap.put("0x89", "L4_MPLS");
        l4TypeAliasMap.put("0x8a", "L4_MANET");
        l4TypeAliasMap.put("0x8b", "L4_HIP");
        l4TypeAliasMap.put("0x8c", "L4_Shim6");
        l4TypeAliasMap.put("0x8d", "L4_WESP");
        l4TypeAliasMap.put("0x8e", "L4_ROHC");
    }
}

PktInHistoryResource类

@Get("json")
public HashMap<String,String> retrieve(){
    IPktInHistoryService pihr =(IPktInHistoryService)getContext().getAttributes().
            get(IPktInHistoryService.class.getCanonicalName());
    Long count_packet_in=pihr.getPACKET_IN_Count();
    Long count_packet_in_UDP=pihr.getPACKET_IN_UDP_Count();
    HashMap<String,String>resp=new HashMap<String,String>();
    resp.put("Packet-In-Total", Long.toString(count_packet_in));
    resp.put("Packet-In-UDP-Total", Long.toString(count_packet_in_UDP));
    return resp;
}

可以通过REST API打印PACKET-IN 包数量以及 PACKET-IN 中 UDP 包的数量
具体 REST API 想要获得的数据就可以放到 resp 中,之后调用 REST API 接口就能打印出来

PktInHistoryWebRoutable类

@Override
public Restlet getRestlet(Context context) {
    // TODO Auto-generated method stub
    Router router=new Router(context);
    router.attach("/pktinhistory/json", PktInHistoryResource.class);
    return router;
}

@Override
public String basePath() {
    // TODO Auto-generated method stub
    return "/wm/statics" ;
}

绑定 REST API 服务地址
用于之后直接用REST API 接口得到数据

PktInHistory 的服务IPktInHistoryService

public interface IPktInHistoryService extends IFloodlightService {

    public ConcurrentCircularBuffer<SwitchMessagePair>getBuffer();
    public Long getPACKET_IN_Count();
    public Long getPACKET_IN_UDP_Count();
}

用于在 REST API 中获取当前计数的值
此处指写了两个计数的,一个是所有的 PACKET-IN 包,另一个是 PACKET-IN 包中的 UDP 的包


在对应的 PKtInHistory 中的对应方法

public Long getPACKET_IN_UDP_Count() {
    // TODO Auto-generated method stub
    return PACKET_IN_UDP_COUNT.get();
}

Mininet 环境配置

neal@ubuntu:~$ sudo mn --switch ovs,protocols=OpenFlow13,port=6653 --controller=remote --ip=127.0.0.1  --mac --topo=tree,2 --test iperf

然后在 Floodlight 中查看对应的打印信息

2016-12-06 21:37:40.753 INFO  [n.f.p.PktInHistory] 
OFMessage:PACKET_IN on switch 00:00:00:00:00:00:00:01 
srcMac:ce:72:93:42:23:ce
dstMac:33:33:00:00:00:fb
EtherType:0x86dd
multicast
EtherType: L3_IPv6
L4_UDP
srcIP:fe80::cc72:93ff:fe42:23ce
DstIP:ff02::fb

2016-12-06 21:37:46.666 INFO  [n.f.p.PktInHistory] 
OFMessage:PACKET_IN on switch 00:00:00:00:00:00:00:01 
srcMac:ce:72:93:42:23:ce
dstMac:33:33:00:00:00:02
EtherType:0x86dd

multicast
EtherType: L3_IPv6
L4_ICMPv6
srcIP:fe80::cc72:93ff:fe42:23ce
DstIP:ff02::2

在 cli.py 中添加一条 Rest api 命令

elif args.cmd =='pktin_cnt':
path='/wm/statics/pktinhistory/json'

运行:neal@ubuntu:~/Floodlight/example$ ./cli.py pktin_cnt

获得如下结果:
{
"Packet-In-Total": "67",
"Packet-In-UDP-Total": "33"
}
Number of items: 2

可以直接获得包的统计值

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,494评论 18 139
  • 简介 用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者...
    保川阅读 5,933评论 1 13
  • 一说到REST,我想大家的第一反应就是“啊,就是那种前后台通信方式。”但是在要求详细讲述它所提出的各个约束,以及如...
    时待吾阅读 3,394评论 0 19
  • ——读书笔记|《跃迁:成为高手的技术》(古典著) 焦虑是这个时代的底色,世界太快,身体在狂奔,无奈灵魂落在身后泣不...
    花之葭阅读 367评论 0 5
  • 我且是如此執拗 像快破繭的那隻蛹 不動彈,偏偏不是無法動彈,而是不想動彈。 前幾日 我在夜裡 變成你巷子外那棵樹,...
    沁歡阅读 80评论 0 0