linux 本地socket通信

来源:互联网 发布:怎么看淘宝登陆记录 编辑:程序博客网 时间:2024/05/15 00:32

linux 本地socket通信

在linux中的进程间通信,不仅仅有消息队列,共享内存,管道,等!
本地socket也是不错的机制,效率只比消息队列低一点。

#include <ctype.h>#include <dlfcn.h>#include <dirent.h>#include <errno.h>#include <fcntl.h>#include <inttypes.h>#include <pthread.h>#include <semaphore.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/socket.h>#include <sys/select.h>#include <sys/types.h>#include <sys/un.h>#include <sys/wait.h>#include <sys/mman.h>#define ALOGD printf#define ALOGE printf#define ALOGI printfint create_socket(const char *name) {    struct sockaddr_un addr;    int sockfd, ret;    sockfd = socket(PF_UNIX, SOCK_STREAM, 0);    if(sockfd < 0) {        ALOGD("Failed to open socket '%s': %s\n", name, strerror(errno));        return -1;    }    memset(&addr, 0, sizeof(addr));    addr.sun_family = AF_UNIX;    snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", name);    ret = unlink(addr.sun_path);    if(ret != 0 && errno != ENOENT) {        ALOGD("Failed to unlink old socket '%s': %s\n", name, strerror(errno));        close(sockfd);        return -1;    }    ret = bind(sockfd, (struct sockaddr *) &addr, sizeof(addr));    if(ret) {        ALOGD("Failed to bind socket '%s': %s\n", name, strerror(errno));        unlink(addr.sun_path);        close(sockfd);        return -1;    }    chmod(addr.sun_path, (mode_t) 0660);    ALOGD("Created socket %s with sockfd=%d\n", addr.sun_path, sockfd);    return sockfd;}/** * Connect to server, Never return if connect fail * @return Sock fd. */int connect_server(const char *path) {    struct sockaddr_un server;    socklen_t alen = 0;    int sock, ret = 0;    if(path == NULL)        return -1;    sock = socket(PF_UNIX, SOCK_STREAM, 0);    if(sock < 0) {        ALOGE("Failed to open socket '%s': %s\n", path, strerror(errno));        return -1;    }    /** Initialize address structure */    memset(&server, 0, sizeof(struct sockaddr_un));    /** Set address family to unix domain sockets */    server.sun_family = AF_UNIX;    /** Set address to the requested pathname */    snprintf(server.sun_path, sizeof(server.sun_path), "%s", path);    /** Get length of pathname */    alen = strlen(server.sun_path) + sizeof(server.sun_family);    while(1) {        ret = connect(sock, (struct sockaddr *) &server, alen);        if(ret == 0)            break;        sleep(1);    }    ALOGI("Connected to server socket '%s': sock=%d", path, sock);    return sock;}

通过create_socket的函数,建立本地socket节点。
例如:create_socket("/dev/socket/server_socket");
通过connect_server的函数,建立于服务节点的通信。
例如:connect_server("/dev/socket/server_socket");

static void *server_accepting_thread(void *) {    signal(SIGUSR1, signal_handler);    int client_fd;    struct sockaddr_un addr;    socklen_t addr_size = sizeof(addr);    int sockfd = create_socket(SOCKET);    if(sockfd < 0)        return NULL;    listen(sockfd, 8);    sem_post(&g_sem_accept_ready);    msg_t msg;    while(1) {        client_fd = -1;        memset(&msg, 0, sizeof(msg));        if((client_fd = accept(sockfd, (struct sockaddr *) &addr, &addr_size)) < 0) {            continue;        }        ALOGI("client_fd=%d connected\n", client_fd);        TEMP_FAILURE_RETRY(recv(client_fd, &msg, sizeof(msg), MSG_WAITALL));        ALOGI("client_fd=%d connected module is %s, msg is %s\n", client_fd, msg.module, msg.msg);        /*Set to module */        module_set_fd(msg.module, client_fd, msg.msg);    }    return NULL;

注意::
TEMP_FAILURE_RETRY(recv(client_fd, &msg, sizeof(msg), MSG_WAITALL));
它的功能: 不断地从套接口中接收客户端的“say_hello”数据直到成功为止。需要客户端实现。
保证通信正常。易于调试。
//使用MSG_WAITALL时,sockfd必须处于阻塞模式下,否则不起作用。
//所以MSG_WAITALL不能和MSG_NONBLOCK同时使用。
客户端可以通过recv接受数据

        if((recv_size = recv(sock, msg, sizeof(msg_t), MSG_WAITALL)) < 0) {            ALOGE("%s:Recv fail: %s, received size:%d\n", __FUNCTION__, strerror(errno), recv_size);            break;        }
0 0
原创粉丝点击