UNIX 域流式套接字

简介: UNIX 域流式套接字

提示

官方并没有给出这个使用的示例,本示例是基于源码分析并根据 tcp echo server 来改写的。


环境准备

在编译的时候要开启 uds 选项:

$ ./configure --enable-uds
$ make && sudo make install点击复制复制失败已复制


回环测试代码

建立server.c文件,写入如下内容:

#include "hv/hloop.h"
#include "hv/hsocket.h"
#define errlog(errmsg)                                                \
    do {                                                              \
        perror(errmsg);                                               \
        printf("--%s--%s--%d--\n", __FILE__, __FUNCTION__, __LINE__); \
        return -1;                                                    \
    } while (0)
static void on_close(hio_t *io) {
    printf("on_close fd=%d error=%d\n", hio_fd(io), hio_error(io));
}
static void on_recv(hio_t *io, void *buf, int readbytes) {
    printf("on_recv fd=%d readbytes=%d\n", hio_fd(io), readbytes);
    char localaddrstr[SOCKADDR_STRLEN] = {0};
    char peeraddrstr[SOCKADDR_STRLEN] = {0};
    printf("[%s] <=> [%s]\n",
           SOCKADDR_STR(hio_localaddr(io), localaddrstr),
           SOCKADDR_STR(hio_peeraddr(io), peeraddrstr));
    printf("< %.*s", readbytes, (char *)buf);
    // echo
    printf("> %.*s", readbytes, (char *)buf);
    hio_write(io, buf, readbytes);
}
static void on_accept(hio_t *io) {
    printf("on_accept connfd=%d\n", hio_fd(io));
    char localaddrstr[SOCKADDR_STRLEN] = {0};
    char peeraddrstr[SOCKADDR_STRLEN] = {0};
    printf("accept connfd=%d [%s] <= [%s]\n", hio_fd(io),
           SOCKADDR_STR(hio_localaddr(io), localaddrstr),
           SOCKADDR_STR(hio_peeraddr(io), peeraddrstr));
    hio_setcb_close(io, on_close);
    hio_setcb_read(io, on_recv);
    hio_read_start(io);
}
int main(int argc, char *argv[]) {
    hloop_t *loop = hloop_new(0);
    hio_t *listenio = hio_create_socket(loop, argv[1], -1, HIO_TYPE_SOCK_STREAM, HIO_SERVER_SIDE);
    if (listenio == NULL) {
        errlog("create io error");
        return -1;
    };
    hio_setcb_accept(listenio, on_accept);
    if (hio_accept(listenio) != 0) {
        errlog("bind callback error");
        return -1;
    }
    printf("listenfd=%d\n", hio_fd(listenio));
    hloop_run(loop);
    hloop_free(&loop);
    return 0;
}点击复制复制失败已复制


编译并运行:

$ gcc server.c -o server -lhv && ./server socket点击复制复制失败已复制


提示

其中 socket 参数为套接字文件路径。


测试客户端:client.c

#include <stdio.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/un.h>
#define N 128
#define errlog(errmsg)                                                \
    do {                                                              \
        perror(errmsg);                                               \
        printf("--%s--%s--%d--\n", __FILE__, __FUNCTION__, __LINE__); \
        return -1;                                                    \
    } while (0)
int main(int argc, const char *argv[]) {
    int sockfd;
    struct sockaddr_un serveraddr;
    socklen_t addrlen = sizeof(serveraddr);
    char buf[N] = {};
    // Step1. 创建套接字
    if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
        errlog("fail to socket");
    }
    // Step2. 填充服务器本地信息结构体
    serveraddr.sun_family = AF_UNIX;
    strcpy(serveraddr.sun_path, argv[1]);
    // Step3. 发送客户端请求
    if (connect(sockfd, (struct sockaddr *)&serveraddr, addrlen) < 0) {
        errlog("fail to connect");
    }
    while (1) {
        fgets(buf, N, stdin);
        buf[strlen(buf) - 1] = '\0';
        if (send(sockfd, buf, N, 0) < 0) {
            errlog("fail to send");
        }
        if (strncmp(buf, "quit", 4) == 0) {
            printf("client is quired\n");
            break;
        } else {
            if (recv(sockfd, buf, N, 0) < 0) {
                errlog("fail to recv");
            }
            printf("server: %s\n", buf);
        }
    }
    close(sockfd);
    return 0;
}点击复制复制失败已复制


客户端使用:

$ gcc client.c -o client && ./client socket点击复制复制失败已复制


演示示例:

演示.gif


提示

上面演示中的 server 部分打印会有数据慢一拍的感觉,即下一包数据来了,上一包数据才会在终端打印出来,这时因为缓存的问题,加上 \n 就没有这个问题了,可以看一下之前的笔记:缓存区的类型缓存区的刷新及配置

目录
相关文章
|
Unix Linux
Linux本地套接字(Unix域套接字)----SOCK_DGRAM方式
这里介绍一下Linux进程间通信的socket方式---Local socket。这篇主要是介绍下SOCK_DGRAM方式的通信,即数据包的方式(与UDP类似),面向无连接。
310 0
|
Unix
UNIX 域数据报套接字
UNIX 域数据报套接字
125 0
UNIX 域数据报套接字
|
网络协议 Unix
UNIX 域流式套接字
UNIX 域流式套接字
166 0
UNIX 域流式套接字
|
网络协议 Unix
UNIX 域套接字概述
UNIX 域套接字概述
165 0
|
Unix 网络协议
UNIX域协议(无名套接字)
关于什么是UNIX域套接字可以参考:http://www.cnblogs.com/xcywt/p/8185597.html这里主要介绍非命名的UNIX域套接字的用法。1.socketpair函数先看man手册: SYNOPSIS       #include           /* See ...
1271 0
|
网络协议 Unix C语言
UNIX域协议(命名套接字)
这里主要介绍命名UNIX域套接字 1.什么是UNIX域套接字Unix域协议并不是一个实际的协议族,而是在单个主机上执行客户/服务通信的一种方式。是进程间通信(IPC)的一种方式。它提供了两类套接字:字节流套接字(有点像TCP)和数据报套接字(有点像UDP)UNIX域数据报服务是可靠的,不会丢失消息,也不会传递出错。
1240 0
|
网络协议 Unix API
《UNIX网络编程 卷1:套接字联网API(第3版)》——导读
本书想达到的目标是向大家提供网络编程指导。这些内容不仅适用于专业人士,也适用于初学者;不仅适用于维护已有代码,也适用于开发新的网络应用程序;此外,还适用于那些只是想了解一下自己系统中网络组件的工作原理的人。
1479 0
|
网络协议 Unix API
《UNIX网络编程 卷1:套接字联网API(第3版)》——8.16 小结
UDP套接字可能产生异步错误,它们是在分组发送完一段时间后才报告的错误。TCP套接字总是给应用进程报告这些错误,但是UDP套接字必须已连接才能接收这些错误。
1496 0