ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

域套接字-多客户端实现

2021-03-21 12:30:51  阅读:239  来源: 互联网

标签:域套 dbg int printf sockfd 接字 include servaddr 客户端


域套接字-多客户端实现

我们在linux 应用开发中,如果需要实现进程间通信的多客户端接口,就需要引入select 和epoll 相关机制了,本文介绍下epoll的功能的实现。
多客户端使用场景,比如我们需要开发一个库接口,提供给客户调用,那么使用域套接字实现进程间通信,就必须在service端引入多路复用,否则库功能就只能被一个进程使用了。

代码实现:

service端
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<unistd.h>
#include<string.h>
#include<sys/un.h>
#include<sys/epoll.h>

#define dbg_printf(...) printf("[%s.%d]",__func__,__LINE__);printf(__VA_ARGS__)
#define UNIX_SOCKET_FILE  "/home/linux/test/socket/temp.file"


static int sockfd = 0;
static struct sockaddr_un servaddr,cliaddr;


int main(int argc, const char *argv[])
{

        int ret = 0;
        int connfd = 0;

        sockfd = socket(AF_UNIX,SOCK_STREAM,0);
        if(sockfd < 0 )
        {
                dbg_printf("socket error \n");
                return -1;
        }

        if(access(UNIX_SOCKET_FILE,F_OK) == 0)
        {
                dbg_printf("remove unix socket file \n");
                remove(UNIX_SOCKET_FILE);
        }

        memset(&servaddr,0,sizeof(servaddr));
        servaddr.sun_family = AF_UNIX;
        strcpy(servaddr.sun_path,UNIX_SOCKET_FILE);

        if(0 != bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr)))
        {
                dbg_printf("bind fail \n");
                close(sockfd);
                return -1;
        }

        if(0 != listen(sockfd,10))
        {
                dbg_printf("linsten fail \n");
                close(sockfd);
                return -1;
        }


        int clilen = sizeof(cliaddr.sun_family)+strlen(cliaddr.sun_path);
/*
        if((connfd = accept(sockfd,(struct sockaddr *)&cliaddr,(socklen_t *)&clilen)) == -1)
        {
                dbg_printf("accept fail \n");
                return -1;
        }
        dbg_printf("accept success connfd = %d \n",connfd);

*/
        char recvbuf[64];
        int n = 0;

        int epfd;
        epfd = epoll_create(100);

        struct epoll_event ev;

        ev.events= EPOLLIN;
        ev.data.fd = sockfd;
        //将sockfd 添加到 监控事件的表中
        epoll_ctl(epfd,EPOLL_CTL_ADD,sockfd,&ev);

        int datafd = 0;

        int i = 0;
        struct epoll_event evrdy[100];

        while(1)
        {
                ret = epoll_wait(epfd,evrdy,100,-1);
                dbg_printf("ret = %d ",ret);

                for(i = 0;i < ret; i++)
                {
                        if(evrdy[i].data.fd == sockfd) //建立连接的文件描述符
                        {
                                dbg_printf("build new connect \n");
                                datafd = accept(sockfd,(struct sockaddr *)&cliaddr,&clilen);

                                ev.events = EPOLLIN;
                                ev.data.fd = datafd;
                                //将sockfd 添加到 监控事件的表中
                                epoll_ctl(epfd,EPOLL_CTL_ADD,datafd,&ev);
                        }
                        else  //进程间通信描述符
                        {
                                dbg_printf("recv data \n");
                                memset(recvbuf,0,sizeof(recvbuf));
                                n = recv(evrdy[i].data.fd,recvbuf,sizeof(recvbuf),0);
                                if(n == -1)
                                {
                                        dbg_printf("recv error \n");
                                }
                                else if(n == 0)
                                {
                                        epoll_ctl(epfd,EPOLL_CTL_DEL,evrdy[i].data.fd,NULL);
                                        close(evrdy[i].data.fd);
                                        dbg_printf("client exit \n");
                                }
                                else if(n > 0)
                                {
                                        printf("service recvbuf is %s \n",recvbuf);

                                        send(evrdy[i].data.fd,"ok",strlen("ok"),0);
                                }
                        }
                }
        }

        close(sockfd);

        return 0;
}

client端

#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<unistd.h>
#include<string.h>
#include<sys/un.h>

#define dbg_printf(...) printf("[%s.%d]",__func__,__LINE__);printf(__VA_ARGS__)
#define UNIX_SOCKET_FILE  "/home/linux/test/socket/temp.file"


static int sockfd = 0;
static struct sockaddr_un servaddr,cliaddr;


int main(int argc, const char *argv[])
{

        int ret = 0;
        int connfd = 0;

        sockfd = socket(AF_UNIX,SOCK_STREAM,0);
        if(sockfd < 0 )
        {
                dbg_printf("socket error \n");
                return -1;
        }

        memset(&servaddr,0,sizeof(servaddr));
        servaddr.sun_family = AF_UNIX;
        strcpy(servaddr.sun_path,UNIX_SOCKET_FILE);


        int serlen = sizeof(servaddr.sun_family)+strlen(servaddr.sun_path);
        if(connect(sockfd,(struct sockaddr *)&servaddr,serlen) == -1)
        {
                dbg_printf("connect fail \n");
                close(sockfd);
                return -1;
        }

        dbg_printf("conect success \n");

        char recvbuf[64];
        char sendbuf[64];

        while(1)
        {
                memset(recvbuf,0,sizeof(recvbuf));
                memset(sendbuf,0,sizeof(sendbuf));

                strcpy(sendbuf,"i love you");

                send(sockfd,sendbuf,strlen(sendbuf),0);

                recv(sockfd,recvbuf,sizeof(recvbuf),0);

                dbg_printf("recv is %s \n",recvbuf);

                sleep(5);

        }

        close(sockfd);

        return 0;
}

实例测试:

编译上面文件为service 和client
client 我修改 发送内容 hello world 和 i love you ,编译生成client1 和client2,客户端与service通信, 测试如下
在这里插入图片描述

标签:域套,dbg,int,printf,sockfd,接字,include,servaddr,客户端
来源: https://blog.csdn.net/qq_38240926/article/details/115047103

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有