struct message{
int id;
char* data;
};
…
send(fds[i].fd, &msg, sizeof(msg), 0)
Этот send отправляет клиенту не данные, а указатель. Указатель на данные, которых у клиента нет.
// Add new socket to poll array
fds[nfds].fd = new_socket;
fds[nfds].events = POLLIN;
nfds++;
}
// Check for data from clients
for (int i = 1; i < nfds; i++) {
if (fds[i].revents & POLLIN) {
Здесь ты добавил сокет в массив дескрипторов полл и сразу проверяешь, не установлен ли у него revents. Но это поле в этот момент не инициализировано. Мало того, ты просишь ожидать POLLIN, но клиент никогда ничего не отправляет серверу, поэтому и сервер не дождавшись POLLIN никогда ничего не отправляет клиенту.
struct pollfd fds[1];
fds[0].fd = sock;
fds[0].events = POLLOUT;
if (poll(fds, 1, -1) <= 0) {
perror("poll failed");
exit(EXIT_FAILURE);
}
if (!(fds[0].revents & POLLOUT)) {
perror("connect failed");
exit(EXIT_FAILURE);
}
// Receive message from server
while ((valread = read(sock, &msg, sizeof(msg))) == -1 && errno == EAGAIN);
Здесь ты ждёшь до POLLOUT, но после этого начинаешь читать. Это малость нелогично, потому что наличие данных для чтения показывается флагом POLLIN. POLLOUT же на свежеустановленном соединении есть сразу, поэтому чтение тупо вертится в цикле while пока не прийдут данные.
как это можно попробовать подебажить понять что не так, что происходит
Можно тупо повставлять печать в ключевые места, что да, соединение установлено, соединение принято, полл завершился успехом, данные отправлены, данные приняты.