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

📄 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 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)    {        int local_port;        int ack_number;        TcpSegment send_segment;        DatagramSocket socket;        // Quietly quit if there is not socket.        if (_async_socket == null ||            (socket = _async_socket.getDatagramSocket()) == null)        {            return;        }        // 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        {            DatagramPacket packet;            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);            // _fsm.Transmitted();        }        catch (IOException io_exception)        {            // _fsm.TransmitFailed(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);    }// 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 + -