监听socket被子进程继承导致的通信问题

来源:互联网 发布:vb.net excel教程 编辑:程序博客网 时间:2024/05/01 16:10

如果socket仅仅是针对connection,例如是accept出来的,那问题不大
例如ftp<子进程模式>,父进程关闭此socket,子进程完全接管这个socket负责与客户端进行通信。

本文主要讨论监听socket被子进程继承导致的通信问题

如果socket属于UNIX Domain Socket族类型,例如:

    int fd, size;    struct sockaddr_un un;    memset(&un, 0, sizeof(un));    un.sun_family = AF_UNIX;    strcpy(un.sun_path, "foo.socket");    if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {        perror("socket error");        exit(1);    }

问题也不大,不会影响父进程accept客户进程,不会影响通信

其他情况,socket按照网络通信(包括本机lo通信),无论tcp/udp,由于父子两个进程同时在listen相同的socket资源,竞争导致父进程无法与客户端正常通信。
例如:

def server():    try:        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)        sock.bind(('0.0.0.0', 8888))        while True:            conn, addr = sock.accept()            t = threading.Thread(target=start_child, args=(conn, addr))            t.start()        sock.close()............def start_child(conn, addr):    cmd="sh child_test 1>/dev/null 2>&1 null"    try:        proc = subprocess.Popen(cmd, shell = True, stdout = subprocess.PIPE)        return proc.communicate()[0]    except Exception, e:        print("Execute failed, command: %s, error: %s" %(cmd, str(e)))    conn.send("finished")   #此处不会发生阻塞,但是报文不知道跑到哪里去了............

可以通过netstat -lnp|grep 8888或者lsof|grep -E 8888.*LISTEN来确认父子进程监听了同一个ip:port,发生了竞争关系

对于python来说,subprocess.Popen提供了一个简单的方法来解决这类问题,增加参数close_fds=True即可
close_fds:
unix 下执行新进程前是否关闭0/1/2之外的文件
windows下不继承还是继承父进程的文件描述符|

对于c c++而言,同样关闭0/1/2之外的文件描述符
通过对/proc/pid/fd的文件操作,获取fd list,关闭其中0/1/2之外的所有文件标识符

0 0
原创粉丝点击