网络编程-03UDP

一、基于socket的UDP通信

1.udp的通信流程

服务器:
    创建套接字(socket)
    -->绑定IP地址和端口号(bind)    man 7 ip
    -->接收(recvfrom)/发送(sendto)
    -->关闭套接字(close)
客户端:
    创建套接字(socket)
    -->接收(recvfrom)/发送(sendto)
    -->关闭套接字(close)

2.UDP发送和接收

(1)发送数据—sendto
对比:
    普通:   
       ssize_t write(int fd, const void *buf, size_t count);
     TCP:         

       ssize_t send(int sockfd, const void *buf, size_t len, int flags);//tcp
       返回值:成功返回发送的字节数  
       参数:
           sockfd:套接字
           buf:发送内容缓冲区的首地址
           len:请求发送的字节数
           flags:默认选项0
    
      UDP:            
           ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                  const struct sockaddr *dest_addr, socklen_t addrlen); //UDP
          参数:
              sockfd:套接字
              buf:发送内容缓冲区的首地址
              flags:0
              dest_addr:接收端的地址就够信息首地址   struct sockaddr_in caddr存入
                                                   (struct sockaddr*)&caddr强转
              addrlen:接收端地址结构的大小  
(2)接收数据—recvfrom
#include <sys/types.h>
#include <sys/socket.h>

ssize_t recv(int sockfd, void *buf, size_t len, int flags); //TCP

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen);

参数:
    sockfd:套接字
    buf:缓冲区结构体首地址
    len:buf长度
    flags:0
    src_addr:发送端的地址结构信息首地址
    addrlen:发送端地址结构长度的地址

练习

练习1:搭建一个UDP发送端和接收端,发送端向接收发送信息,接收端打印信息

服务器:
int main(int argc, char *argv[])
{ 
    //1、创建套接字
     int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
     if(sockfd < 0)
     {
         perror("socket");
         exit(-1);
     }
    //2、绑定IP地址和端口号
     struct sockaddr_in saddr;
     saddr.sin_family = AF_INET;
     saddr.sin_port = htons(8888);
     saddr.sin_addr.s_addr = INADDR_ANY;    
     
     int s_len = sizeof(saddr);
    
     int ret = bind(sockfd, (struct sockaddr *)&saddr, s_len);
     if(ret < 0)
     {
         perror("bind");
         exit(-1);
      }

    //3、接收、发送数据
     char buf[N] = {0};
    
     struct sockaddr_in caddr;
     memset(&caddr, 0, sizeof(caddr));
    
     int c_len = sizeof(caddr);
    
     while(1)
     {
         memset(buf, 0, N);
         ret = recvfrom(sockfd, buf, N, 0, (struct sockaddr *)&caddr, &c_len);
         if(ret < 0)
         {
             perror("recvfrom");
             exit(-1);
          }
          printf("%s:%s\n", inet_ntoa(caddr.sin_addr), buf);
     }
    
    //4、关闭套接字
     close(sockfd);
     return 0;
} 
客户端:
int main(int argc, char *argv[])
{ 
    //1、创建套接字
     int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
     if(sockfd < 0)
     {
         perror("socket");
         exit(-1);
     }

    //2、接收、发送数据
     struct sockaddr_in saddr;
     saddr.sin_family = AF_INET;
     saddr.sin_port = htons(8888);
     saddr.sin_addr.s_addr = inet_addr("192.168.16.163");
    
     int s_len = sizeof(saddr);
    
     int ret;
     char buf[N] = {0};
     while(1)
     {
         fgets(buf, N, stdin);
    
         ret = sendto(sockfd, buf, N, 0, (struct sockaddr *)&saddr, s_len);
         if(ret < 0)
         {
             perror("sendto");
             exit(-1);
         }
     }
    //3、关闭套接字
     close(sockfd);
    
     return 0;
} 

练习2:设计一个时间服务器,发送端向服务器发送时间请求,接收方回传当前时间

服务器:
#define N 64

int main(int argc, char *argv[])
{ 
    //1、创建套接字
     int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
     if(sockfd < 0)
     {
         perror("socket");
         exit(-1);         
     }

    //2、绑定IP地址和端口号
     struct sockaddr_in saddr;
     saddr.sin_family = AF_INET;
     saddr.sin_port = htons(8888);
     saddr.sin_addr.s_addr = INADDR_ANY;
    
     int s_len = sizeof(saddr);
    
     int ret = bind(sockfd, (struct sockaddr *)&saddr, s_len);
     if(ret < 0)
     {
         perror("bind");
         exit(-1);
      }
    

    //3、接收、发送数据
     char buf[N] = {0};
     
     struct sockaddr_in caddr;
     memset(&caddr, 0, sizeof(caddr));
    
     int c_len = sizeof(caddr);
     time_t t;
     struct tm *my_t = NULL;
    
     while(1)
     {        
         memset(buf, 0, N);
         ret = recvfrom(sockfd, buf, N, 0, (struct sockaddr *)&caddr, &c_len);
         if(ret < 0)
         {
             perror("recvfrom");
             exit(-1);
         }
         if(strcmp(buf, "time\n") == 0)
         {
             memset(buf, 0, N);
             time(&t);
             my_t = localtime(&t);
             sprintf(buf, "%d-%d-%d %d:%d:%d", my_t->tm_year+1900, 
             my_t->tm_mon+1, my_t->tm_mday, my_t->tm_hour, my_t->tm_min, 
             my_t->tm_sec);
             sendto(sockfd, buf, N, 0, (struct sockaddr *)&caddr, c_len);    
         }
         else
         {
             strcpy(buf, "cmd error!");            
             sendto(sockfd, buf, N, 0, (struct sockaddr *)&caddr, c_len);
          }
    }
    

    //4、关闭套接字
     close(sockfd);
    
     return 0;
} 

客户端:
#define N 64

int main(int argc, char *argv[])
{ 
    //1、创建套接字
     int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
     if(sockfd < 0)
     {
         perror("socket");
         exit(-1);
     }

    //2、接收、发送数据
     struct sockaddr_in saddr, caddr;
     saddr.sin_family = AF_INET;
     saddr.sin_port = htons(8888);
     saddr.sin_addr.s_addr = inet_addr("192.168.16.163");
    
     int s_len = sizeof(saddr);
     int c_len = sizeof(caddr);
    
     memset(&caddr, 0, sizeof(caddr));
    
     int ret;
     char buf[N] = {0};
     while(1)
     {
         fgets(buf, N, stdin);
    
         ret = sendto(sockfd, buf, N, 0, (struct sockaddr *)&saddr, s_len);
         if(ret < 0)
         {
             perror("sendto");
             exit(-1);
        }
                
    memset(buf, 0, N);
    ret = recvfrom(sockfd, buf, N, 0, (struct sockaddr *)&caddr, &c_len);
    printf("recv %dbytes:%s\n", ret, buf);
    }
    //3、关闭套接字
     close(sockfd);
        
     return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值