Java数据报套接字接收缓冲区溢出导致冻结

时间:2015-11-02 15:30:00

标签: java udp datagram

我试图在没有使用UDP的流量控制机制的情况下实现类似TCP的协议。所以我在Java中使用Datagram Socket。奇怪的是,当发送方使用大窗口大小,即在短时间内向接收方发送大量数据包时,接收方的数据报套接字会在一段时间后停止接收数据包。更明确地说,接收器程序停留在DatagramSocket.receive()方法,似乎数据报套接字的接收缓冲区已溢出,并导致它在DatagramSocket.receive()方法中阻塞。为了证实这种怀疑,我将接收缓冲区的大小设置得更大,然后麻烦就消失了。  所以我只想问一下当接收缓冲区溢出时会发生什么(除了丢弃数据包),以及为什么程序会在DatagramSocket.receive()方法冻结并停止接收数据包。

public class Receiver {
    String fileName;  //  output file name
    short listeningPort;
    InetAddress senderIp;
    short senderPort;
    String logFileName;  // the log file name 
    DatagramSocket inSocket; // udp socket to receive data
    Socket outSocket; // tcp socket to send control message 
    PriorityQueue<Packet> outOfOrder;  // buff to save the out of order packet
    DataOutputStream send;
    FileOutputStream wFile;
    PrintWriter wLog;
    private int receiverSeqN = 0;// the sequence number for sending packet to sender
    private int receiverAckN = 0; // the ack sequence number    
    private boolean receiverFIN = false;

    public Receiver( String fN, short lP, String sI, short sP, String lFN){
        fileName = fN;
        listeningPort = lP;             
        senderPort = sP;
        logFileName = lFN;

        outOfOrder = new PriorityQueue<Packet>();

        try {
            senderIp = InetAddress.getByName(sI);
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


        try {

            outSocket = new Socket(senderIp,senderPort); // create the TCP socket to send control message to sender                     
            send = new DataOutputStream(outSocket.getOutputStream());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        try {
            inSocket = new DatagramSocket(lP); // create the UDP socket to listen 
        } catch (SocketException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            wFile = new  FileOutputStream(fileName);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            System.out.println("unable to creat file.");
            e.printStackTrace();
        }

        try {
            wLog = new PrintWriter(logFileName);
        } catch (FileNotFoundException e) {
            System.out.println("unable to creat log file");
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    // receiving packet
    public void receive(){  

        byte[] buff = new byte[1024];
        DatagramPacket dp = new DatagramPacket(buff,0,buff.length);
        try {           
            inSocket.receive(dp);  // *program stuff here!!!!*
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        byte[] data = Arrays.copyOf(dp.getData(), dp.getLength());

        Packet newPak = new Packet(Timestamp.from(Instant.now()),data);     

        log(newPak);

        if (newPak.corrupted || outOfOrder.contains(newPak) || newPak.seqN < receiverAckN) {
            sendAck(receiverAckN);
            return;
        }
        outOfOrder.add(newPak);
        Packet current = outOfOrder.peek();
        while (current.seqN == receiverAckN){
            if ( current.FIN ) receiverFIN = true;
            receiverAckN++;
            deliver(current.message);
            outOfOrder.poll();
            if(outOfOrder.isEmpty())  break;
            current = outOfOrder.peek();            
        }       
        sendAck(receiverAckN);                  
    }

    // send the ack packet to the  sender
    public void sendAck(int ackN){

        Packet pak = new Packet(Timestamp.from(Instant.now()),listeningPort, senderPort, receiverSeqN++, ackN, true,receiverFIN, new byte[0]);
        log(pak);
        try {
            send.write(pak.toByteArray());
            send.flush();


        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }





    }
    // deliver message to the file
    public void deliver(byte[] message){    

        byte[] temp = Arrays.copyOf(message, message.length);
        try {
        //  System.out.println(new String(temp, 0, temp.length));
            wFile.write(temp );             
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
    // log the packet
    public void log(Packet packet){

         wLog.write(packet.toString());
         wLog.write("\n");
         wLog.flush();


    }


    // receiving message


    public void go(){
        while(!receiverFIN){
            receive();
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e2) {
            // TODO Auto-generated catch block
            e2.printStackTrace();
        }
        try {
            wFile.flush();
            wLog.flush();
            wFile.close();
            wLog.close();
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        try {
            send.close();
            inSocket.close();
            outSocket.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println("The reception is successful.");

    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Receiver receiver = new Receiver(args[0], Short.parseShort(args[1]), args[2], Short.parseShort(args[3]),args[4]);
        receiver.go();


    }

}

0 个答案:

没有答案