Unix/Linux编程:UDS 数据报

这篇具有很好参考价值的文章主要介绍了Unix/Linux编程:UDS 数据报。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

〇、前言

对于recvfrom()来讲,src_addr 和 addrlen 参数会返回用来发送数据报的远程 socket 的地址。
(这些参数类似于 accept()中的 addr 和 addrlen 参数,它们返回已连接的对等 socket 的地址。) src_addr 参数是一个指针,它指向了一个与通信 domain 匹配的地址结构。与 accept()一样, addrlen 是一个值-结果参数。在调用之前应该将 addrlen 初始化为 src_addr 指向的结构的大小;在返回之后,它包含了实际写入这个结构的字节数。

一、接收:recvfrom()

在Socket编程中,recvfrom()函数用于从套接字接收数据,并获取发送方的地址信息。它适用于基于数据报的套接字,如UDP套接字。
recvfrom()函数的原型如下:

#include <sys/types.h>
#include <sys/socket.h>

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

  • sockfd:Socket文件描述符,表示要接收数据的套接字。
  • buf:指向接收数据的缓冲区的指针。
  • len:缓冲区的大小,表示最多接收多少字节的数据。
  • flags:标志参数,用于控制接收操作的行为,通常设置为0。
  • src_addr:指向struct sockaddr类型的指针,用于存储发送方的地址信息。
  • addrlen:指向socklen_t类型的指针,用于存储src_addr结构体的大小。

在调用recvfrom() 函数时,需要提供一个已经创建和绑定的套接字,并传递一个缓冲区以存储接收到的数据。函数将阻塞,直到有数据到达套接字。

当接收到数据时,recvfrom() 函数将数据存储在提供的缓冲区中,并将发送方的地址信息存储在src_addr中。实际接收的字节数将作为函数的返回值返回,如果返回值为-1,则表示发生了错误。

下面是一个简单的示例,演示如何使用recvfrom()函数接收UDP套接字的数据:

// us_xfr.h
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <zconf.h>

#define BUF_SIZE 10 

#define SV_SOCK_PATH "/tmp/ud_ucase"

int main(int argc, char *argv[]) {
    struct sockaddr_un svaddr, claddr;
    int sfd, j;
    ssize_t numBytes;
    socklen_t len;
    char buf[BUF_SIZE];

    sfd = socket(AF_UNIX, SOCK_DGRAM, 0); /* Create server socket */
    if (sfd == -1) {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    if (strlen(SV_SOCK_PATH) > sizeof(svaddr.sun_path) - 1) {
        printf("Server socket path too long: %s", SV_SOCK_PATH);
        exit(EXIT_FAILURE);
    }

    if (remove(SV_SOCK_PATH) == -1 && errno != ENOENT) {
        printf("remove-%s", SV_SOCK_PATH);
        exit(EXIT_FAILURE);
    }

    memset(&svaddr, 0, sizeof(struct sockaddr_un));
    svaddr.sun_family = AF_UNIX;
    strncpy(svaddr.sun_path, SV_SOCK_PATH, sizeof(svaddr.sun_path) - 1);

    if (bind(sfd, (struct sockaddr *)&svaddr, sizeof(struct sockaddr_un)) ==
        -1) {
        printf("bind");
        exit(EXIT_FAILURE);
    }

    /* Receive messages, convert to uppercase, and return to client */
    for (;;) {
        len = sizeof(struct sockaddr_un);
        numBytes =
            recvfrom(sfd, buf, BUF_SIZE, 0, (struct sockaddr *)&claddr, &len);
        if (numBytes == -1) {
            printf("recvfrom");
            exit(EXIT_FAILURE);
        }

        printf("Server received %zd bytes from %s\n", numBytes,
               claddr.sun_path);

        for (j = 0; j < numBytes; j++)
            buf[j] = toupper((unsigned char)buf[j]);

        if (sendto(sfd, buf, numBytes, 0, (struct sockaddr *)&claddr, len) !=
            numBytes) {
            printf("sendto");
            exit(EXIT_FAILURE);
        }
    }
}

二、发送:sendto()

在Socket编程中,sendto() 函数用于通过套接字发送数据到指定的目标地址。它适用于基于数据报的套接字,如UDP套接字。
sendto() 函数的原型如下:

#include <sys/types.h>
#include <sys/socket.h>

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);

  • sockfd:Socket文件描述符,表示要发送数据的套接字。
  • buf:指向要发送的数据的缓冲区的指针。
  • len:要发送的数据的字节数。
  • flags:标志参数,用于控制发送操作的行为,通常设置为0。
  • dest_addr:指向struct sockaddr类型的目标地址结构体的指针,用于指定发送数据的目标地址。
  • addrlen:dest_addr结构体的大小。

