linux本地socket通讯

本文提供了一个LINUX环境下使用AF_UNIX进行本地socket通讯的服务端与客户端示例代码。通过使用流SOCK_STREAM实现可靠的数据传输,示例展示了如何创建、连接及接受socket,并利用epoll进行事件监听。

LINUX本地socket通讯AF_UNIX地址族,服务端客户端通讯demo

AF_UNIX适用于本机进程间通讯,效率高,支持流SOCK_STREAM和数据报SOCK_DGRAM,其实都是面向可靠的链接
server端代码

#include <pthread.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <stddef.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <unistd.h>
#include <sys/epoll.h>


void SetNoBlock(int fd)
{
    int option = fcntl(fd, F_GETFD);
    if (option < 0) {
        return;
    }

    option = option | O_NONBLOCK | FD_CLOEXEC;
    option = fcntl(fd, F_SETFD, option);
    if (option < 0) {
        return;
    }
    return;
}

static int CreatePipeServerSocket_(const char *server, int maxClient)
{
    int listenfd = socket(PF_UNIX, SOCK_STREAM, 0);

    unlink(server);
    struct sockaddr_un serverAddr;
    int ret = 0;
    memset(&serverAddr, 0, sizeof(serverAddr));
    serverAddr.sun_family = AF_UNIX;
    strcpy(serverAddr.sun_path, server);
    uint32_t size = offsetof(struct sockaddr_un, sun_path) + strlen(server);
    ret = bind(listenfd, (struct sockaddr *)&serverAddr, size);
    SetNoBlock(listenfd);
    ret = listen(listenfd, maxClient);
    if (ret < 0) {
        printf("error");
    }
    printf("CreatePipeSocket listen fd: %d server:%s \n", listenfd, serverAddr.sun_path);
    return listenfd;
}

static int CreatePipeSocket_(const char *server)
{
    int fd = socket(PF_UNIX, SOCK_STREAM, 0);
    SetNoBlock(fd);

    struct sockaddr_un serverAddr;
    memset(&serverAddr, 0, sizeof(serverAddr));

    serverAddr.sun_family = AF_UNIX;
    strcpy(serverAddr.sun_path, server);

    uint32_t size = offsetof(struct sockaddr_un, sun_path) + strlen(serverAddr.sun_path);
    int ret = connect(fd, (struct sockaddr *)&serverAddr, size);

    printf("CreatePipeSocket connect fd: %d server: %s \n", fd, serverAddr.sun_path);
    return fd;
}

static int AcceptPipeSocket_(int serverFd)
{
    struct sockaddr_un clientAddr;
    socklen_t addrlen = sizeof(clientAddr);
    bzero(&clientAddr, addrlen);
    int fd = accept(serverFd, (struct sockaddr *)&clientAddr, &addrlen);
    printf("AcceptPipeSocket client fd %d %s \n", fd, clientAddr.sun_path);
    return fd;
}

void RunServer()
{
    int maxevents = 5;
    int epollFd = 0;
    epollFd = epoll_create(maxevents);
    if (epollFd == 0) {
        printf("error epollFd is 0\n");
    }
    if(access("/home/cc/test_socket",F_OK))
	{
		unlink("/home/cc/test_socket");//删除该文件	
	}
    int lfd = CreatePipeServerSocket_("/home/cc/test_socket", 10);
    struct epoll_event event = {};
    event.events = EPOLLIN;
    //绑定事件fd
    event.data.fd = lfd;
    if (lfd < 0) {
        printf("create pipe failed\n");
    }
    int ret = epoll_ctl(epollFd, EPOLL_CTL_ADD, lfd, &event);
    if (ret < 0) {
        printf("epoll_ctl failed\n");
    }
    struct epoll_event waitEvents[5] = {};

    while (1) {
        int number = epoll_wait(epollFd, waitEvents, 5, -1);
        for (int index = 0; index < number; index++) {
            if (waitEvents[index].events & EPOLLIN == EPOLLIN && waitEvents[index].data.fd == lfd) {
                int confd = AcceptPipeSocket_(lfd);
                struct epoll_event event = {};
                event.events = EPOLLIN;
                event.data.fd = confd;
                epoll_ctl(epollFd, EPOLL_CTL_ADD, confd, &event);
                continue;
            }
            if (waitEvents[index].events & EPOLLIN == EPOLLIN) {
                int rfd = waitEvents[index].data.fd;
                char buff[1024];
                recv(rfd, buff, 1024, 0);
                send(rfd, "hello", 6, 0);
            }
        }
    }
}

int main()
{
    RunServer();
    return 0;
}

客户端代码

#include <pthread.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <stddef.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <unistd.h>
#include <sys/epoll.h>

void SetNoBlock(int fd)
{
    int option = fcntl(fd, F_GETFD);
    if (option < 0) {
        return;
    }

    option = option | O_NONBLOCK | FD_CLOEXEC;
    option = fcntl(fd, F_SETFD, option);
    if (option < 0) {
        return;
    }
    return;
}

static int CreatePipeSocket_(const char *server)
{
    int fd = socket(PF_UNIX, SOCK_STREAM, 0);
    SetNoBlock(fd);

    struct sockaddr_un serverAddr;
    memset(&serverAddr, 0, sizeof(serverAddr));

    serverAddr.sun_family = AF_UNIX;
    strcpy(serverAddr.sun_path, server);

    uint32_t size = offsetof(struct sockaddr_un, sun_path) + strlen(serverAddr.sun_path);

    int ret = connect(fd, (struct sockaddr *)&serverAddr, size);
    if (ret != 0) {
        printf("connect failed\n");
    }
    printf("CreatePipeSocket connect fd: %d server: %s\n", fd, serverAddr.sun_path);
    return fd;
}


int main()
{
    int confd = CreatePipeSocket_("/home/cc/test_socket");
    char buf[1024];
    while (1)
    {
        sleep(1);
        printf("n\n");
        send(confd, "hello", 6, MSG_DONTWAIT);
        recv(confd, buf, 1024, 0);
        printf("%s\n",buf);
        buf[0] = 0;
    }
    return 0;
    
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值