TCP与UDP协议的比较

来源:互联网 发布:手机查看淘宝注册时间 编辑:程序博客网 时间:2024/06/03 22:05

1 UDP的特点
  UDP提供不可靠的交付,但也有优点:
  1) 发送数据前不需要建立连接,减少开销与发送数据的延迟。
  2) UDP不使用拥塞控制,不保证交付,减少了复杂的连接状态表,网络的拥塞不会使源主机的发送速率降低。
  3) 数据报首部字节比TCP少,节约开销。
  所以UDP适用于实时应用,网络拥塞时允许丢失一点数据。

2 TCP的特点
  TCP是面向连接的运输层协议,它提供双工和可靠交付的服务。
  TCP与UDP的最大区别是:TCP是面向连接的,而UDP是无连接的
  TCP的的可靠性基于:
  1) 基于确认请求机制的网络协议,经过确认的报文,可保证可靠性,最新发出的报文无法保证。
  2) 保证数据按序到达。
  3) 丢包重传。
  4) 经历面向连接保证可靠性。
  5) 进行流量控制。
  6) 提供定时器(超时重传定时器)。
  7) 逻辑上实现网络拥塞。

3 对以上几点的解释
  1) TCP的确认是对接收到的数据的最高序号(即收到的数据流中的最后一个序号)表示确认。但接收端返回的确认号是己收到的数据的最高序号加1也就是说,确认号表示接收端期望下次收到的数据中的第一个数据字节的序号。
  TCP传输的可靠是由于使用了序号和确认。当TCP发送一报文段时,它同时也在自己的重传队列中存放一个副本。若收到确认,则删除此副本。若在计时器时间到之前没有收到确认,则重传此报文段的副本。TCP的确认并不保证数据己由应用层交付给了端用户,而只是表明在接收端的TCP收到了对方所发送的报文段。


  2) 流量控制(点对点通信的控制),TCP采用大小可变的滑动窗口进行流量控制。流量控制就是控制发送端的数据,使得来得及接受。发送端发送大小大于接收端接收时,丢失。也就是我,接受端向告诉发送端自己所能接收的字节大小,发送端可以分批发送,但不可超过允许发送端发送数据的大小。
  3) 拥塞控制,防止过多的数据注入到网络中,使网络中的路由器或链路不致过载。拥塞的产生:
  当网络的吞吐量明显地小于理想的吞吐量时,网络就进入了轻度拥塞的状态。当提供的负载达到某一数值时,网络的吞吐量反而随提供的负载的增大而下降,这时网络就进入了拥塞状态。当提供的负载继续增大到某一数值时,网络的吞吐量就下降到零,网络已无法工作。这就是所谓的死锁。
  拥塞控制方法:1> 慢开始:从小增大拥塞窗口控制(倍数增加)。 2> 拥塞避免:从小增大拥塞窗口控制(常数增加)
3> 快重传:发送端连续收到三个重复的ACK,断定分组丢失,此时重传丢失的报文,不等待定时器的超时。 4> 快恢复:与快重传配合使用。
  4) TCP每发送一个报文段,就对这个报文段设置一次定时器,如果重传时间到但没收到确认,重传这一报文。

4 TCP三次握手,四次挥手
  TCP的flags的五中状态:SYN表示建立连接,FIN表示关闭连接,ACK表示响应,PSH表示有 DATA数据传输,RST表示连接重置。
  设客户进运行在主机A中。它先向其TCP发出主动打开命令,表明要向某个IP地址的某个端囗建立运输连接。
  主机A的TCP向主机B的TCP发出连接请求报文段,其首部中的同步比特SYN应置为l,同时选择一个序号x,表明在后面传送数据时的第一个数据字节的序号是x+1。
  主机B的TCP收到连接请求报文段后,如同意,则发回确认。在确认报文段中应将SYN和ACK置为1,确认号应为x+1,同时也为自己选抒一个序号y。
  主机A的TCP收到此报文段后,还要向B给出确认,其ACK置1,确认号为y+1。
  运行客户进程的主机A的TCP通知上层应用进程,连接已经建立(或打开)。
  当运行服务器进程的主机B的TCP收到主机A的确认后.也通知其上层应用进程,连接己经建立。
  挥手与此类似。


5 TCP与UDP通信协议程序
  单进程代码:
tcp_server

#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <string.h>#include <stdlib.h>#include <netinet/in.h>#include <arpa/inet.h>static void useage(const char* proc){    printf("Useage: %s [local_ip] [local_port]\n",proc);}int startup(const char* ip, int port){    int sock = socket(AF_INET, SOCK_STREAM,0);    if(sock < 0)    {        perror("socket");        exit(1);    }    struct sockaddr_in local;    local.sin_family = AF_INET;    local.sin_port = htons(port);    local.sin_addr.s_addr = inet_addr(ip);    if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0)    {        perror("bind");        exit(2);    }    if(listen(sock, 10) < 0)    {        perror("listen");        exit(3);    }    return sock;}int main(int argc, char *argv[]){    if(argc != 3)    {        useage(argv[0]);        return 4;    }    int sock = startup(argv[1], atoi(argv[2]));    while(1)    {        struct sockaddr_in client;        socklen_t len = sizeof(client);        int new_fd = accept(sock,(struct sockaddr*)&client, &len);        if(new_fd < 0)        {            perror("accept");            continue;        }        char buf[1024];        while(1)        {            ssize_t s = read(new_fd, buf,sizeof(buf)-1);            if(s > 0)            {                buf[s] = 0;                printf("client: %s\n",buf);                write(new_fd, buf, strlen(buf));            }            else if(s == 0)            {                printf("client is done");                break;            }            else            {                perror("read");                return 5;            }        }    }    return 0;}

tcp_client

#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <string.h>#include <stdlib.h>#include <netinet/in.h>#include <arpa/inet.h>static void useage(const char* proc){    printf("Useage: %s [local_ip] [local_port]\n",proc);}int main(int argc, char *argv[]){    if(argc != 3)    {        useage(argv[0]);        return 1;    }    int sock = socket(AF_INET, SOCK_STREAM,0);    if(sock < 0)    {        perror("socket");        return 2;    }    struct sockaddr_in peer;    peer.sin_family = AF_INET;    peer.sin_port = htons(atoi(argv[2]));    peer.sin_addr.s_addr = inet_addr(argv[1]);    if(connect(sock, (struct sockaddr*)&peer, sizeof(peer)) < 0)    {        perror("connect");        return 3;    }    char buf[1024];    while(1)    {        printf("please enter# ");        fflush(stdout);        ssize_t s = read(0, buf,sizeof(buf)-1);        if(s > 0)        {            buf[s-1] = 0;            write(sock, buf, strlen(buf));           ssize_t _s = read(sock, buf, strlen(buf)-1);           if(_s > 0)           {               buf[_s] = 0;           }           else if(_s == 0)           {               printf("server quit\n");               break;           }           else           {               perror("read");               break;           }        }    }    close(sock);    return 0;}
原创粉丝点击