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

📄 tcpconnection.java

📁 SMC takes a state machine stored in a .sm file and generates a State pattern in twelve programming l
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
    }    /* package */ void openSuccess()    {        _listener.opened(this);        return;    }    /* package */ void openFailed(String reason)    {        _listener.openFailed(reason, this);        return;    }    /* package */ void closeSocket()    {        _async_socket.closeDatagramSocket();        _async_socket = null;        _address = null;        _port = -1;        return;    }    /* package */ void halfClosed()    {        if (_listener != null)        {            _listener.halfClosed(this);        }        return;    }    /* package */ void closed(String reason)    {        if (_listener != null)        {            _listener.closed(reason, this);            _listener = null;        }        return;    }    /* package */ void clearListener()    {        _listener = null;        return;    }    /* package */ void transmitted()    {        if (_listener != null)        {            _listener.transmitted(this);        }        return;    }    /* package */ void transmitFailed(String reason)    {        if (_listener != null)        {            _listener.transmitFailed(reason, this);        }        return;    }    /* package */ void receive(TcpSegment segment)    {        // Send the TCP segment's data to the socket listener.        if (_listener != null)        {            _listener.receive(segment.getData(), this);        }        return;    }    // Create a client socket to handle a new connection.    /* package */ void accept(TcpSegment segment)    {        TcpClient accept_client;        DatagramSocket dgram_socket;        try        {            _address = segment.getSourceAddress();            _port = segment.getSourcePort();            // Create a new client socket to handle this side of            // the socket pair.            dgram_socket = new DatagramSocket();            accept_client = new TcpClient(_address,                                          _port,                                          dgram_socket,                                          _sequence_number,                                          (TcpServer) this,                                          _listener);            ((TcpConnection) accept_client).acceptOpen(segment);        }        catch (Exception jex)        {            // If the open fails, send a reset to the peer.            send(TcpSegment.RST,                 null,                 0,                 0,                 segment);        }        return;    }    /* package */ void accepted()    {        TcpServer server = _server;        TcpConnectionListener listener = _listener;        // Tell the server listener that a new connection has        // been accepted. Then clear the server listener because        // this socket is now truly a client socket. Clear the        // listener member data now because the callback method        // will be resetting it and the reset will fail if we        // don't do it.        _server = null;        _listener = null;        listener.accepted((TcpClient) this, server);        return;    }    // Send the SYN/ACK reply to the client's SYN.    /* package */ void sendAcceptSynAck(TcpSegment segment)    {        int client_port;        byte[] port_bytes = new byte[2];        // Tell the far-side client with what port it should now        // communicate.        client_port =            _async_socket.getDatagramSocket().getLocalPort();        port_bytes[0] = (byte) ((client_port & 0x0000ff00) >> 8);        port_bytes[1] = (byte)  (client_port & 0x000000ff);        send(TcpSegment.SYN_ACK,             port_bytes,             0,             2,             null,             -1,             segment);        return;    }    /* package */ void send(int flags,                            byte[] data,                            int offset,                            int size,                            TcpSegment recv_segment)    {        send(flags,             data,             offset,             size,             recv_segment.getSourceAddress(),             recv_segment.getSourcePort(),             recv_segment);        return;    }    /* package */ void send(int flags,                            byte[] data,                            int offset,                            int size,                            InetAddress address,                            int port,                            TcpSegment recv_segment)    {        DatagramSocket socket;        // Quietly quit if there is no socket.        if (_async_socket != null &&            (socket = _async_socket.getDatagramSocket()) != null)        {            int local_port;            int ack_number;            TcpSegment send_segment;            DatagramPacket packet = null;            // If the address and port were not specified, then            // send this segment to whatever client socket we are            // currently speaking.            if (address == null)            {                address = _address;                port = _port;            }            // If there is a recv_segment, then use its            // destination port as the local port. Otherwise, use            // the local datagram socket's local port.            if (recv_segment != null)            {                local_port = recv_segment.getDestinationPort();            }            else            {                local_port =                    _async_socket.getDatagramSocket().getLocalPort();            }            // Send the ack number only if the ack flag is set.            if ((flags & TcpSegment.ACK) == 0)            {                ack_number = 0;            }            else            {                // Figure out the ack number based on the                // received segment's sequence number and data                // size.                ack_number = getAck(recv_segment);            }            send_segment =                new TcpSegment(local_port,                               address,                               port,                               _sequence_number,                               ack_number,                               flags,                               data,                               offset,                               size);            // Advance the sequence number depending on the            // message sent. Don't do this if message came from            // an interloper.            if (address.equals(_address) && port == _port)            {                _sequence_number = getAck(send_segment);            }            // Now send the data.            try            {                packet = send_segment.packetize();                // DEBUG//                 System.out.println(//                     "Sending packet to " +//                     packet.getAddress() +//                     ":" +//                     Integer.toString(packet.getPort()) +//                     ":\n" +//                     send_segment);                _async_socket.getDatagramSocket().send(packet);            }            catch (IOException io_exception)            {                // Ignore - the ack timer will figure out this                // packet was never sent.                // DEBUG//                 System.out.println(//                     "Send to " +//                     packet.getAddress() +//                     ": " +//                     io_exception.getMessage());            }        }        return;    }    /* package */ void startTimer(String name, long time)    {        AsyncTimer.startTimer(name, time, this);        return;    }    /* package */ void stopTimer(String name)    {        AsyncTimer.stopTimer(name);        return;    }    /* package */ void setDestinationPort(TcpSegment segment)    {        byte[] data;        // The server socket is telling us the accepted client's        // port number. Reset the destination port to that.        data = segment.getData();        _port = ((((int) data[0]) & 0x000000ff) << 8) |                 (((int) data[1]) & 0x000000ff);        // Modify the segment's source port so that the ack will        // go to the correct destination.        segment.setSourcePort(_port);        return;    }    private int getAck(TcpSegment segment)    {        int retval;        // The ack # depends on the segment's flags.        switch (segment.getFlags())        {            case TcpSegment.FIN:            case TcpSegment.SYN:            case TcpSegment.FIN_ACK:            case TcpSegment.SYN_ACK:                retval = segment.getSequenceNumber() + 1;                break;            case TcpSegment.PSH:            case TcpSegment.PSH_ACK:                retval = segment.getSequenceNumber() +                         segment.getDataSize();                break;            case TcpSegment.ACK:            default:                retval = segment.getSequenceNumber();                break;        }        return(retval);    }    /*     * REFLECTION     * Uncomment the following method to output transitions.     *    private void _outputTransitions()    {        if (_fsm.getDebugFlag() == true)        {            java.io.PrintStream str = _fsm.getDebugStream();            TcpConnectionContext.TcpConnectionState state =                _fsm.getState();            java.util.Iterator it;            String sep;            str.print("State ");            str.print(state.getName());            str.print(" has transitions ");            for (it = state.getTransitions().iterator(), sep = "{";                 it.hasNext();                 sep = ", ")            {                str.print(sep);                str.print(it.next());            }            str.println("}");        }        return;    }     *     *///---------------------------------------------------------------// Member data.//    protected TcpConnectionListener _listener;    private TcpConnectionContext  _fsm;    protected AsyncDatagramSocket   _async_socket;    private int                   _sequence_number;    // The port to which a client socket is connected.    protected InetAddress _address;    protected int         _port;    // The server which accepted this connection.    protected TcpServer _server;    private String _errorMessage;    // The Initial Sequence Number.    private static final int ISN = 1415531521;    // Wait only so long for an ACK (in milliseconds).    /* package */ static final long ACK_TIMEOUT = 2000;    // Wait a while before reusing this port (in milliseconds).    /* package */ static final long CLOSE_TIMEOUT = 10000;    /* package */ static final long MIN_TIMEOUT = 1;    // Use this table to translate received segment flags into    // state map transitions.    private static Method[] _transition_table;    static    {        try        {            Class context = TcpConnectionContext.class;            Class[] parameters = new Class[1];            Method undefined;            int i;            // All "TCP flag" transitions take a DatagramPacket as            // a parameter.            parameters[0] = TcpSegment.class;            _transition_table = new Method[TcpSegment.FLAG_MASK + 1];            // First, set all transitions to undefined.            undefined = context.getDeclaredMethod("UNDEF",                                                  parameters);            for (i = 0; i < _transition_table.length; ++i)            {                _transition_table[i] = undefined;                                }            // Now go back and set the known transitions.            _transition_table[TcpSegment.FIN] =                context.getDeclaredMethod("FIN", parameters);            _transition_table[TcpSegment.SYN] =                context.getDeclaredMethod("SYN", parameters);            _transition_table[TcpSegment.RST] =                context.getDeclaredMethod("RST", parameters);            _transition_table[TcpSegment.PSH] =                context.getDeclaredMethod("PSH", parameters);            _transition_table[TcpSegment.ACK] =                context.getDeclaredMethod("ACK", parameters);            _transition_table[TcpSegment.URG] =                context.getDeclaredMethod("URG", parameters);            _transition_table[TcpSegment.FIN_ACK] =                context.getDeclaredMethod("FIN_ACK", parameters);            _transition_table[TcpSegment.SYN_ACK] =                context.getDeclaredMethod("SYN_ACK", parameters);            _transition_table[TcpSegment.PSH_ACK] =                context.getDeclaredMethod("PSH_ACK", parameters);        }        catch (Exception jex) {}    }}

⌨️ 快捷键说明

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