【发布时间】:2021-03-25 05:56:48
【问题描述】:
我正在尝试编写一个将串行数据流式传输到客户端的基本 TCP 服务器。服务器将连接到串行设备,从该设备读取数据,然后将其作为字节流传输给客户端。写TCP服务器没问题。问题是当客户端断开连接时服务器会崩溃。在其他语言中,例如 Python,我可以简单地将 write() 语句包装在 try-catch 块中。程序将尝试写入套接字,但如果客户端已断开连接,则会引发异常。在另一个项目中,这段代码 sn-p 为我工作:
try:
client_socket.send(bytes(buf, encoding='utf8'))
except Exception as e:
logger.info("Client disconnected: %s", client_id)
我可以在我的 C 代码中处理客户端断开连接,但只能通过首先从套接字读取并检查读取是否等于 0。如果是,那么我的客户端已断开连接,我可以照常进行。这个解决方案的问题是我的客户端在每次写入后都必须 ping 回服务器,这不太理想。
有谁知道如何在 C 中优雅地处理 TCP 客户端断开连接?我的示例代码如下所示。谢谢!
// Define a TCP socket
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
// Allow for the backlog of 100 connections to the socket
int backlog = 100;
// Supply a port to bind the TCP server to
short port = 9527;
// Set up server attributes
struct sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(port);
// Set the socket so that we can bind to the same port when we exit the program
int flag = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)) == -1) {
perror("setsockopt fail");
}
// Bind the socket to the specified port
int res = bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
if (res < 0) {
perror("bind fail");
exit(1);
}
// Listen for incoming connections
if (listen(sockfd, backlog) == -1) {
perror("listen fail");
exit(1);
} else {
printf("Server listening on port\n", port);
}
for(;;) {
// Wait for incoming connection
struct sockaddr_in cliaddr;
socklen_t len = sizeof(cliaddr);
int connfd = accept(sockfd, (struct sockaddr *)&cliaddr, &len);
if (-1 == connfd) {
perror("Could not accept incoming client");
continue;
}
//Resolving Client Address
char buff[INET_ADDRSTRLEN + 1] = {0};
inet_ntop(AF_INET, &cliaddr.sin_addr, buff, INET_ADDRSTRLEN);
uint16_t cli_port = ntohs(cliaddr.sin_port);
printf("connection from %s, port %d\n", buff, cli_port);
for(;;) {
// Read from serial device into variable here, then send
if(send(connfd, "Data...Data...Data\n", 19, 0) < 0) {
printf("Client disconnected...\n");
break;
}
}
}
【问题讨论】:
-
试一试? C? C 没有例外。
-
对。我是说在 Python 这样的另一种语言中,我可以使用 try-catch 来处理客户端断开连接。 C 没有这种机制,所以我想知道是否有一种替代方案不需要客户端一直 ping 回服务器。
-
如果没有持续不断的通信,就无法知道连接是否仍然存在。
-
通常服务器会使用
select或poll来查看哪些客户端发送了新数据。断开连接算作发送新数据,但当您尝试读取数据时,read将返回 0。 -
@user253751 -- 我明白了。那么这是否意味着处理客户端断开连接的唯一方法是让客户端不断发送新数据,然后让服务器从套接字读取?令我感到奇怪的是,大多数语言在底层都是用 C 构建的,它们可以处理客户端断开连接而无需从套接字读取。但是 C 本身无法处理它,除非客户端不断 ping 服务端
标签: c sockets server tcp stream