前段时间写一个传递文件句柄的小 demo,有 server 端、有 client 端,之间通过 Unix Domain Socket 通讯。

在普通模式下,双方可以正常建立连接,当server端作为daemon启动时,则第一次启动成功,之后再启动, listen 会连接报 ENOTSUPP 错误,导致启动失败。

spipe.c

 int cli_conn(const char *name)
{
int fd, len, err, rval;
struct sockaddr_un un; if ((fd = socket (AF_UNIX, SOCK_STREAM, )) < ) {
printf ("create socket failed\n");
return -;
} printf ("create socket ok\n");
memset (&un, , sizeof (un));
un.sun_family = AF_UNIX;
strcpy (un.sun_path, name);
len = offsetof (struct sockaddr_un, sun_path) + strlen (name);
if (connect (fd, (struct sockaddr *)&un, len) < ) {
err = errno;
printf ("connect failed\n");
rval = -;
goto errout;
} printf ("connect to server ok\n");
return fd;
errout:
close (fd);
errno = err;
return rval;
} int serv_listen (const char *name)
{
int fd, len, err, rval;
struct sockaddr_un un; if ((fd = socket (AF_UNIX, SOCK_STREAM, )) < ) {
printf ("socket failed\n");
return -;
} printf ("create socket ok\n");
unlink (name);
memset (&un, , sizeof(un));
un.sun_family = AF_UNIX;
strcpy (un.sun_path, name);
len = offsetof (struct sockaddr_un, sun_path) + strlen (name); if (bind (fd, (struct sockaddr *)&un, len) < ) {
err = errno;
printf ("bind failed\n");
rval = -;
goto errout;
} printf ("bind socket to path ok\n");
if (listen (fd, QLEN) < ) {
err = errno;
printf ("listen failed, errno %d\n", errno);
rval = -;
goto errout;
} printf ("start listen on socket ok\n");
return fd;
errout:
close (fd);
errno = err;
return rval;
} int serv_accept (int listenfd, uid_t *uidptr)
{
int clifd, err, rval;
time_t staletime;
struct sockaddr_un un;
struct stat statbuf; size_t len = sizeof (un);
if ((clifd = accept (listenfd, (struct sockaddr *)&un, &len)) < ) {
printf ("accept failed\n");
return -;
} len -= offsetof (struct sockaddr_un, sun_path);
un.sun_path[len] = ;
printf ("accept %s ok\n", un.sun_path); unlink (un.sun_path);
return clifd; errout:
close (clifd);
errno = err;
return rval;
}

出错的位置在 serv_listen (line 57) 处,出错时的 server 端输出为:

Jan 17 00:24:44 localhost opend: create socket ok
Jan 17 00:24:44 localhost opend: bind socket to path ok
Jan 17 00:24:44 localhost opend: listen failed, errno 95
Jan 17 00:24:44 localhost opend: serv_listen error: Operation not supported

errno 95 为 ENOTSUPP。不以 daemon 运行时正常的输出如下:

create socket ok
bind socket to path ok
start listen on socket ok
accept ok
new connection: uid 0, fd 4

可能细心的读者会觉得,以 daemon 方式运行 printf 怎么还可以输出呢,是有以下宏定义做了处理:

 #ifdef USE_APUE
#include "../apue.h"
#define printf log_msg
#endif

以 daemon 运行时会定义 USE_APUE 宏,从而将 printf 重定义为 log_msg 输出到 syslog。

下面是 server 端的代码:

csopend2.c

 int main (int argc, char *argv[])
{
int c = ;
log_open ("open.serv", LOG_PID, LOG_USER); opterr = ; // don't want getopt() writting to stderr !
while ((c = getopt (argc, argv, "d")) != EOF) {
switch (c) {
case 'd':
debug = log_to_stderr = ;
break;
case '?':
err_quit ("unrecongnized option: -%c", optopt);
}
} if (debug == )
{
log_to_stderr = ;
daemonize ("opend");
} loop ();
return ;
}

不使用 -d 时表示 daemon 运行(与常识相反?),上面标黄的代码就是。

对应的 client 端代码:

csopenc.c

一开始怀疑是用于 listen 的本地 socket 文件已经存在,于是去 /tmp 目录看了下,果然有 opend 这个文件,删除之,再运行,不行;

然后怀疑是没有复用端口(?)所致,于是在 listen 之前添加了以下代码段:

     int opt = ;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(opt)) < ) {
err = errno;
printf ("setsockopt failed\n");
rval = -;
goto errout;
}

设置端口复用。编译、运行,输出如下:

Jan 17 00:43:11 localhost opend: create socket ok
Jan 17 00:43:11 localhost opend: bind socket to path ok
Jan 17 00:43:11 localhost opend: set socket option ok
Jan 17 00:43:11 localhost opend: listen failed, errno 95
Jan 17 00:43:11 localhost opend: serv_listen error: Operation not supported

设置成功了,但还是不行

难道 daemon 与普通进程使用 Unix 域套接字还有什么区别么?

暂时存疑……

[apue] 作为 daemon, 启动 Unix Domain Socket 侦听失败?的更多相关文章

  1. 由一个简单需求到Linux环境下的syslog、unix domain socket

    本文记录了因为一个简单的日志需求,继而对linux环境下syslog.rsyslog.unix domain socket的学习.本文关注使用层面,并不涉及rsyslog的实现原理,感兴趣的读者可以参 ...

  2. 问题解决:psql: could not connect to server: No such file or directory Is the server running locally and accepting connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?

    错误提示: psql: could not connect to server: No such file or directory Is the server running locally and ...

  3. Unix domain socket 简介

    Unix domain socket 又叫 IPC(inter-process communication 进程间通信) socket,用于实现同一主机上的进程间通信.socket 原本是为网络通讯设 ...

  4. linux一切皆文件之Unix domain socket描述符(二)

    一.知识准备 1.在linux中,一切皆为文件,所有不同种类的类型都被抽象成文件(比如:块设备,socket套接字,pipe队列) 2.操作这些不同的类型就像操作文件一样,比如增删改查等 3.主要用于 ...

  5. php, hhvm与odp & Unix domain Socket方式

    接上一篇,复习一下 启动php或hhvm: php/sbin/php-fpm start hhvm/bin/hhvm_control start 启动nginx或lighttpd: webserver ...

  6. 问题解决:psql: could not connect to server: No such file or directory Is the server running locally and accepting connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?

    错误提示: psql: could not connect to server: No such file or directory Is the server running locally and ...

  7. monitor a local unix domain socket like tcpdump

    Can I monitor a local unix domain socket like tcpdump? - Super User https://superuser.com/questions/ ...

  8. ndk学习16: unix domain socket

    一.UNIX Domain Socket 概念: UNIX Domain Socket是在socket架构上发展起来的用于同一台主机的进程间通讯(IPC) 特点: 1. 它不需要经过网络协议栈,不需要 ...

  9. Unix Domain Socket 域套接字实现

    主要注意流程: STREAM SOCKET: Server :  socket() --->  bind() ---> listen()  ---> accept() Client: ...

随机推荐

  1. Python--day47--mysql索引种类

  2. 《代码整洁之道 中文版》高清 PDF 电子书下载

    代码整洁之道.PDF 下载 代码整洁之道.PDF 中文版 高清 PDF  电子书下载 代码整洁之道下载  点我下载 作者简介  · · · · · · Robert C. Martin,Object ...

  3. SourceYard 制作源代码包

    本文带大家走进SourceYard开发之旅 在项目开发中,将一个大的项目拆为多个小项目解耦,减少模块之间的耦合.因为如果将代码放在一起,即使有团队的约束,但只要能写出的代码就会有小伙伴写出,很快就发现 ...

  4. Redis 命令行工具能这样用你知道了吗?

    我们天天都在使用 Redis 内置的命令行工具 redis-cli,久而久之以为它就是一个简单的交互式 Redis 数据结构手工操作程序,但是它背后强大的功能绝大多数同学可能闻所未闻.本节我们一起来挖 ...

  5. P1018 灵灵排数字

    题目描述 今天灵灵收到了n张卡片,他需要给他们从小到大排序. 输入格式 输入的第一行包含一个整数 \(n(1 \le n \le 10^5)\) . 输入的第二行包含 \(n\) 个正整数,以空格间隔 ...

  6. 28款GitHub最流行的开源机器学习项目,推荐GitHub上10 个开源深度学习框架

    20 个顶尖的 Python 机器学习开源项目 机器学习 2015-06-08 22:44:30 发布 您的评价: 0.0 收藏 1收藏 我们在Github上的贡献者和提交者之中检查了用Python语 ...

  7. centos虚拟机Ping不通网关

    centos虚拟机Ping不通网关 今天在VMware中安装了centos mini版本,安装完成后,用xshell连接一直连不上,本来以为是mini版本没有安装ssh server,于是就用命令: ...

  8. java.util.Date和jdk1.8新时间API比拼

    旧的时间和日期的API的缺陷 Java 的 java.util.Date 和 java.util.Calendar 类易用性差,不支持时区,而且都不是线程安全的. Date如果不格式化,打印出的日期可 ...

  9. 布尔&list与条件循环语句与trutle

    布尔值与空值 布尔值: 一个布尔值只有True.False两种值 空值: 是python里一个特殊的值,用None表示.None不能理解为0.因为0是有意义的,而None是一个特殊值. list(列表 ...

  10. Qt3升至Qt4需要注意的几件事项浅谈

    Qt3升至Qt4需要注意的几件事项浅谈 公司以前的项目是用Qt3写的,随着时间的推移慢慢显示出Qt3有多方面的限制,因此先公司决定用Qt4来改写这个项目,并为软件添加新功能,在此背景先编写此文章. 先 ...