在写计算机网络课设的时候,需要用socket写一个多线程的服务器,直接用fork写成了多进程。起初运行的时候觉得没什么问题,抓包看了一下发现,客户端和服务器之间的socket并没有关闭。
从上图可以看出,只有两次挥手单向的关闭。
经过查找资料,发现是多进程时内存复制,对socket文件产生了第二次的引用,必须关闭所有的引用才能触发socket关闭。
Socket *clientSock = ss.sAccept(); pid = fork(); if (!pid) { time_t serverTime = time(0); char str[4]; memcpy(str, &serverTime, sizeof(time_t)); clientSock->sendTo(str); clientSock->sClose(); break; } else{ clientSock->sClose(); }
在主进程和子进程中都关闭socket后,后,可以看到抓包结果中,完成了四次挥手,socket成功关闭
那么问题就来了,在这个例子中,子进程中的指针应该是指向主进程Socket对象的,所以子进程和主进程中的关闭都是对主进程中Socket进行关闭,而且必须关闭两次才能将sock文件的引用全部关闭,也就是说,子进程创建后,相同地址的Socket对文件描述符产生了两次引用。这个问题应该是多进程内存复制机制的问题,内存并不是完全照搬的复制,而是根据指针对堆内存中对象的引用情况进行复制,这点还没有搞清楚其中的原理机制,等待之后再补充。