TCP与UDP协议的比较

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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值