TCP的流模式與UDP的報文模式對比


1       案例背景

在學習TCP-IP協議詳解卷一時,讀到介紹TCP協議的部分,發現TCP的首部是沒有報文總長度字段的,而在UDP中是有的,對這個問題的思考引出了兩者之間的區別。

2    案例分析

TCP報文的格式:

 

TCP首部的格式:

 

UDP報文的格式:

 

UDP首部的格式:

 

針對首部公共部分的對比,很明顯的一個區別是UDP首部是有數據報總長度字段的,而TCP首部是沒有數據報總長度字段的,這個原因的解釋在TCP-IP詳解卷一答案中的解釋是TCP首部有選項字段而UDP首部大小是固定的,而網上的查詢結果有一種是因為模式的不同。

我比較贊同的是,TCP是面向連接的流模式,而UDP是不連接的數據報模式。

3       實驗

實驗一:

       TCP客戶端循環發送數據到服務器,主循環部分分三次調用send或者sendto,分別發送111,222,333;而服務器是睡眠十秒,然后調用recv或者recvfrom接收數據。注意,只接收一次。

客戶端發送部分(其中的sendto可用send代替):

    while(1)

       {

              memset(achBuf,0,1024);

              memcpy(achBuf,"111",3);

        buflen = strlen(achBuf);

              ret = sendto(nSockFd,achBuf,buflen,0,(struct sockaddr*)&ServAddr,sizeof(ServAddr));

              memset(achBuf,0,1024);

              memcpy(achBuf,"222",3);

        buflen = strlen(achBuf);

           ret = sendto(nSockFd,achBuf,buflen,0,(struct sockaddr*)&ServAddr,sizeof(ServAddr));

              memset(achBuf,0,1024);

              memcpy(achBuf,"333",3);

        buflen = strlen(achBuf);

           ret = sendto(nSockFd,achBuf,buflen,0,(struct sockaddr*)&ServAddr,sizeof(ServAddr));

}

服務器接收部分(其中的recv可用recvfrom代替):

       sleep(10);

       recv(conn,buf,1024,0);

       printf("conn = %s\n",buf);

四種不同的發送接收組合,均是以下結果:

 

實驗二:

UDP客戶端循環發送數據到服務器,分三次調用sendto,分別發送了111,222,333;服務器睡眠十秒,然后調用recvfrom循環接收數據。為了表示是第幾次接收到的數據,首先打印接收序號。

客戶端發送部分:

       nNum = sendto(nSockFd,"111\n", 12, 0, (struct sockaddr *)&MCAddr,sizeof(MCAddr));

    printf("nNum = %d\n",nNum);

       nNum = sendto(nSockFd,"222\n", 12, 0, (struct sockaddr *)&MCAddr,sizeof(MCAddr));

    printf("nNum = %d\n",nNum);   

       nNum = sendto(nSockFd,"333\n", 12, 0, (struct sockaddr *)&MCAddr,sizeof(MCAddr));

    printf("nNum = %d\n",nNum);

服務器接收部分:

       while(1)

       {

              sleep(10);

              memset(achBuf,0,MAXBUFLEN);

              nNum = recvfrom(nServFd,achBuf,MAXBUFLEN,0,(struct sockaddr *)&CliAddr, &dwCliAddrLen);

             

              if(nNum < 0)

              {

                     printf("recverror\n");

                     break;    

              }

              printf("%d\n",i);i++;

              printf("%s\n",achBuf);

       }

結果如下圖:

 

4       總結

由實驗結果可以知道,讀取數據的方式和調用的函數沒有關系,而和套接字類型有關。而TCP接收數據時不是一次只讀取一個數據報,而是根據buf的大小和緩沖區數據的大小中的較小值來讀取數據的,可以一次性讀取多個數據報;而UDP是按照接收到的數據次序,一次只讀取一個數據報。

現在可以大概的推敲出流模式和數據報模式的區別,接收和發送數據方式的不同。流模式只要不超過流的容量就可以繼續往流上提交數據,另一端只要流上有數據就可以讀取,而不管這個數據的開頭和結尾;數據報模式,有嚴格的次序關系和數據報的分割關系。而這兩種的不同大概是由於TCP一個套接字只接收來自一個對象的數據,而UDP套接字可以接收來自任意對象的數據。

兩者在模式上的不同,導致兩者在效率和應用模式上的不同。

在每個數據都要分析的情況下,例如發送一條配置命令,TCP必須約定消息頭格式指出這條消息的大小,而UDP不需要。而在流媒體數據上,由於TCP有數據重組的特性,效率相對UDP更高。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM