非阻塞 Linux 服务器套接字
Non-blocking Linux server socket
我想创建一个始终打印到屏幕的服务器套接字 "tick" ,如果一个客户端向该服务器发送数据,服务器将打印该数据。我使用非阻塞套接字,但它不起作用,服务器打印到屏幕 "tick" 但无法从客户端接收数据。
服务器
int main(int argc, char *argv[]) {
int server_sockfd, client_sockfd;
sockaddr_un server_address;
sockaddr_un client_address;
int client_len;
int res;
/* remove old socket and create unnamed socket */
unlink("server_socket");
server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
/* non-blocking socket */
fcntl(server_sockfd, F_SETFL, O_NONBLOCK);
/* name the socket */
server_address.sun_family = AF_UNIX;
strcpy(server_address.sun_path, "server_socket");
bind(server_sockfd, (sockaddr*)&server_address, sizeof(server_address));
/* listen client */
printf("server_waiting\n");
listen(server_sockfd, 5);
client_len = sizeof(client_address);
client_sockfd = accept(server_sockfd, (sockaddr*)&client_address, (socklen_t*)&client_len);
while(1) {
char ch;
res = recv(client_sockfd, &ch, 1, 0);
if (res == -1) {
printf("tick\n");
}
else {
printf("received: %c\n", ch);
}
}
}
客户
int main(int argc, char *argv[]) {
int sock_fd;
struct sockaddr_un address;
int result;
char ch = 'A';
/* create socket for client */
sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
/* name of socket as agreed with server */
address.sun_family = AF_UNIX;
strcpy(address.sun_path, "server_socket");
result = connect(sock_fd, (sockaddr*) &address, sizeof(address));
if (result == -1) {
perror("fail\n");
exit(1);
}
/* write via socket */
send(sock_fd, &ch, 1, 0);
close(sock_fd);
exit(0);
}
您正在将列表套接字设置为非阻塞而不是接受的套接字。
按照您的代码逻辑,您确实希望等待 accept 调用,而不是 recv 调用
而不是
/* non-blocking socket */
fcntl(server_sockfd, F_SETFL, O_NONBLOCK);
删除它,而是将 fcntl 调用添加到您从 accept 调用返回的套接字中,例如
client_sockfd = accept(....);
int flags = fcntl(client_sockfd, F_GETFL, 0);
fcntl(client_sockfd, F_SETFL, flags | O_NONBLOCK);
accept
和 fcntl
可能会失败,因此您应该检查生产代码中的失败。
我想创建一个始终打印到屏幕的服务器套接字 "tick" ,如果一个客户端向该服务器发送数据,服务器将打印该数据。我使用非阻塞套接字,但它不起作用,服务器打印到屏幕 "tick" 但无法从客户端接收数据。
服务器
int main(int argc, char *argv[]) {
int server_sockfd, client_sockfd;
sockaddr_un server_address;
sockaddr_un client_address;
int client_len;
int res;
/* remove old socket and create unnamed socket */
unlink("server_socket");
server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
/* non-blocking socket */
fcntl(server_sockfd, F_SETFL, O_NONBLOCK);
/* name the socket */
server_address.sun_family = AF_UNIX;
strcpy(server_address.sun_path, "server_socket");
bind(server_sockfd, (sockaddr*)&server_address, sizeof(server_address));
/* listen client */
printf("server_waiting\n");
listen(server_sockfd, 5);
client_len = sizeof(client_address);
client_sockfd = accept(server_sockfd, (sockaddr*)&client_address, (socklen_t*)&client_len);
while(1) {
char ch;
res = recv(client_sockfd, &ch, 1, 0);
if (res == -1) {
printf("tick\n");
}
else {
printf("received: %c\n", ch);
}
}
}
客户
int main(int argc, char *argv[]) {
int sock_fd;
struct sockaddr_un address;
int result;
char ch = 'A';
/* create socket for client */
sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
/* name of socket as agreed with server */
address.sun_family = AF_UNIX;
strcpy(address.sun_path, "server_socket");
result = connect(sock_fd, (sockaddr*) &address, sizeof(address));
if (result == -1) {
perror("fail\n");
exit(1);
}
/* write via socket */
send(sock_fd, &ch, 1, 0);
close(sock_fd);
exit(0);
}
您正在将列表套接字设置为非阻塞而不是接受的套接字。
按照您的代码逻辑,您确实希望等待 accept 调用,而不是 recv 调用
而不是
/* non-blocking socket */
fcntl(server_sockfd, F_SETFL, O_NONBLOCK);
删除它,而是将 fcntl 调用添加到您从 accept 调用返回的套接字中,例如
client_sockfd = accept(....);
int flags = fcntl(client_sockfd, F_GETFL, 0);
fcntl(client_sockfd, F_SETFL, flags | O_NONBLOCK);
accept
和 fcntl
可能会失败,因此您应该检查生产代码中的失败。