recvmsg和sendmsg的用法

/**********************************************************************************
函数原型: ssize_t recvmsg(int sockfd,struct msghdr* msg,int msg_flags);
ssize_t sendmsg(int sockfd,struct msghdr* msg,int msg_flags);
函数说明:向指定套接字读或写若干字节,包含信息封装在struct msghdr里
返回值:若成功,返回读或写的字节个数,若失败,返回-1
**********************************************************************************/
/*********************************************************************************
struct msghdr {
void* msg_name; //接收或发送的地址
int msg_namelen; //接收或发送的长度
struct iovec * msg_iov; //缓冲区
int msg_iovlen; //缓冲区个数
void * msg_control; //辅助数据(注:以后补充)
int msg_controllen //辅助数据大小
int msg_flags; //内核向进程传递的标志(函数中参数是进程1传递给内核的)
}
*********************************************************************************/

For Example:
服务端代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/wait.h>

#define BUFSIZE 4096
#define LISTENQ 100

void sig_child(int signo) {
    int ppid;
    while ((ppid = waitpid(-1,NULL,WNOHANG)) > 0) {
        printf("child process: %d terminated\n",ppid);
    }
}

void server_echo(int fd) {
    char recv[BUFSIZE];
    int n;
    struct msghdr rvmsg;
    struct iovec io;
    struct sockaddr_storage from;
    struct cmsghdr control;
    io.iov_base = recv;
    io.iov_len = BUFSIZE;
    rvmsg.msg_name = &from;
    rvmsg.msg_iov = &io;
    rvmsg.msg_iovlen = 1;
    rvmsg.msg_control = &control;
    rvmsg.msg_controllen = sizeof(struct cmsghdr);
    struct msghdr sdmsg;
    while ((n = recvmsg(fd,&rvmsg,0)) > 0) {
        sdmsg.msg_name = rvmsg.msg_name;
        sdmsg.msg_namelen = rvmsg.msg_namelen;
        sdmsg.msg_iov = &io;
        sdmsg.msg_iovlen = 1;
        sdmsg.msg_control = NULL;
        sdmsg.msg_controllen = 0;
        sdmsg.msg_flags = 0;
        io.iov_len = n;
        if (sendmsg(fd,&sdmsg,0) != n) {
            printf("send message to client failed: %s\n",strerror(errno));
            exit(1);
        }
        io.iov_len = BUFSIZE;
    }
}
int main(int argc,char** argv) {
    if (argc != 2) {
        printf("please check <service name or port>\n");
        exit(1);
    }

    struct addrinfo hints;
    bzero(&hints,sizeof(struct addrinfo));
    hints.ai_flags = AI_PASSIVE;
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    struct addrinfo* results;
    int err;
    if ((err = getaddrinfo(NULL,argv[1],&hints,&results)) != 0) {
        printf("getaddrinfo error: %s\n",gai_strerror(err));
        exit(1);
    }
    struct addrinfo* dummy = results;
    int sockfd;
    for (; dummy != NULL; dummy = dummy->ai_next) {
        if ((sockfd = socket(dummy->ai_family,dummy->ai_socktype,dummy->ai_protocol)) < 0) {
            continue;
        }
        if (bind(sockfd,dummy->ai_addr,dummy->ai_addrlen) == 0) {
            break;
        }
        close(sockfd);
    }
    if (dummy == NULL) {
        freeaddrinfo(results);
        printf("all failed\n");
        exit(1);
    }
    freeaddrinfo(results);
    if (listen(sockfd,LISTENQ) < 0) {
        printf("listen error: %s\n",strerror(errno));
        exit(1);
    }
    int connfd;
    int pid;
    if (signal(SIGCHLD,sig_child) == SIG_ERR) {
        printf("signal error: %s\n",strerror(errno));
        exit(1);
    }
    for (; ;) {
        if ((connfd = accept(sockfd,NULL,NULL)) < 0) {
            if (errno == EINTR) {
                continue;
            }else {
                printf("accept error: %s\n",strerror(errno));
                exit(1);
            }
        }
        if ((pid = fork()) < 0) {
            printf("fork error: %s\n",strerror(errno));
            exit(1);
        }else if (pid == 0) {
            close(sockfd);
            server_echo(connfd);
            close(connfd);
            exit(0);
        }
        close(connfd);
    }
    return 0;
}

客户端代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>



#define BUFSIZE 4096

void client_echo(int fd,struct sockaddr_storage* to,socklen_t tolen) {
    char send[BUFSIZE];
    int n;
    struct msghdr sdmsg,rvmsg;
    struct iovec io;
    io.iov_base = send;
    sdmsg.msg_name = to;
    sdmsg.msg_namelen = tolen;
    sdmsg.msg_iov = &io;
    sdmsg.msg_iovlen = 1;
    sdmsg.msg_control = NULL;
    sdmsg.msg_controllen = 0;
    sdmsg.msg_flags = 0;

    struct sockaddr_storage from;
    struct cmsghdr control;
    rvmsg.msg_name = &from;
    rvmsg.msg_control = &control;
    rvmsg.msg_controllen = sizeof(struct cmsghdr);
    rvmsg.msg_iov = &io;
    rvmsg.msg_iovlen = 1;
    rvmsg.msg_flags = 0;
    while ((n = read(STDIN_FILENO,send,BUFSIZE)) > 0) {
        io.iov_len = n;
        if (sendmsg(fd,&sdmsg,0) != n) {
            printf("send message to server error: %s\n",strerror(errno));
            exit(1);
        }
        io.iov_len = BUFSIZE;
        if ((n = recvmsg(fd,&rvmsg,0)) < 0) {
            printf("get from server fail: %s\n",strerror(errno));
            exit(1);
        }
        if (write(STDOUT_FILENO,send,n) != n) {
            printf("write error: %s\n",strerror(errno));
            exit(1);
        }
    }
}

int main(int argc,char** argv) {
    if (argc != 3) {
        printf("please check <ip address or host name> <service name or host name>\n");
        exit(1);
    }

    struct addrinfo hints;
    bzero(&hints,sizeof(struct addrinfo));

    hints.ai_flags = AI_ALL;
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    struct addrinfo* results;
    int err;
    if ((err = getaddrinfo(argv[1],argv[2],&hints,&results)) != 0) {
        printf("getaddrinfo error: %s\n",gai_strerror(errno));
        exit(1);
    }

    struct addrinfo* dummy = results;
    int sockfd;
    for (; dummy != NULL; dummy = dummy->ai_next) {
        if ((sockfd = socket(dummy->ai_family,dummy->ai_socktype,dummy->ai_protocol)) < 0) {
            continue;
        }
        if (connect(sockfd,dummy->ai_addr,dummy->ai_addrlen) == 0) {
            break;
        }
        close(sockfd);
    }

    if (dummy == NULL) {
        freeaddrinfo(results);
        printf("all connect failed\n");
        exit(1);
    }
    client_echo(sockfd,(struct sockaddr_storage*)dummy->ai_addr,dummy->ai_addrlen);
    freeaddrinfo(results);
    return 0;
}
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值