下面是一个简单的示例,演示如何使用sendto() 函数发送UDP套接字的数据:

#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <zconf.h>

#define BUF_SIZE                                                               \
    10 /* Maximum size of messages exchanged between client and server */
#define SV_SOCK_PATH "/tmp/ud_ucase"
int main(int argc, char *argv[]) {
    struct sockaddr_un svaddr, claddr;
    int sfd, j;
    size_t msgLen;
    ssize_t numBytes;
    char resp[BUF_SIZE];

    if (argc < 2 || strcmp(argv[1], "--help") == 0) {
        printf("%s msg...\n", argv[0]);
        exit(1);
    }

    /* Create client socket; bind to unique pathname (based on PID) */

    sfd = socket(AF_UNIX, SOCK_DGRAM, 0);
    if (sfd == -1) {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    memset(&claddr, 0, sizeof(struct sockaddr_un));
    claddr.sun_family = AF_UNIX;
    snprintf(claddr.sun_path, sizeof(claddr.sun_path), "/tmp/ud_ucase_cl.%ld",
             (long)getpid());

    if (bind(sfd, (struct sockaddr *)&claddr, sizeof(struct sockaddr_un)) ==
        -1) {
        perror("bind");
        exit(EXIT_FAILURE);
    }

    /* Construct address of server */

    memset(&svaddr, 0, sizeof(struct sockaddr_un));
    svaddr.sun_family = AF_UNIX;
    strncpy(svaddr.sun_path, SV_SOCK_PATH, sizeof(svaddr.sun_path) - 1);


    for (j = 1; j < argc; j++) {
        msgLen = strlen(argv[j]); 
        if (sendto(sfd, argv[j], msgLen, 0, (struct sockaddr *)&svaddr,
                   sizeof(struct sockaddr_un)) != msgLen) {
            perror("sendto");
            exit(EXIT_FAILURE);
        }

        numBytes = recvfrom(sfd, resp, BUF_SIZE, 0, NULL, NULL);

        if (numBytes == -1) {
            perror("recvfrom");
            exit(EXIT_FAILURE);
        }
        printf("Response %d: %.*s\n", j, (int)numBytes, resp);
    }
    remove(claddr.sun_path); 
    exit(EXIT_SUCCESS);
}

三、运行

编译运行之后,启动客户端和服务端,键入:

(base) ***@shenjian Test % ./client_ud 你好 
hello nihao
Response 1: 你好
Response 2: HELLO
Response 3: NIHAO

可以在服务端看到:

Server received 6 bytes from /tmp/ud_ucase_cl.16568
Server received 5 bytes from /tmp/ud_ucase_cl.16568
Server received 5 bytes from /tmp/ud_ucase_cl.16568

可以看到运行结果符合预期。

全文完,感谢阅读。文章来源地址https://www.toymoban.com/news/detail-476569.html

到了这里,关于Unix/Linux编程:UDS 数据报的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unix 网络编程:Socket 状态图&编程参数

        Flags (9 bits) (aka Control bits) . Contains 9 1-bit flags NS (1 bit): ECN-nonce - concealment protection (experimental: see RFC 3540). CWR (1 bit): Congestion Window Reduced (CWR) flag is set by the sending host to indicate that it received a TCP segment with the ECE flag set and had responded in congestion control mechanism (added to header by RFC 31

    2024年02月02日
    浏览(44)
  • 《UNUX环境高级编程》(1)UNIX基础

    操作系统 一种软件,控制计算机硬件资源,提供程序运行环境。操作系统包含了 内核 和一些其他软件(如 shell 、 公用函数库 、 应用程序 等)。例如Linux就是GNU操作系统的内核,因此也称为 GNU/Linux 操作系统。 系统调用 内核的接口 公用函数库 构建在系统调用之上 应用程

    2024年02月15日
    浏览(28)
  • UNIX网络编程:socket实现client/server通信

    阅读 UNIX网络编程 卷1:套接字联网API 第3版 的前4个章节,觉得有必要对书籍上的源码案例进行复现,并推敲TCP的C/S通信过程。 📌 测试环境:CentOS7.6 x64 编译server.c 和 client.c gcc server.c -g -std=gnu99 -o server 和 gcc client.c -g -std=gnu99 -o client 运行测试: 📌 server.c仅仅实现对单个客户

    2024年02月06日
    浏览(49)
  • UNIX网络编程卷一 学习笔记 第二十二章 高级UDP套接字编程

    TCP是一个字节流协议,又使用滑动窗口,因此没有记录边界或发送者数据发送能力超过接收者接收能力之类的事情,但对于UDP,每个输入操作对应一个UDP数据报(一个记录),因此当收取的数据报大于引用的输入缓冲区时就有问题。 UDP是不可靠协议,但有些应用确实有理由使

    2024年02月12日
    浏览(60)
  • UNIX网络编程卷一 学习笔记 第三十一章 流

    在大多数源自SVR 4的内核中,X/Open传输接口(X/Open Transport Interface,XTI,是独立于套接字API的另一个网络编程API)和网络协议通常就像终端IO系统那样也使用流系统(STREAMS system)实现。 我们将使用传输提供者接口(Transport Provider Interface,TPI)开发一个简单的TCP客户程序,TP

    2024年02月09日
    浏览(74)
  • Unix教程_编程入门自学教程_菜鸟教程-免费教程分享

    UNIX / LINUX教程 Unix / Linux - 入门 Unix / Linux - 文件管理 Unix / Linux - 目录管理 Unix / Linux - 文件权限/访问模式 Unix / Linux - 环境 Unix / Linux基本实用程序 - 打印,电子邮件 Unix / Linux - 管道和过滤器 Unix / Linux - 进程管理 Unix / Linux - 网络通信实用程序 Unix / Linux - vi编辑器教程 Shell Scri

    2024年02月03日
    浏览(60)
  • unix网络编程-简易服务器与客户端程序解析

    a -- address f -- file        eg: fputs() -- file put stream fd -- file descriptor h - host(主机) in/inet -- internet        eg: sockaddr_in; inet_aton n -- network(网络字节序)/numeric(数值) p -- protocol(协议)/presentation(表达/呈现形式) s -- socket        eg: sin -- socket internet t -- type,用于指定某种

    2024年01月16日
    浏览(69)
  • UNIX网络编程卷一 学习笔记 第二十七章 IP选项

    IPv4允许在20字节的首部固定部分后跟最多共40字节的选项。尽管已经定义了10种IPv4选项,但最常用的是源路径选项。我们可通过存取IP_OPTIONS套接字选项访问这些选项,我们存取该套接字选项时,所用的缓冲区中的值就是它们置于IP数据报中的格式。 IPv6允许在固定长度40字节的

    2024年02月14日
    浏览(54)
  • UNIX网络编程卷一 学习笔记 第二十八章 原始套接字

    原始套接字提供普通的TCP和UDP套接字不具备的以下3个能力: 1.有了原始套接字,进程可以读写ICMPv4、IGMPv4、ICMPv6等分组。例如,ping程序就使用原始套接字发送ICMP回射请求并接收ICMP回射应答。多播路由守护程序mrouted也使用原始套接字发送和接收IGMPv4分组。 这个能力还使得使

    2024年02月11日
    浏览(50)
  • 【UNIX 环境编程】GCC 编译器 | Makefile 基础入门 | GDB 调试教学

    💭 写在前面: 本文将介绍如何使用 GCC 编译器编译,并详细介绍了 Makefile 的基本构造、创建Makefile 文件以及 Makefile 变量,以提高编译效率。此外,本文还将探讨GDB调试器的使用,包括调试前的准备、readelf 读取 ELF 文件信息、显示代码、断点、调试、监视、跳转等内容。 

    2024年02月03日
    浏览(71)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包