⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 udp.java

📁 一个小型网络仿真器的实现
💻 JAVA
字号:
/*
   JaNetSim  ---  Java Network Simulator
   -------------------------------------

   This software was developed at the Network Research Lab, Faculty of
   Computer Science and Information Technology (FCSIT), University of Malaya.
   This software may be used and distributed freely. FCSIT assumes no responsibility
   whatsoever for its use by other parties, and makes no guarantees, expressed or
   implied, about its quality, reliability, or any other characteristic.

   We would appreciate acknowledgement if the software is used.

   FCSIT ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND
   DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
   FROM THE USE OF THIS SOFTWARE.
*/

package janetsim.component;

import janetsim.*;

public class UDP implements SimListener,java.io.Serializable {

  private class UDBKey implements java.io.Serializable {
    int source_ip,dest_ip;
    int source_port,dest_port;
    UDBKey(int srcip,int srcport,int destip,int destport) {
      source_ip=srcip;
      source_port=srcport;
      dest_ip=destip;
      dest_port=destport;
    }
    public boolean equals(Object o) {
      if(!(o instanceof UDBKey)) return false;
      UDBKey k=(UDBKey)o;
      if(k.source_ip==source_ip && k.source_port==source_port &&
          k.dest_ip==dest_ip && k.dest_port==dest_port)
        return true;
      return false;
    }
    public int hashCode() {
      return (source_ip ^ source_port ^ dest_ip ^ dest_port);
    }
  }

  private class UDB implements java.io.Serializable {
    UDBKey key=null;
    UDPUser user=null;
  }

  private class ProcessEntry implements java.io.Serializable {
    IPPacket packet;
    boolean incoming;
    SimComponent fromlink;

    ProcessEntry(IPPacket p,boolean in,SimComponent frmlink) {
      packet=p;
      incoming=in;
      fromlink=frmlink;
    }
  }

  //packet processing queue
  private java.util.List processing_q=null;
  private boolean busy;

  private java.util.Random randgen;
  private java.util.Map udbs=null;
  private SimComponent comp=null;
  private UDPProvider provider=null;

//private events
  private static final int MY_READY_DEMUX = SimProvider.EV_PRIVATE + 1;


  public UDP(SimComponent owner,UDPProvider prov) {
    randgen=new java.util.Random(owner.getName().hashCode());

    processing_q=new java.util.LinkedList();
    busy=false;

    udbs=new java.util.HashMap();
    comp=owner;
    provider=prov;
  }

  public void reset() {
    randgen.setSeed(comp.getName().hashCode());

    processing_q.clear();
    busy=false;

    udbs.clear();
    provider.statusChanged();
  }

  public void action(SimEvent e) {
    switch(e.getType()) {
      case MY_READY_DEMUX:
        my_ready_demux();
        break;
    }
  }

  //IMPORTANT: this method is called by provider
  public void receive_ip(IPPacket packet,SimComponent fromlink) {
    processing_q.add(new ProcessEntry(packet,true,fromlink));
    check_processing_q();
  }

  private void send_ip(IPPacket packet) { //called by udp
    processing_q.add(new ProcessEntry(packet,false,null));
    check_processing_q();
  }

  private void my_ready_demux() {
    //ready to process the next packet (process delay already accounted for)

    if(processing_q.isEmpty()) {
      System.out.println("Warning: udp: demux called when processing_q is empty!");
      return;
    }

    ProcessEntry entry=(ProcessEntry)processing_q.remove(0);
    if(entry.incoming)
      process_packet(entry.packet,entry.fromlink);
    else
      transmit_packet(entry.packet);

    busy=false;
    check_processing_q();
  }

  private void check_processing_q() {
    if(busy) return;

    if(!processing_q.isEmpty()) {
      long ticks=compute_processing_delay();
      comp.getSim().enqueue(new SimEvent(MY_READY_DEMUX,this,this,comp.getSim().now()+ticks,null));
      busy=true;
    }
  }

  private void transmit_packet(IPPacket packet) {
    provider.sendPacket(packet);    
  }

  private void process_packet(IPPacket packet,SimComponent fromlink) {
    UDPPacket udppacket=(UDPPacket)packet.payload;
    UDBKey k=new UDBKey(packet.destIP,udppacket.destport,packet.sourceIP,udppacket.sourceport);

    boolean passive=false;
    UDB udb=(UDB)udbs.get(k);

    if(udb==null) {
      passive=true;
      k=new UDBKey(packet.destIP,udppacket.destport,0,0);
      udb=(UDB)udbs.get(k);
    }
    if(udb==null) return;

    udb.user.receive_packet(packet.sourceIP,udppacket.sourceport,fromlink,
                            new UDPBuffer(udppacket.len-8,udppacket.payload));
  }

  private long compute_processing_delay() {
    double fuzz=0;
    double delayvar=provider.getDelayVar();

    if(delayvar > 0)
      fuzz=randgen.nextDouble() * (delayvar+delayvar) - delayvar;

    long ticks=SimClock.USec2Tick(provider.getDelay()+fuzz);
    if(ticks<0) ticks=0;

    return ticks;
  }


///////////////////////////// Services ///////////////////////////////////


