提示
官方并没有给出这个使用的示例,本示例是基于源码分析并根据 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点击复制复制失败已复制
演示示例:
提示
上面演示中的 server
部分打印会有数据慢一拍的感觉,即下一包数据来了,上一包数据才会在终端打印出来,这时因为缓存的问题,加上 \n
就没有这个问题了,可以看一下之前的笔记:缓存区的类型和缓存区的刷新及配置