关于网络编程中通讯socket的数量控制

slwj 2019-06-12 11:34:13
各位好,阅读一个例程时遇到点疑惑,服务器和客户端的代码分别如下,搞不懂为何在服务器程序中,当子进程退出时,在子进程和父进程都要调用
close(iConnSocket);

将用于通信的socket计数减1

多谢各位!

源代码如下:


void sigChildFun(int sigNO)
{
pid_t pid;
int stat;
while((pid = waitpid(-1, &stat, WNOHANG)) > 0)
{
NULL;
}

return;
}

int main()
{
sockaddr_in servAddr;
memset(&servAddr,0,sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = INADDR_ANY;
servAddr.sin_port = htons(8765);

int iListenSocket = socket(AF_INET, SOCK_STREAM, 0);
bind(iListenSocket, (sockaddr *)&servAddr, sizeof(servAddr));
listen(iListenSocket,5);

signal(SIGCHLD, sigChildFun);

while(1)
{
sockaddr_in clientAddr;
socklen_t iSize = sizeof(clientAddr);
memset(&clientAddr, 0, sizeof(clientAddr));

int iConnSocket = accept(iListenSocket,(sockaddr*)&clientAddr, &iSize);
if(iConnSocket < 0)
{
if(errno == EINTR || errno == ECONNABORTED)
{
continue;
}
else
{
printf("accept error, server\n");
return -1;
}
}

int tmpPid = fork();
if(tmpPid == 0)
{
close(iListenSocket); // 子进程让监听socket的计数减1, 并非直接关闭监听socket

char szBuf[1024] = {0};
snprintf(szBuf, sizeof(szBuf), "server pid[%u], client ip[%s]", getpid(), inet_ntoa(clientAddr.sin_addr));
write(iConnSocket, szBuf, strlen(szBuf) + 1);

while(1)
{
if(read(iConnSocket, szBuf, 1) <= 0)
{
close(iConnSocket); // 子进程让通信的socket计数减1
return -2; // 子进程退出
}
}

close(iConnSocket); // 子进程让通信的socket计数减1
return 0; // 子进程退出
}

close(iConnSocket); // 不知道为何,父进程再次让通信的socket计数减1,之前子进程已经调用过了
}

getchar();
close(iListenSocket); // 父进程让监听socket计数减1, 此时会关掉监听socket(因为之前子进程已经有此操作)
return 0;
}


客户端程序为:

int main()
{
int sockClient = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addrSrv;
addrSrv.sin_addr.s_addr = inet_addr("10.100.70.140");
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(8765);
connect(sockClient, ( const struct sockaddr *)&addrSrv, sizeof(struct sockaddr_in));

char szBuf[2048] = {0};
int iRet = recv(sockClient, szBuf, sizeof(szBuf) - 1 , 0);
printf("msg from server: %s\n", szBuf);

getchar();
close(sockClient);

return 0;
}
...全文
161 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
米粒光华 2019-07-22
  • 打赏
  • 举报
回复
使用fork产生子进程时,系统将父进程打开的所有文件制作一份拷贝给子进程。在子进程中将iConnSocket关掉,只是删去子进程打开文件表中的相应表项,但因为父进程仍在使用iConnSocket,系统打开文件表中不会将iConnSocket删去。仅当父进程最后结束时关闭iConnSocket,该描述符才从系统打开文件表中删除,真正地被关掉。
离水的鱼儿 2019-06-15
  • 打赏
  • 举报
回复
引用 6 楼 slwj 的回复:
[quote=引用 5 楼 离水的鱼儿 的回复:] 追根究底就是防止某些资源没有被释放,导致垃圾空间,尤其是做网络,当连接数过多的时候资源也会消耗的很大,所以要注意资源释放的问题
多次释放会不会引出问题来?[/quote]多次释放会释放失败,会反回一个错误代码,就和释放空指针一个道理,你可以在释放之前判断一下资源是否有效,如同释放指针 判断是不是为空再释放。
slwj 2019-06-15
  • 打赏
  • 举报
回复
引用 7 楼 轻箬笠 的回复:
fork是克隆的意思吧。 也就是说,调用fork之后,子进程和父进程的变量指向的内存都不一样了吧。所以需要分别释放吧。 “一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。”
释放是应该的,本来一次释放就可以了,我的意思是多次释放,会不会出错?
sdghchj 2019-06-15
  • 打赏
  • 举报
回复
Linux里所有资源都可叫文件,文件是可以同时共享打开多次的,打开多次就要关闭多次。
轻箬笠 2019-06-15
  • 打赏
  • 举报
回复
fork是克隆的意思吧。
也就是说,调用fork之后,子进程和父进程的变量指向的内存都不一样了吧。所以需要分别释放吧。

“一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。”
slwj 2019-06-14
  • 打赏
  • 举报
回复
引用 5 楼 离水的鱼儿 的回复:
追根究底就是防止某些资源没有被释放,导致垃圾空间,尤其是做网络,当连接数过多的时候资源也会消耗的很大,所以要注意资源释放的问题
多次释放会不会引出问题来?
赵4老师 2019-06-12
  • 打赏
  • 举报
回复
虎头蛇尾是俗人的习惯, 有始有终是君子的操守。
离水的鱼儿 2019-06-12
  • 打赏
  • 举报
回复
追根究底就是防止某些资源没有被释放,导致垃圾空间,尤其是做网络,当连接数过多的时候资源也会消耗的很大,所以要注意资源释放的问题
slwj 2019-06-12
  • 打赏
  • 举报
回复
子进程有2处地方,父进程有1处调用
close(iConnSocket);
CT8100 2019-06-12
  • 打赏
  • 举报
回复
前者close 后有return 所以这说明永远只有一个close执行了
棉猴 2019-06-12
  • 打赏
  • 举报
回复
我觉得就是为了防止资源没有释放,多关闭几次。

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