zoukankan      html  css  js  c++  java
  • 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 ",buf);

    四种不同的发送接收组合,均是以下结果:

    实验二:

    UDP客户端循环发送数据到服务器,分三次调用sendto,分别发送了111,222,333;服务器睡眠十秒,然后调用recvfrom循环接收数据。为了表示是第几次接收到的数据,首先打印接收序号。

    客户端发送部分:

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

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

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

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

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

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

    服务器接收部分:

           while(1)

           {

                  sleep(10);

                  memset(achBuf,0,MAXBUFLEN);

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

                 

                  if(nNum < 0)

                  {

                         printf("recverror ");

                         break;    

                  }

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

                  printf("%s ",achBuf);

           }

    结果如下图:

    4       总结

    由实验结果可以知道,读取数据的方式和调用的函数没有关系,而和套接字类型有关。而TCP接收数据时不是一次只读取一个数据报,而是根据buf的大小和缓冲区数据的大小中的较小值来读取数据的,可以一次性读取多个数据报;而UDP是按照接收到的数据次序,一次只读取一个数据报。

    现在可以大概的推敲出流模式和数据报模式的区别,接收和发送数据方式的不同。流模式只要不超过流的容量就可以继续往流上提交数据,另一端只要流上有数据就可以读取,而不管这个数据的开头和结尾;数据报模式,有严格的次序关系和数据报的分割关系。而这两种的不同大概是由于TCP一个套接字只接收来自一个对象的数据,而UDP套接字可以接收来自任意对象的数据。

    两者在模式上的不同,导致两者在效率和应用模式上的不同。

    在每个数据都要分析的情况下,例如发送一条配置命令,TCP必须约定消息头格式指出这条消息的大小,而UDP不需要。而在流媒体数据上,由于TCP有数据重组的特性,效率相对UDP更高。

  • 相关阅读:
    11G-使用跨平台增量备份减少可移动表空间的停机时间 XTTS (Doc ID 1389592.1)
    如何在asm上定位数据块
    log file switch (checkpoint incomplete)
    踩坑记录(git)-误提交target文件夹删除办法
    踩坑记录(java)-双层增强for调用remove(obj)报错 java.util.ConcurrentModificationException(并发修改异常)
    Zookeeper服务端的创建及简单的客户端创建节点
    SpringAOP(注解方式实现面向切面编程)之常用Before、After、Around
    EasyExcel示例(阿里巴巴)基于Maven
    Redis简单命令(部分示例代码)
    sqlserver日志处理不当而造成的隐患
  • 原文地址:https://www.cnblogs.com/leo0000/p/4863139.html
Copyright © 2011-2022 走看看