关闭客户端套接字并保持服务器套接字处于活动状态

3

我正在使用TCP套接字建立服务器-客户端连接。每当我关闭客户端套接字时,我的服务器也会关闭。但是我只想关闭客户端,我的服务器必须等待下一个accept()

服务器端:

{
bind(lfd,(struct sockaddr*)&serv_addr, sizeof(serv_addr));
listen(lfd, 10);
   while(1)
   {
        cfd = accept(lfd, (struct sockaddr*)NULL, NULL);
   //server must wait here after client closes the connection application code
        close(lfd);
    }
}

客户端:

inet_pton(AF_INET, argv[1], &serv_addr.sin_addr);
connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
// ... application code
if(c == 1)
   close(fd);

在Codeproject.com上查找TCP套接字的多线程/多连接示例,并了解如何实现它。 - i486
关键在于分叉一个新的进程来处理新连接。然后,在您的子进程运行查询以完成时,继续运行主进程。如果您使用线程(可以这样做),则需要确保线程不会关闭彼此的套接字-因为线程共享同一堆。 - Owl
3个回答

15

当你在服务端使用accept时,你会为该客户端生成一个新的套接字。

当你处理完客户端后,必须使用close()关闭该套接字(也就是在你的术语中使用close(cfd))。你也可以使用shutdown()关闭套接字 - 这将影响套接字在TCP层面上如何关闭。但无论你是否使用shutdown(),你必须关闭它,否则将泄露FD(文件描述符)。

你不能关闭监听FD(lfd 在你的程序中)直到你不再想接受任何连接。

简而言之: 把 close(lfd) 改成 close(cfd)


6
描述符lfd描述的TCP监听套接字用于在特定端口等待TCP传入连接。 在调用accept之后,将创建一个新的套接字描述符,即您示例中的cfd
所有服务器和客户端之间的数据交换都是使用cfd执行的。 如果客户端首先关闭了套接字,则服务器端的sendrecv可能会返回-1,并附带适当的errno值。
如果您想让服务器关闭连接,则应该在shutdown(cfd,SHUT_RDWR)close(cfd)之后使用,而不是使用close(lfd)。这样可以使lfd套接字保持打开状态,允许服务器等待下一个传入连接的acceptlfd应在服务器终止时关闭。 shutdown()提供了更大的灵活性,可以在永久终止通信之前发送或接收剩余数据。

你的意思是 shutdown(而不是 close)吗? - Basile Starynkevitch
是的,我的错误。但是close()也可以工作。基本区别在于shutdown允许您接收任何挂起的数据,而使用close()时,套接字会立即被销毁。 - Manos
顺便提一下,您打错字了(应该是 close,而不是 clode - Basile Starynkevitch
@Manos 我认为那不对。如果你shutdown但没有close,你会泄漏一个FD。请看下面我的回答。 - abligh

0

accept调用将返回一个新的套接字描述符(在您的代码中为cfd),该描述符连接到客户端,因此当客户端关闭其连接端时,cfd将被关闭而不是lfd。只要服务器需要,您可以使用lfd(监听套接字)来接受连接。还要考虑在客户端代码中在close(fd)之前调用shutdown。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接