  public Object open(int sourceip,int sourceport,int destip,int destport,
                      UDPUser user) {
    UDBKey k=new UDBKey(sourceip,sourceport,destip,destport);
    UDB udb=(UDB)udbs.get(k);

    if(udb==null) { //connection does not exist
      udb=new UDB();
      udb.key=k;
      udb.user=user;
      udbs.put(k,udb);
      provider.statusChanged();
      return k;
    }

    return null; //connection already exists!
  }

  public boolean send(Object k,UDPBuffer buf) {
    UDB udb=(UDB)udbs.get(k);
    if(udb==null) return false; //no connection yet

    UDPPacket udppacket=new UDPPacket();
    udppacket.sourceport=udb.key.source_port;
    udppacket.destport=udb.key.dest_port;
    udppacket.len=8+buf.len;
    udppacket.payload=buf.payload;

    IPPacket packet=new IPPacket();
    packet.sourceIP=udb.key.source_ip;
    packet.destIP=udb.key.dest_ip;
    packet.protocol=IPPacket.PRO_UDP;
    packet.len=20+udppacket.len;
    packet.payload=udppacket;

    provider.sendPacket(packet);

    return true;
  }

  //send with specified outgoing link
  public boolean send(Object k,UDPBuffer buf,SimComponent tolink) {
    UDB udb=(UDB)udbs.get(k);
    if(udb==null) return false; //no connection yet

    UDPPacket udppacket=new UDPPacket();
    udppacket.sourceport=udb.key.source_port;
    udppacket.destport=udb.key.dest_port;
    udppacket.len=8+buf.len;
    udppacket.payload=buf.payload;

    IPPacket packet=new IPPacket();
    packet.sourceIP=udb.key.source_ip;
    packet.destIP=udb.key.dest_ip;
    packet.protocol=IPPacket.PRO_UDP;
    packet.len=20+udppacket.len;
    packet.payload=udppacket;

    provider.sendPacket(packet,tolink);

    return true;
  }

  //this is a "targeted" send (overrides the dest ip & port)
  public boolean send(Object k,UDPBuffer buf,int destip,int destport) {
    UDB udb=(UDB)udbs.get(k);
    if(udb==null) return false; //no connection yet

    UDPPacket udppacket=new UDPPacket();
    udppacket.sourceport=udb.key.source_port;
    udppacket.destport=destport;
    udppacket.len=8+buf.len;
    udppacket.payload=buf.payload;

    IPPacket packet=new IPPacket();
    packet.sourceIP=udb.key.source_ip;
    packet.destIP=destip;
    packet.protocol=IPPacket.PRO_UDP;
    packet.len=20+udppacket.len;
    packet.payload=udppacket;

    provider.sendPacket(packet);

    return true;
  }

  //this is a "targeted" send (overrides the dest ip & port) with
  //  specified outgoing link
  public boolean send(Object k,UDPBuffer buf,int destip,int destport,
                        SimComponent tolink) {
    UDB udb=(UDB)udbs.get(k);
    if(udb==null) return false; //no connection yet

    UDPPacket udppacket=new UDPPacket();
    udppacket.sourceport=udb.key.source_port;
    udppacket.destport=destport;
    udppacket.len=8+buf.len;
    udppacket.payload=buf.payload;

    IPPacket packet=new IPPacket();
    packet.sourceIP=udb.key.source_ip;
    packet.destIP=destip;
    packet.protocol=IPPacket.PRO_UDP;
    packet.len=20+udppacket.len;
    packet.payload=udppacket;

    provider.sendPacket(packet,tolink);

    return true;
  }

  public boolean close(Object k) {
    UDB udb=(UDB)udbs.get(k);
    if(udb==null) return false; //no connection yet

    udbs.remove(udb.key);
    provider.statusChanged();

    return true;
  }

  public int connectionCount() {
    return udbs.size();
  }
  public int queryUDB_srcip(int index) {
    if(index>=udbs.size()) return 0;

    UDB [] udbarr=(UDB [])udbs.values().toArray(new UDB[0]);
    return udbarr[index].key.source_ip;
  }
  public int queryUDB_srcport(int index) {
    if(index>=udbs.size()) return 0;

    UDB [] udbarr=(UDB [])udbs.values().toArray(new UDB[0]);
    return udbarr[index].key.source_port;
  }
  public int queryUDB_destip(int index) {
    if(index>=udbs.size()) return 0;

    UDB [] udbarr=(UDB [])udbs.values().toArray(new UDB[0]);
    return udbarr[index].key.dest_ip;
  }
  public int queryUDB_destport(int index) {
    if(index>=udbs.size()) return 0;

    UDB [] udbarr=(UDB [])udbs.values().toArray(new UDB[0]);
    return udbarr[index].key.dest_port;
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -