`
jimmee
  • 浏览: 528525 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

UDT协议-基于UDP的可靠数据传输协议的实现分析(6)-链接的建立和关闭

阅读更多

1. 模式有client/server mode(客户端,服务器端模式) and the rendezvous mode(会合模式,可同时向对方发送请求)

2. client发送的握手信息,信息有:
1) UDT version: udt版本,主要用作兼容性处理
2) Socket Type: STREAM (0) or DGRAM (1).
3) Initial Sequence Number: 第一包的序号,是个随机值
4) Packet Size: the maximum size of a data packet (including all
    headers). This is usually the value of MTU.
5) Maximum Flow Window Size
6) Connection Type. This information is used to differential the
        connection setup modes and request/response.
7) Socket ID. The client UDT socket ID.
8) Cookie. This is a cookie value used to avoid SYN flooding attack
        [RFC4987].
9) Peer IP address: B's IP address.

   

 //initial handshake for connect
    protected void sendInitialHandShake()throws IOException{
        ConnectionHandshake handshake = new ConnectionHandshake();
        handshake.setConnectionType(ConnectionHandshake.CONNECTION_TYPE_REGULAR);
        handshake.setSocketType(ConnectionHandshake.SOCKET_TYPE_DGRAM);
        long initialSequenceNo=SequenceNumber.random();
        setInitialSequenceNumber(initialSequenceNo);
        handshake.setInitialSeqNo(initialSequenceNo);
        handshake.setPacketSize(getDatagramSize());
        handshake.setSocketID(mySocketID);
        handshake.setMaxFlowWndSize(flowWindowSize);
        handshake.setSession(this);
        handshake.setAddress(endPoint.getLocalAddress());
        logger.info("Sending "+handshake);
        // 没有设置destinationID
        endPoint.doSend(handshake);
    }

 

client的状态之后设置位handshaking

3. server端对握手信息的处理

接收到握手信息后,产生cookie返回,client端需要返回相同的cookie到server
 
 

   /*
     * response after the initial connection handshake received:
     * compute cookie
     */
    protected void ackInitialHandshake(ConnectionHandshake handshake)throws IOException{
        ConnectionHandshake responseHandshake = new ConnectionHandshake();
        //compare the packet size and choose minimun
        long clientBufferSize=handshake.getPacketSize();
        long myBufferSize=getDatagramSize();
        long bufferSize=Math.min(clientBufferSize, myBufferSize);
        long initialSequenceNumber=handshake.getInitialSeqNo();
        setInitialSequenceNumber(initialSequenceNumber);
        setDatagramSize((int)bufferSize);
        responseHandshake.setPacketSize(bufferSize);
        responseHandshake.setUdtVersion(4);
        responseHandshake.setInitialSeqNo(initialSequenceNumber);
        responseHandshake.setConnectionType(-1);
        responseHandshake.setMaxFlowWndSize(handshake.getMaxFlowWndSize());
        //tell peer what the socket ID on this side is
        responseHandshake.setSocketID(mySocketID);
        responseHandshake.setDestinationID(this.getDestination().getSocketID());
        responseHandshake.setSession(this);
        // 产生cookie
        sessionCookie=SequenceNumber.random();
        responseHandshake.setCookie(sessionCookie);
        responseHandshake.setAddress(endPoint.getLocalAddress());
        logger.info("Sending reply "+responseHandshake);
        endPoint.doSend(responseHandshake);
    }

 
server端的状态为n_handshake=1(第一次握手)

4. client端收到server端的返回
      

  // 第一次握手的响应
        if (getState()==handshaking) {
            logger.info("Received initial handshake response from "+peer+"\n"+hs);
            if(hs.getConnectionType()==ConnectionHandshake.CONNECTION_SERVER_ACK){
                try{
                    //TODO validate parameters sent by peer
                    long peerSocketID=hs.getSocketID();
                    sessionCookie=hs.getCookie();
                    destination.setSocketID(peerSocketID);
                    setState(handshaking+1);
                }catch(Exception ex){
                    logger.log(Level.WARNING,"Error creating socket",ex);
                    setState(invalid);
                }
                return;
            }
            else{
                logger.info("Unexpected type of handshake packet received");
                setState(invalid);
            }
        }

 
client的状态设置为handshaking+1

同时发送二次握手信息

//2nd handshake for connect
    protected void sendSecondHandshake()throws IOException{
        ConnectionHandshake handshake = new ConnectionHandshake();
        handshake.setConnectionType(ConnectionHandshake.CONNECTION_TYPE_REGULAR);
        handshake.setSocketType(ConnectionHandshake.SOCKET_TYPE_DGRAM);
        handshake.setInitialSeqNo(initialSequenceNo);
        handshake.setPacketSize(getDatagramSize());
        handshake.setSocketID(mySocketID);
        handshake.setMaxFlowWndSize(flowWindowSize);
        handshake.setSession(this);
        handshake.setCookie(sessionCookie);
        handshake.setAddress(endPoint.getLocalAddress());
        handshake.setDestinationID(getDestination().getSocketID());
        logger.info("Sending confirmation "+handshake);
        endPoint.doSend(handshake);
    }

 

5. server端接收到client的二次握手

protected void sendFinalHandShake(ConnectionHandshake handshake)throws IOException{

        if(finalConnectionHandshake==null){
            finalConnectionHandshake= new ConnectionHandshake();
            //compare the packet size and choose minimun
            long clientBufferSize=handshake.getPacketSize();
            long myBufferSize=getDatagramSize();
            long bufferSize=Math.min(clientBufferSize, myBufferSize);
            long initialSequenceNumber=handshake.getInitialSeqNo();
            setInitialSequenceNumber(initialSequenceNumber);
            setDatagramSize((int)bufferSize);
            finalConnectionHandshake.setPacketSize(bufferSize);
            finalConnectionHandshake.setUdtVersion(4);
            finalConnectionHandshake.setInitialSeqNo(initialSequenceNumber);
            finalConnectionHandshake.setConnectionType(-1);
            finalConnectionHandshake.setMaxFlowWndSize(handshake.getMaxFlowWndSize());
            //tell peer what the socket ID on this side is
            finalConnectionHandshake.setSocketID(mySocketID);
            finalConnectionHandshake.setDestinationID(this.getDestination().getSocketID());
            finalConnectionHandshake.setSession(this);
            finalConnectionHandshake.setCookie(sessionCookie);
            finalConnectionHandshake.setAddress(endPoint.getLocalAddress());
        }
        logger.info("Sending final handshake ack "+finalConnectionHandshake);
        endPoint.doSend(finalConnectionHandshake);
    }

 

server端的状态位ready,链接建立完毕

6. client端收到二次握手的确认
 

if(getState()==handshaking+1){ // 第二次握手的响应
            try{
                logger.info("Received confirmation handshake response from "+peer+"\n"+hs);
                //TODO validate parameters sent by peer
                setState(ready);
                socket=new UDTSocket(endPoint,this);
            }catch(Exception ex){
                logger.log(Level.WARNING,"Error creating socket",ex);
                setState(invalid);
            }

 
client端状态为ready, 链接建立完毕

7. 关闭,接收到Shutdown包,直接设置状态为关闭

 

8.  一些类的梳理:

 

(1)一个链接,可以理解为一个session

client端对应一个ClientSession
server端对应一个ServerSession

(2) Server对应UDTServerSocket,Client对应UDTClient

(3) 底层的udp的传输和多个Session的维护使用UDPEndPoint

(4) 每个session的数据操作实际对应一个UDTSocket和CongestionControl

(5)每个UDTSocket对应一个UDTReceiver和UDTSender,对应一个UDTInputStream和UDTOutputStream

(6)CongestionControl用于拥塞控制

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics