首页 > 编程语言 >UDP 编程

UDP 编程

时间:2023-08-05 12:23:24浏览次数:39  
标签:serv SERV UDP addr int 编程 sockfd buf

UDP 编程

#include <sys/socket.h>
// 可以发送或接收一个长度为0的数据报

ssize_t recvfrom(int sockfd, 
                 void *buf, size_t nbytes, 
                 int flags,   // 常与 recv send recvmsg sendmsg 配合
                 struct sockaddr *from, socklen_t *addrlen); // 可用空指针表示不关心发送者

ssize_t sendto(int sockdf, 
               const void *buf, size_t nbytes, 
               int flags, 
               const struct sockaddr *to, socklen_t *addrlen);
服务端
 // 包含所有的头文件
#include <arpa/inet.h>
#include <bits/stdc++.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>

const int SERV_PORT = 60000;

int main(int argc, char const *argv[]) {
  int sockfd{0};
  struct sockaddr_in serv_addr;
  struct sockaddr_in client_addr;
  char buf_msg[BUFSIZ]{0};
  char buf_addr[BUFSIZ]{0};
  int n{0};

  bzero(&serv_addr, sizeof(serv_addr));
  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  serv_addr.sin_port = htons(SERV_PORT);

  sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  if (sockfd == -1) {
    perror("socket");
    exit(1);
  }

  if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) {
    perror("bind");
    exit(1);
  }

  while (true) {
    socklen_t client_addr_len = sizeof(client_addr);
    bzero(buf_msg, sizeof(buf_msg));
    n = recvfrom(sockfd, buf_msg, BUFSIZ, 0, (struct sockaddr *)&client_addr,
                 &client_addr_len);
    if (n == -1) {
      perror("recvfrom");
      exit(1);
    }
    printf(
        "received from %s at PORT %d: %s\n",
        inet_ntop(AF_INET, &client_addr.sin_addr, buf_addr, sizeof(buf_addr)),
        ntohs(client_addr.sin_port), buf_msg);

    sendto(sockfd, buf_msg, n, 0, (struct sockaddr *)&client_addr,
           sizeof(client_addr));
  }

  return 0;
}
客户端
 #include <arpa/inet.h>
#include <bits/stdc++.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>

// const int SERV_PORT = 60000;
// const char *SERV_ADDR = "127.0.0.1";

int main(int argc, char const *argv[]) {
  int sockfd{0};
  struct sockaddr_in serv_addr;
  struct sockaddr_in recv_addr;

  char buf_addr[BUFSIZ]{0};
  char buf_msg[BUFSIZ]{0};

  char SERV_ADDR[] = "127.0.0.1";
  int SERV_PORT = 60000;

  if (argc >= 2) {
    strncpy(SERV_ADDR, argv[1], strlen(argv[1]));
  }
  if (argc == 3) {
    int port_num = atoi(argv[2]);
    if (port_num > 0 && port_num < 65536) {
      SERV_PORT = port_num;
    }
  }

  bzero(&serv_addr, sizeof(serv_addr));
  serv_addr.sin_family = AF_INET;
  if (inet_pton(AF_INET, SERV_ADDR, &serv_addr.sin_addr) != 1) {
    perror("inet_pton");
    exit(1);
  }
  serv_addr.sin_port = htons(SERV_PORT);

  sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  if (sockfd == -1) {
    perror("socket");
    exit(1);
  }

  // // 客户端也可绑定端口,也可以由系统自动分配。设置本地ip和端口号
  // if (bind(sockfd, (struct sockaddr *)&client_addr, sizeof(client_addr))) {
  //   perror("bind");
  //   exit(1);
  // }

  // connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));

  while (printf("input >> "), scanf("%s%*c", buf_msg) > 0) {
    sendto(sockfd, buf_msg, strlen(buf_msg), 0, (struct sockaddr *)&serv_addr,
           sizeof(serv_addr));

    socklen_t recv_addr_len = sizeof(recv_addr);
    int n = recvfrom(sockfd, buf_msg, BUFSIZ, 0, (struct sockaddr *)&recv_addr,
                     &recv_addr_len);
    if (n == -1) {
      perror("recvfrom");
      exit(1);
    }

    inet_ntop(AF_INET, &recv_addr.sin_addr, buf_addr, sizeof(buf_addr));
    int recv_port = ntohs(recv_addr.sin_port);

    // 忽略来自其他地址的数据报
    if (strlen(buf_addr) != strlen(SERV_ADDR) ||
        strncmp(buf_addr, SERV_ADDR, strlen(SERV_ADDR)) != 0 ||
        recv_port != SERV_PORT) {
      printf("Datagram from %s:%d was ignored.\n", buf_addr, recv_port);
      continue;
    }

    printf("received from %s at PORT %d: %s\n", buf_addr,
           ntohs(recv_addr.sin_port), buf_msg);
  }

  return 0;
}

异步错误

当服务器进程退出后,客户端的recvfrom请求会永远阻塞。本地网络上,客户端发送udp数据报前进行一次ARP请求和应答,服务器返回一个ICMP端口不可达,但这个ICMP错误不会返回给客户进程。这个ICMP错误称为一个异步错误。

对于一个UDP套接字,它引发的异步错误不会发送给他,除非他使用 connect 进行了连接。如果不进行绑定,recvfrom仅能返回errno,不能返回IP和端口。

connect

使用connect绑定后,可以返回异步错误。实现记录对端iP和端口号 之后发送数据不可以再用 sentdo 指定目的地址,而是使用 write sendmsg 或 第五个参数为空的sendto 接收数据不可以再用 recvfrom 指定源地址,而是使用 read recvmsg 或 第五个参数为空的recvfrom

可以多次调用 connect 指定新的IP和端口号,将套接字地址结构体的 sin_family 指定为 AF_UNSPEC 可以断开连接。

使用 connect 显示指定目的地后会提升效率,类似的UDP也可以使用 bind 函数指定本地套接字IP和端口

 

 

 

标签:serv,SERV,UDP,addr,int,编程,sockfd,buf
From: https://www.cnblogs.com/zhh567/p/17607437.html

相关文章

  • Linux 网络编程常用辅助函数
    最大地址结构structsockaddr_storage;//足够大,能够支持任何套接字地址结构从套接字获取信息 //获取本地连接的地址externintgetsockname(int__fd,__SOCKADDR_ARG__addr,socklen_t*__restrict__len)__THROW;//获取连接另一侧的地址externintgetpeername(......
  • 《安富莱嵌入式周报》第319期:声音编程器,开源激光雕刻机,自制600W海尔贝克无刷电机,车用
    周报汇总地址:http://www.armbbs.cn/forum.php?mod=forumdisplay&fid=12&filter=typeid&typeid=104 更新视频教程:更新第7期ThreadX视频教程:如何实现RTOS高效的任务管理,抢占式调度,时间片调度和零中断延迟(2023-07-31)https://www.armbbs.cn/forum.php?mod=viewthread&tid......
  • Linux环境编程day03--文件管理
    分别使用标准IO和系统IO写入一百万个整数到文件,测试谁的时间更短?为什么?结论:在同等数据的写入下,使用标准IO要比直接使用系统IO更快原因:标准IO有缓冲区机制,在执行fwrite写文件时,数据不是直接调用系统IO写入磁盘,而是先存放在内存的缓冲区中,直到缓冲区满后才会调用一次系统IO全部写......
  • Linux环境编程day04--信号产生与处理
    信号管理基本概念1、中断当进程接收到消息后中止当前正在进行进程,转而去执行其它任务,等其它任务执行结束后再返回刚刚中止的位置,可以继续往下运行这种执行模式称为中断中断分为硬件中断、软件中断,硬件中断是由硬件设备引发的、软件中断是执行了中断指令引发2、信号信号是一......
  • 【雕爷学编程】Arduino动手做(182)---DRV8833双路电机驱动模块
    37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)与否,都会记录下来—小小的进步或是搞......
  • python多进程编程常用到的方法
    python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU资源,在python中大部分情况需要使用多进程。python提供了非常好用的多进程包Multiprocessing,只需要定义一个函数,python会完成其它所有事情。借助这个包,可以轻松完成从单进程到并发执行的转换。multiprocessing支......
  • 网络编程
    网络编程概述计算机网络:计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统.网络管理软件及网络通信协议的管理和协商下,实现资源共享和信息传递的计算机系统网络通信的要素网络编程中有两个主要的问题:如何准确地......
  • 编程精华资源(ITeye优秀专栏)大汇总
    博客是记录学习历程、分享经验的最佳平台,多年以来,各路技术大牛在ITeye网站上产生了大量优质的技术文章,并将系列文章集结成专栏,以便读者能够更便捷、更系统地浏览学习,这些可称之为“编程精华资源”。 为了便于读者更好地查阅,本文将ITeye中的这些精华资源进行了整理分类,你可以通过......
  • GitHub中最火的开源项目及编程语言
    GitHub目前已经成为全球最流行的开源项目托管平台,目前托管在GitHub上的项目数量已经达到了1000万,而达到这一里程碑只用了不到4年的时间,这足以见得开源的趋势以及GitHub的受欢迎程度。 2012年8月,GitHub在每个项目主页面中加入了Star功能,允许用户通过标注Star的形式来标记自己感兴趣......
  • 拓端tecdat|R语言编程指导随机森林模型中具有相关特征的变量重要性
    R语言随机森林模型中具有相关特征的变量重要性 变量重要性图是查看模型中哪些变量有趣的好工具。由于我们通常在随机森林中使用它,因此它看起来非常适合非常大的数据集。大型数据集的问题在于许多特征是“相关的”,在这种情况下,很难比较可变重要性图的值的解......