`
memorymyann
  • 浏览: 271963 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

17.I/O函数recvmsg与sendmsg

阅读更多

想对于之前的几个IO函数,recvmsg与sendmsg功能更为强大,当然用起来也更为复杂。

#include "sys/socket.h"

 

ssize_t recvmsg(int sockfd,  struct msghdr * msg, int flags);

ssize_t sendmsg(int sockfd,  struct msghdr * msg, int flags);

成功时候返回读写字节数,出错时候返回-1.

 

这2个函数只用于套接口,不能用于普通的I/O读写,参数sockfd则是指明要读写的套接口。

flags用于传入控制信息,一般包括以下几个

MSG_DONTROUTE             send可用

MSG_DONWAIT                 send与recv都可用

MSG_PEEK                        recv可用

MSG_WAITALL                   recv可用

MSG_OOB                         send可用

MSG_EOR                          send recv可用

 

返回信息都记录在struct msghdr * msg中。

struct msghdr {

       void * msg_name;//协议地址和套接口信息,在非连接的UDP中,发送者要指定对方地址端口,接受方用于的到数据来源,如果不需要的话可以设置为NULL(在TCP或者连接的UDP中,一般设置为NULL)。

        socklen_t msg_namelen;//上面的长度

        struct lovec * msg_lov;

        ssize_t msg_lovlen;//和readv和writev一样

        void * msg_control;

        socklen_t msg_controllen;

        int msg_flags; //用于返回之前flags的控制信息

}

 

样例1,在TCP中使用 sendmsg与recvmsg

 

服务器

......

#define MAXSIZE 100

int main(int argc, char ** argu) {
        .......

        struct msghdr msg;//初始化struct msghdr
        msg.msg_name = NULL; //在tcp中,可以设置为NULL
        struct iovec io;//初始化返回数据
        io.iov_base = buf; //只用了一个缓冲区
        io.iov_len = MAXSIZE; //定义返回数据长度
        msg.msg_iov = &io;
        msg.msg_iovlen = 1;//只用了一个缓冲区,所以长度为1

        ...................
        ssize_t recv_size = recvmsg(connfd, &msg, 0);
        char * temp = msg.msg_iov[0].iov_base;//获取得到的数据
        temp[recv_size] = '\0';//为数据末尾添加结束符
        printf("get message:%s", temp);
        ..........................
}

 

客户端

..................

#define MAXSIZE 100

int main(int argc, char ** argv) {
        .................
        struct msghdr msg;//初始化发送信息
        msg.msg_name = NULL;
        struct iovec io;
        io.iov_base = send_buff;
        io.iov_len = sizeof(send_buff);
        msg.msg_iov = &io;
        msg.msg_iovlen = 1;

        if(argc != 2) {
                printf("please input port");
                exit(1);
        }
        ............
        ssize_t size = sendmsg(sockfd, &msg, 0);
        close(sockfd);
        exit(0);
}

 

这里控制信息都设置成0,主要是初始化返回信息struct msghdr结构。关于struct iovec这个数据结构,上一篇readv与writev有介绍。

 

未连接的UDP套接口

服务器

#include "/programe/net/head.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include "sys/wait.h"
#include "sys/select.h"
#include "sys/poll.h"

#define MAXSIZE 100

int main(int argc, char ** argv) {
        int sockfd;
        struct sockaddr_in serv_socket;
        struct sockaddr_in  * client_socket = (struct sockaddr_in *) malloc (sizeof(struct sockaddr_in));
        char buf[MAXSIZE + 1];

        sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        bzero(&serv_socket, sizeof(serv_socket));
        serv_socket.sin_family = AF_INET;
        serv_socket.sin_addr.s_addr = htonl(INADDR_ANY);
        serv_socket.sin_port = htons(atoi(argv[1]));
        bind(sockfd, (struct sockaddr *)&serv_socket, sizeof(serv_socket));

        struct msghdr msg;
        msg.msg_name = client_socket;

        //如果想得到对方的地址和端口,一定要把初始化完毕的内存头指针放入msg之中
        msg.msg_namelen = sizeof(struct sockaddr_in);//长度也要指定
        struct iovec io;
        io.iov_base = buf;
        io.iov_len = MAXSIZE;
        msg.msg_iov = &io;
        msg.msg_iovlen = 1;

        ssize_t len = recvmsg(sockfd, &msg, 0);
        client_socket = (struct sockaddr_in *)msg.msg_name;
        char ip[16];
        inet_ntop(AF_INET, &(client_socket->sin_addr), ip, sizeof(ip));
        int port = ntohs(client_socket->sin_port);
        char * temp = msg.msg_iov[0].iov_base;
        temp[len] = '\0';
        printf("get message from %s[%d]: %s\n", ip, port, temp);
        close(sockfd);
}

 

客户端

#include "/programe/net/head.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "sys/select.h"

#define MAXSIZE 100

int main(int argc, char ** argv) {
        int sockfd;
        struct sockaddr_in serv_socket;
        int maxfdpl;
        char send[] = "hello yuna";
        if(argc != 2) {
                printf("please input port");
                exit(1);
        }

        sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        bzero(&serv_socket, sizeof(serv_socket));
        serv_socket.sin_family = AF_INET;
        serv_socket.sin_port = htons(atoi(argv[1]));
        inet_pton(AF_INET, "192.168.1.235", &serv_socket.sin_addr);

        struct msghdr msg;
        msg.msg_name = &serv_socket;
        msg.msg_namelen = sizeof(struct sockaddr_in);
        struct iovec io;
        io.iov_base = send;
        io.iov_len = sizeof(send);
        msg.msg_iov = &io;
        msg.msg_iovlen = 1;

        ssize_t send_size = sendmsg(sockfd, &msg, 0);
        close(sockfd);
        exit(0);
}

分享到:
评论

相关推荐

    unix平台下I/O聚集和分离的一种方案

    在Unix操作系统环境中,I/O(Input/Output)操作是程序与外部设备交互的关键途径,包括读取数据、写入数据以及控制硬件设备等。在处理多个文件或套接字时,I/O聚集和分离是优化性能和管理资源的重要手段。本篇文章将...

    iozone.txt

    内核文件I/O->标准库I/O->高级I/O->IPC中 1. read()/write(); 2. pread()/pwrite(); 3. getc()/putc(); 4. fgetc()/fputc(); 5. getchar()/putchar(); 6. ferror()/feof(); 7. fgets()/fputs(); 8. ...

    linux_net.pdf

    两台主机建立udp通信所走过的函数列表: | sys_read fs/read_write.c | sock_read net/socket.c | sock_recvmsg net/socket.c | inet_recvmsg net/ipv4/af_inet.c | udp_recvmsg net/ipv4/udp.c | skb_recv_datagram...

    tcpip详解2_16

    它们负责处理插座层与协议层之间的I/O操作,包括流控制和错误处理,由于需要处理多种协议,因此这两个函数通常非常复杂。 本章还提到了几个关键的头文件和C源文件,如`sys/socket.h`、`sys/socketvar.h`、`sys/uio....

    TCPIP协议详解卷2:实现

    参加本书翻译的有:谢钧(序言和第1章~第7章),蒋慧(第8章~第14章,第22章~第23章),吴礼发(第15~第17章),端义峰(第18章~第19章),胥光辉(第20章~第21章)和陆雪莹(第24章~第32章以及全部附录)。全书由谢希仁教授审校...

    linux tcpip协议栈.doc

    3. 调用`sock_recvmsg`和`sock_sendmsg`进一步处理socket消息,这两函数在`net/socket.c`中定义。 4. `inet_recvmsg`和`inet_sendmsg`分别在`net/ipv4/af_inet.c`中处理IPv4相关的接收和发送。 5. `udp_recvmsg`和`...

    linux programming instances网络编程教程 附源代码

    11.4 recvmsg和sendmsg函数 11.5 辅助数据 11.6 本章小结 第12章 多线程编程及网络应用 12.1 基本概念 12.1.1 引入多线程的原因 12.1.2 线程的基本概念 12.1.3 线程的分类 12.2 线程基础 12.2.1 线程的...

    unix 域 socket服务端客户端stream方式代码

    在Unix域Socket的stream方式下,`recvmsg`和`sendmsg`函数可以实现更复杂的I/O操作,它们相比于常规的`recv`和`send`函数提供了更多的灵活性。 1. `recvmsg`函数: - `recvmsg`不仅可以接收数据,还可以获取关于...

    linux 网络数据流程

    3. tcp_v4_recvmsg函数从socket队列中提取数据包并处理,最终通过sys_read或sys_recvmsg系统调用将数据传给用户空间。 对于UDP协议,处理流程如下: 1. udp_rcv函数接收UDP数据包,并调用udp_v4_recvmsg函数。 2. ...

    unix 网络编程 源代码

    5. **套接字选项与控制消息**:讨论了如何使用getsockopt和setsockopt函数设置和获取套接字选项,以及使用recvmsg和sendmsg处理套接字控制消息。 6. **多路复用I/O**:讲解了select、poll和epoll等多路复用I/O模型...

    linux-TcpIP协议栈源码阅读笔记.pdf

    这一层是应用程序与网络通信的接口,提供了一套标准API,如socket、bind、listen、connect、accept、send、recv等。在内核中,每个socket用`struct socket`结构体表示。相关的代码主要位于`/net/socket.c`和`/...

    Linux进程间传递文件描术符事例代码

    然后,通过某种IPC机制(如`sendmsg()`、`recvmsg()`或`fork()`+`dup2()`)将一个文件描述符发送到另一个进程。`processB.c`可能包含以下关键代码片段: ```c #include <sys/socket.h> #include <unistd.h> int ...

    unix网络编程1

    7. **非阻塞I/O与异步通知**:探讨如何使用非阻塞I/O模式,以及利用信号驱动I/O和异步通知模型来优化网络程序的性能。 8. **套接字地址转换**:介绍`gethostbyname()`和`getaddrinfo()`等函数,用于进行主机名到IP...

    UNIX网络编程 第三版

    7. **套接字选项和控制消息**:如setsockopt()和getsockopt()函数用于设置和获取套接字的选项,而recvmsg()和sendmsg()可以处理控制消息,提供更复杂的通信能力。 8. **网络安全与加密**:网络编程中安全问题不容...

    TCP-IP详解卷2:实现.part1

    第16章 插口I/O 381 16.1 引言 381 16.2 代码介绍 381 16.3 插口缓存 381 16.4 write、writev、sendto和sendmsg 系统调用 384 16.5 sendmsg系统调用 387 16.6 sendit函数 388 16.6.1 uiomove函数 389 16.6.2 举例 ...

    TCP-IP详解卷2:实现.part2

    第16章 插口I/O 381 16.1 引言 381 16.2 代码介绍 381 16.3 插口缓存 381 16.4 write、writev、sendto和sendmsg 系统调用 384 16.5 sendmsg系统调用 387 16.6 sendit函数 388 16.6.1 uiomove函数 389 16.6.2 举例 ...

    TCPIP详解卷[1].part06

    2.4 SLIP:串行线路IP 17 2.5 压缩的SLIP 18 2.6 PPP:点对点协议 18 2.7 环回接口 20 2.8 最大传输单元MTU 21 2.9 路径MTU 21 2.10 串行线路吞吐量计算 21 2.11 小结 22 第3章 IP:网际协议 24 3.1 引言 24 3.2 IP...

    Linux 4.4.0内核源码分析TCP实现

    1. tcp_sendmsg 函数:tcp_sendmsg 函数是用户层 TCP 的主要函数之一,它将用户进程的数据传输需求转换为内核可以理解的形式。 2. tcp_recvmsg 函数:tcp_recvmsg 函数是用户层 TCP 的主要函数之一,它将内核的响应...

Global site tag (gtag.js) - Google Analytics