UDP/TCP简单对比

UDP(用户数据报协议)协议

这里写图片描述

  • UDP协议是无连接的 : 只需知道对端IP和端口号就可以发送数据,不需要建立连接,双方感知不到对方的存在。
  • UDP协议是不可靠的: 没有确认机制,不会对接收到的数据确认,就不知道对端是否收到。
  • UDP协议是面向数据报的: 不能灵活的控制数据的读写次数和数量, 只能一次读完。
  • UDP是支持全双工: 即双方可以同时进行读写操作。

UDP的缓存区

​ UDP没有真正意义上的发送缓存区,调用sendto将用户数据拷贝给内核,由内核执行后续动作。

​ UDP具有接收缓存区,缓存区满了之后,后续到来的数据将被丢弃。

UDP使用注意事项

​ 在UDP首部中,16位UDP最大长度,最大为64K(包括UDP首部),如果传输数据大于64K需要在上层进行分割,接收端上层进行组装。

TCP(传输控制)协议

这里写图片描述

  • TCP协议是面向连接
  • TCP协议是可靠的
  • TCP协议面向字节流
  • TCP支持全双工

TCP是面向连接的

​ TCP协议传输前需要先建立连接,三次握手,释放连接,四次挥手。

这里写图片描述
TCP是可靠的

​ 序号(按序到达)

​ 确认重传机制

​ 超时重传机制

​ 连接管理

​ 流量控制

​ 拥塞控制

TCP面向字节流

​ TCP存在发送缓冲区和接收缓存区。即可以一次读1字节也可以一次读100字节,可随意读取,当然写也可以。

​ 在发送数据时,如果数据太多会分成多个TCP的数据包发送出去,如果太少会等数量合适,或者合适的时机发送出去。

​ 在接收数据时,也是从缓存区读取数据。

总结

​ UDP和TCP不存在那个好或者不好的问题,只是适合的场景不同。
一般UDP适合高速传输和实时性较高的场景。
一般TCP适合可靠传输的场景。

简单的基于UDP的 socket

//UDP  

//UDP client

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

int CreateSocket()
{
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if(sock < 0)
    {
        perror("sock");
        exit(1);
    }
    return sock;
}
void client(int socket, const char* ip, const char* port)
{
    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(atoi(port));
    server.sin_addr.s_addr = inet_addr(ip);
    char buf[1024];
    struct sockaddr_in peer;

while(1)
 {
    printf("please Enter:");
    fflush(stdout);
    ssize_t s = read(0, buf, sizeof(buf)-1);
    if(s > 0)
    {
       sendto(socket, buf, sizeof(buf), 0\
                       , (struct sockaddr*)&server, sizeof(server));
    }
    socklen_t len = sizeof(peer);
    ssize_t r = recvfrom(socket, buf, sizeof(buf), 0\
                    , (struct sockaddr*)&peer, &len);
    if(r > 0)
    {
        buf[s] = 0;
        printf("[%s : %d] server echo:%s",inet_ntoa(peer.sin_addr),\
                        ntohs(peer.sin_port), buf);
    }
 }


}
int main(int argc, char* argv[])
{
    if(argc != 3)
    {
        printf("%s [ip : port]", argv[0]);
        return 1;
    }
    int sock = CreateSocket();
    client(sock, argv[1], argv[2]);
    return 0;

}
// udp client
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#define ERR_EXIT(x) do\
{  \
   perror(x);\
        exit(1);\
        }while(0)

int CreateSocket(const char* ip,const char* port)
{
      int sock = socket(AF_INET,SOCK_DGRAM, 0);
      if(sock < 0)
      {
            ERR_EXIT("sock");
      }
     struct sockaddr_in local;
       local.sin_family = AF_INET;
       local.sin_port = htons(atoi(port));
       local.sin_addr.s_addr = inet_addr(ip);
      if(bind(sock,(struct sockaddr*)&local, sizeof(local)) < 0)
      {
            ERR_EXIT("bind");
      }
      return sock;
}
void service(const int sock)
{
     struct sockaddr_in local;
     char buf[1024];
    while(1)
     {
        socklen_t len = sizeof(local);
       ssize_t ret =  recvfrom(sock, buf, sizeof(buf), 0, \
                        (struct sockaddr*)&local, &len);
         if(ret >  0)
         {
            buf[ret-1] = 0;
            printf("[%s : %d]client: %s\n",\
                            inet_ntoa(local.sin_addr),ntohs(local.sin_port)\
                            ,buf);
            sendto(sock, buf, sizeof(buf), 0,\
                        (struct sockaddr*)&local, sizeof(local));
         }
     }

}
void UseSocket(const char* str)
{
    printf("%s ip:   port: \n", str);
}
int main(int agrc, char* argv[])
{
    if(agrc != 3)
    {
        UseSocket(argv[0]);
        return 1;
    }
    int socket = CreateSocket(argv[1], argv[2]);
    service(socket);
    return 0;

}

简单的基于TCP的 socket


//client
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

int startup(char* ip, char* port)
{
    int sock = socket(AF_INET, SOCK_STREAM, 0); 
    if(sock < 0)
    {   
        perror("sock");
        exit(2);

}   
 struct sockaddr_in pr; 
 pr.sin_family = AF_INET;
 pr.sin_port = htons(atoi(port));
 //inet_pton(AF_INET, ip, &pr.sin_addr );
 pr.sin_addr.s_addr = inet_addr(ip);
 int ret = connect(sock, (struct sockaddr*)&pr, sizeof(pr));
 if(ret < 0)
 {   
    perror("connect");
    exit(3);
 }   
  printf("get connect\n");
return sock;


}
void client(int sock)
{
      char buf[1024];    
      while(1)
      {    
        memset(buf, 0, sizeof(buf));
        printf("client Please enter: ");
        fgets(buf, sizeof(buf), stdin);
        if(strcmp(buf, "quit\n") == 0)
        {   
            printf("client quit now!\n");
            break;


    }   
    write(sock, buf, strlen(buf)-1);
    printf("wait....\n");


//      int s =  read(sock, buf, sizeof(buf)-1);
//      buf[s] = 0;
//      printf("server $: %s\n", buf);   
      }   
   close(sock);
}

int main(int argc, char* argv[])
{
    if(argc != 3)
    {   
        printf("Usage: %s [ip : port]\n", argv[0]);
        return 1;
    }   
    int sock = startup(argv[1], argv[2]);


client(sock);
return 0;


}

//server
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
int startup(char* ip, char* port)
{
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if(sock < 0)
    {
        perror("sock");
        exit(2);

}
struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_port = htons(atoi(port));
local.sin_addr.s_addr = inet_addr(ip);
if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0)
{
    perror("bind");
    close(sock);
    exit(3);
}
if(listen(sock, 10) < 0)
{
    perror("listen");
    close(sock);
    exit(4);
}
printf("bind and listen success...\n");
return sock;

}
void sock_server(int);
void* tcp_server(void *arg)
{
    int sock = (int)arg;
    sock_server(sock);
}

void sock_server(int sock)
{
    char buf[1024];
    int s ;
    while(1)
      {
        printf("wait....\n");
        s =  read(sock, buf, sizeof(buf)-1);
        if(s < 0)
        {
            perror("read");
            exit(6);
        }
        else if(s == 0)
        {
            printf("connect --\n");
            close(sock);
            break;
        }
        else
        {
        buf[s] = 0;
        printf("client #: %s\n", buf);
        write(sock, buf, strlen(buf));
//      printf("server Please enter: ");
//      memset(buf, 0, sizeof(buf));
//      fgets(buf, sizeof(buf)-1, stdin);
//      write(sock, buf, sizeof(buf));
        }
      }
}
void service(int socket)
{
    struct sockaddr_in peer;
    char buf[1024];
    char ip[40];
    for(;;)
    {
       socklen_t len = sizeof(peer);
      int sock = accept(socket, (struct sockaddr*)&peer, &len);
       if(sock < 0)
       {
          perror("accept");
          exit(5);
       }
      memset(ip, 0x0, sizeof(ip));
      inet_ntop(AF_INET,&peer.sin_addr, ip, sizeof(ip));
      printf("get connect  [ip:%s port: %d]\n", ip, ntohs(peer.sin_port));
      pthread_t tid;
        if(pthread_create(&tid, NULL, tcp_server, (void*)sock) < 0)
        {
            perror("pthread_create");
            exit(7);
        }

    pthread_detach(tid);


//      pid_t pid = fork();
//    if(pid < 0)
//    {
//        printf("fork error\n");
//    }
//    else if(pid == 0)
//    {
//      pid_t cpid = fork();
//      if(cpid < 0)
//      {
//          printf("child fork error\n");
//      }
//      else if(cpid == 0)
//      {
//          close(socket);
//          sock_server(sock);      
//      }
//      else
//      {
//          exit(0);
//      }
//      }
//    else
//    {
//         waitpid(pid, NULL, 0);
//         close(sock);
//          
//    }
    }

}

int main(int argc, char* argv[])
{
    if(argc != 3)
    {
        printf("Usage: %s [ip : port]\n", argv[0]);
        return 1;
    }
    int sock = startup(argv[1], argv[2]);
    service(sock);
    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值