Я впервые играю с epoll в Linux и вижу странное поведение. Specificall, когда я подключаюсь к клиенту к сокету, я вижу два события, выпущенных epoll_wait на стороне сервера. Когда я вызываю accept во второй попытке, я получаю сообщение «временно недоступный».Видя два события принятия на epoll
Вот простой код клиента:
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
const char* msg = "friendly ping";
int main(int argc, char** argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <socket>\n", argv[0]);
exit(-1);
}
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket");
exit(-1);
}
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, argv[1], sizeof(addr.sun_path) - 1);
if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
perror("Error connecting");
exit(-1);
}
write(sock, msg, strlen(msg));
close(sock);
return 0;
}
Серверный код является следующее:
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
const int kMaxEvents = 100;
const char *kSocketFile = "dummy_socket";
void MakeNonBlocking(int fd) {
int flags, s;
flags = fcntl (fd, F_GETFL, 0);
if (flags == -1) {
perror ("fcntl");
exit(-1);
}
flags |= O_NONBLOCK;
s = fcntl (fd, F_SETFL, flags);
if (s == -1) {
perror ("fcntl");
exit(-1);
}
}
void AcceptConnections(int sock, int epoll_fd) {
struct epoll_event event;
event.data.fd = sock;
event.events = EPOLLIN;
int insock = accept(sock, NULL, NULL);
if (insock < 0) {
perror("Error accepting connection");
exit(-1);
}
MakeNonBlocking(insock);
int s = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, insock, &event);
if (s < 0) {
perror("Epoll error adding accepted connection");
exit(-1);
}
printf("Connection processed.\n");
}
int main(void) {
int sock, efd, n;
struct sockaddr_un addr;
struct epoll_event event;
struct epoll_event *events;
char buf[1024];
if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
perror("Error creating socket.");
exit(-1);
}
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, kSocketFile, sizeof(addr.sun_path) - 1);
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
perror("Error binding name to socket");
exit(-1);
}
if (listen(sock, SOMAXCONN) < 0) {
perror("Error listening on socket");
exit(-1);
}
MakeNonBlocking(sock);
if ((efd = epoll_create1(0)) < 0) {
perror("Epoll initialization error");
exit(-1);
}
event.data.fd = sock;
event.events = EPOLLIN;
if (epoll_ctl(efd, EPOLL_CTL_ADD, sock, &event) < 0) {
perror("Epoll error adding socket");
exit(-1);
}
events = (struct epoll_event*) calloc(kMaxEvents, sizeof(event));
if (!events) {
perror("Error allocating event buffers");
exit(-1);
}
while(1) {
printf("Calling epoll_wait\n");
if ((n = epoll_wait(efd, events, kMaxEvents, -1)) == -1) {
perror("epoll_wait failure");
exit(-1);
}
for (int i = 0; i < n; ++i) {
printf("Checking event for fd = %d\n", events[i].data.fd);
if (sock == events[i].data.fd) {
AcceptConnections(sock, efd);
continue;
}
int count = read(events[i].data.fd, buf, 100);
if (count == 0) {
close(events[i].data.fd);
}
write(1, buf, count);
}
}
free(events);
close(efd);
close(sock);
unlink(kSocketFile);
return 0;
}
Когда я запускать сервер и подключиться к клиенту, я получаю:
Calling epoll_wait
Checking event for fd = 3
Connection processed.
Calling epoll_wait
Checking event for fd = 3
Error accepting connection: Resource temporarily unavailable
Другими словами, я вижу два события в гнезде для прослушивания. Есть идеи?
Мне бы хотелось это проверить, но я получаю ошибку времени выполнения: 'Ошибка привязки имени к сокету: операция не разрешена' ... – Myst