1、使用close
函数
原理:close
函数用于完全关闭一个已打开的套接字,包括接收和发送都不可再用,在TCP协议中,close
函数会发送一个FIN包给对方,表示自己没有数据要发送了,请求关闭连接,对方收到FIN包后,会发送一个ACK包回应,然后关闭连接。
示例代码:
“`c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
// 创建套接字文件描述符
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
// 绑定套接字到端口8080
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(8080);
if (bind(server_fd, (struct sockaddr )&address, sizeof(address))<0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
// 开始监听是否有客户端连接
if (listen(server_fd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
// 接受客户端连接
if ((new_socket = accept(server_fd, (struct sockaddr )&address, (socklen_t)&addrlen))<0) {
perror("accept");
exit(EXIT_FAILURE);
}
// 这里可以与客户端进行通信
// 关闭与客户端的连接
close(new_socket);
// 关闭服务器端的监听套接字
close(server_fd);
return 0;
}
适用场景:适用于不需要继续通信并且已经完成所有数据交换的情况,比如客户端发送完请求并接收到响应后,服务器处理完请求就可以关闭连接。 2、原理: shutdown
函数用于优雅地关闭连接,并等待对方确认关闭,它可以只关闭套接字的发送或接收部分,也可以同时关闭接收和发送。参数说明:int shutdown(int sockfd, int how);
sockfd
是连接的套接字描述符,how
表示关闭连接的方式,有以下三种取值:SHUT_RD
:只关闭接收,后续的数据读取会失败。SHUT_WR
:只关闭发送,后续的数据发送会失败。SHUT_RDWR
:同时关闭接收和发送,即完全终止连接。示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> int main() { int server_fd, new_socket; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); // 创建套接字文件描述符等初始化操作(同上)... // 接受客户端连接(同上)... // 只关闭与客户端的发送功能,但仍然可以接收数据 shutdown(new_socket, SHUT_WR); // 或者同时关闭发送和接收功能 shutdown(new_socket, SHUT_RDWR); // 关闭与客户端的连接 close(new_socket); // 关闭服务器端的监听套接字 close(server_fd); return 0; }
适用场景:当只需要关闭连接的一部分功能时可以使用,比如服务器只想停止向客户端发送数据,但仍然可以接收客户端的数据,就可以使用shutdown(new_socket, SHUT_WR)
,这种方式比较优雅,可以给双方一定的时间来处理连接关闭的相关事宜。
3、超时关闭连接
原理:服务端可以设置一个超时时间,当连接在一段时间内没有接收到任何数据时,服务端可以主动关闭连接,这可以通过定时器或者超时检测机制来实现。
实现方式:可以在服务器端的主循环中使用select
、poll
或epoll
等I/O多路复用技术来检测套接字的状态,如果某个连接在规定的时间内没有任何活动,就关闭该连接,使用select
函数时,可以设置超时时间为NULL
,然后定期检查每个套接字的状态,如果发现某个套接字在超时时间内没有可读或可写事件,就关闭该套接字。
示例代码:
“`c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <sys/time.h>
#define TIMEOUT_SECONDS 30
int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
fd_set readfds;
struct timeval tv;
// 创建套接字文件描述符等初始化操作(同上)…
// 接受客户端连接(同上)…
while (1) {
// 设置超时时间为TIMEOUT_SECONDS秒
FD_ZERO(&readfds);
FD_SET(new_socket, &readfds);
tv.tv_sec = TIMEOUT_SECONDS;
tv.tv_usec = 0;
// 使用select函数检测套接字状态
int retval = select(new_socket + 1, &readfds, NULL, NULL, &tv);
if (retval == -1) {
perror("select()");
break;
} else if (retval == 0) {
// 超时,关闭连接
printf("Connection timed out, closing connection.
");
close(new_socket);
break;
} else {
// 处理客户端请求(如果有的话)
}
}
// 关闭服务器端的监听套接字
close(server_fd);
return 0;
}
适用场景:适用于需要限制连接空闲时间的场景,比如服务器资源有限,不希望长时间保持空闲连接占用资源,就可以设置超时时间来自动关闭这些空闲连接。
4、异常关闭连接:当服务端发现连接出现了异常情况,比如收到了无效的数据包或者对方发生了错误,可以选择异常关闭连接,这一般需要服务端有一套完善的异常处理机制。实现方式:在服务器端的数据处理过程中,添加对各种异常情况的判断和处理逻辑,当检测到异常时,可以直接调用close
函数关闭连接,并记录相关的错误信息以便后续排查问题,在接收客户端数据时,如果发现数据格式不正确或者数据长度不符合预期,就可以认为这是一个异常情况,然后关闭该连接。示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1024];
// 创建套接字文件描述符等初始化操作(同上)...
// 接受客户端连接(同上)...
while (1) {
int valread = read(new_socket, buffer, 1024);
if (valread == -1) {
perror("read");
close(new_socket);
break;
} else if (valread == 0) {
printf("Client disconnected.
");
close(new_socket);
break;
} else {
// 简单的异常判断:如果接收到的数据长度为0,认为是异常情况
if (valread == 0) {
printf("Received invalid data, closing connection.
");
close(new_socket);
break;
}
}
}
// 关闭服务器端的监听套接字
close(server_fd);
return 0;
}
适用场景:适用于服务器需要对连接的可靠性和数据的有效性进行严格检查的情况,一旦发现异常立即断开连接,以保证服务器的稳定运行和数据的安全性。
服务器端关闭连接的方式有多种,每种方式都有其特点和适用场景,在实际应用中,需要根据具体的需求和场景选择合适的关闭连接方式,以确保服务器的正常运行和资源的有效利用。
原创文章,作者:未希,如若转载,请注明出处:https://www.kdun.com/ask/1661029.html
本网站发布或转载的文章及图片均来自网络,其原创性以及文中表达的观点和判断不代表本网站。如有问题,请联系客服处理。
发表回复