C чат. Connect () ждет слишком долго; сервер не может отправить конкретную информацию клиенту - PullRequest
0 голосов
/ 21 апреля 2020

Я работаю над программой многопользовательского чата Wi-Fi. Буду признателен за помощь в следующем:

  1. Из-за природы маршрутизаторов dhcp, неясно, какой адрес сервер будет получать каждый день. Клиент просматривает список всех возможных хостов, начиная с 192.168.1.1. Когда он сталкивается с несерверным устройством, он ожидает в течение произвольного промежутка времени, вплоть до минуты. Как я могу заставить его перестать ждать через секунду? Я пытался остановить его с помощью alarm () перед тем, как прочитать руководство по тревоге, так что это была пустая трата времени.
  2. Функция сервера printUsers() - единственная функция, выход которой иногда доставляется, иногда нет. Я бы хотел, чтобы кто-то объяснил, почему.
  3. Я хотел бы получить отзыв о качестве кода. Под этим я подразумеваю такие вещи, как читаемость и удобство сопровождения кода, дизайн программы, стиль, обработка ошибок и т. Д. c.

Код сервера

#include <arpa/inet.h>
#include <ctype.h>
#include <ifaddrs.h>
#include <netdb.h>       //adds symbolic network constants
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

#define BYE           0
#define ERROR         -1
#define HOST_SIZE     4
#define MAX_CONN      11
#define MSG_LEN       255
#define NAME_LEN      30
#define SYS_MSG_LEN  18

int debug;            //command-line argument
int mySock;           //sustains value from assignment till the end
typedef struct pollfd pollfd; 

void addName2msg(char name[], char msg[], char msgOut[]);
void addUser(char name[], int i, char msg[], pollfd *fds, int fdsInd);
void findMyIP(char myIP[]);
void handleArgs(int argc, char *argv[]);
void handleLeaver(int i, char names[][NAME_LEN], pollfd *fds, int*fdI);
void handleNewClient(pollfd *fds, int *fdsInd);
void printUsers(char names[][NAME_LEN], int i, int fd);
void sendAll(int i, char msgOut[], pollfd *fds, int fdsInd);
void sendErr(char *msg);
void sendMsg(int fd, char msg[], int len);
void startHost(char myIP[]);


void workLoop()
{
    static pollfd fds[MAX_CONN];
    int status, fdsInd = 0; 
    static char names[MAX_CONN+1][NAME_LEN];
    char msg[MSG_LEN], msgOut[MSG_LEN+NAME_LEN]; 

    fds[fdsInd].fd = mySock;
    fds[fdsInd++].events = POLLIN;

    while(1) {
        if (debug)
            puts("Waiting for an event to happen...");
        if (poll(fds, fdsInd, -1) == -1)
            sendErr("poll() failed");
        if (debug)
            puts("An event happened");
        for (int i = 0; i < fdsInd; i++) {
            if ((fds[i].fd == mySock) && (fds[i].revents & POLLIN)) {
                handleNewClient(fds, &fdsInd);
            } else if (fds[i].revents & POLLIN) { //handle message
                status = recv(fds[i].fd, msg, MSG_LEN, 0);
                if (debug)
                    printf("Recieved msg from %s, socket %d\n", 
                                          names[i], fds[i].fd);

                if ((status == BYE) || (status == ERROR)) {
                    printf("Status is %d\n", status == BYE? BYE: ERROR);
                    handleLeaver(i, names, fds, &fdsInd);
                    continue;
                }
                if (*names[i] == '\0')  {   //no name? Save msg as name
                    addUser(names[i], i, msg, fds, fdsInd);
                    printUsers(names, i, fds[i].fd);
                    continue;
                }
                addName2msg(names[i], msg, msgOut);
                sendAll(i, msgOut, fds, fdsInd);
            }
        }
    }
}


int main(int argc, char *argv[])
{
    char myIP[INET_ADDRSTRLEN];

    handleArgs(argc, argv);
    findMyIP(myIP);              
    startHost(myIP);
    workLoop();

    return 0;
}
//
void addName2msg(char name[], char msg[], char msgOut[]) {
    int len;
    strncpy(msgOut, name, NAME_LEN );
    len = strlen(msgOut);
    msgOut[len] = ':';
    msgOut[len+1] = ' ';
    strcat(msgOut, msg);
}
//
void addUser(char name[], int i, char msg[], pollfd *fds, int fdsInd)
{
    int j;
    char msgWelc[SYS_MSG_LEN + NAME_LEN] = "Welcome to chat, ";
    char msgJoin[SYS_MSG_LEN] = " joined the chat\n";

    for (j = 0; j < NAME_LEN-3; j++) {
        if (msg[j] == '\n' || isspace(msg[j]))
            break;
        name[j] = msg[j];
    }
    name[j] = '\n';
    name[j+1] = '\0';
    strcat(msgWelc, name);
    sendMsg(fds[i].fd, msgWelc, SYS_MSG_LEN+NAME_LEN);
    name[j] = '\0';
    strncpy(msgWelc, name, NAME_LEN);
    strcat(msgWelc, msgJoin);
    sendAll(i, msgWelc, fds, fdsInd);
}
//
void findMyIP(char myIP[])
{
    struct ifaddrs *addrs;
    struct sockaddr_in *pAddr;

    getifaddrs(&addrs);
    for (; addrs != NULL; addrs = addrs->ifa_next) {
        pAddr = (struct  sockaddr_in *) addrs->ifa_addr;
        if (strstr(inet_ntoa(pAddr->sin_addr), "192.168.1") != NULL)
            strncpy(myIP, inet_ntoa(pAddr->sin_addr), INET_ADDRSTRLEN);
    }
    freeifaddrs(addrs);
    if (debug)
        printf("Local IP is %s\n", myIP);
}
//
void handleArgs(int argc, char *argv[])
{
    if (argc > 2) {
        puts("error: one arg max");
        exit(1);
    }
    if ((argc == 2) && (strcmp("-d", argv[argc-1]) != 0)) {
        puts("error: Call with -d for debugging");
        exit(1);
    } else if (argc == 2)
        debug = 1;
}
//
void handleLeaver(
     int i, char names[][NAME_LEN], pollfd *fds, int *fdsInd)
{
    int lastElem = *fdsInd - 1;
    char trash[MSG_LEN];
    char msgLeft[SYS_MSG_LEN] = " left the chat\n";

    //notify all users
    strncpy(trash, names[i], strlen(names[i])+1);   
    strcat(trash, msgLeft);
    sendAll(i, trash, fds, *fdsInd);

    if (debug) {
        printf("Had: fds0:%d fds1:%d fds2:%d; fdsInd: %d\n", 
                    fds[0].fd, fds[1].fd, fds[2].fd, *fdsInd);
        printf("\tNames1: %s, Names2: %s\n", names[1], names[2]);
    }
    recv(fds[i].fd, trash, MSG_LEN, 0);  //receive garbage

    if (lastElem == i) { 
        fds[i].fd = 0;
        fds[i].events = 0;
        (*fdsInd)--;
        names[i][0] = 0;
    } else {           
        fds[i].fd = fds[lastElem].fd;
        fds[i].events = fds[lastElem].events;
        strncpy(names[i], names[lastElem], NAME_LEN);
        fds[lastElem].fd = 0;
        fds[lastElem].events = 0;   
        (*fdsInd)--;
        names[lastElem][0] = 0;
    }
    if (debug) {
        printf("Removed user\n");
        printf("Have: fds0:%d fds1:%d fds2:%d; fdsInd: %d\n", 
                    fds[0].fd, fds[1].fd, fds[2].fd, *fdsInd);
        printf("\tNames1: %s, Names2: %s\n", names[1], names[2]);
    }
}
//
void handleNewClient(pollfd *fds, int *fdsInd)
{
    struct sockaddr clientInfo;
    socklen_t addrSz;
    int newFD; 
    char nameReq[SYS_MSG_LEN] = "Enter your name: ";

    addrSz = sizeof(clientInfo);
    newFD = accept(mySock, &clientInfo, &addrSz); 
    if (*fdsInd > MAX_CONN) {   //kill extra users
        close(newFD);
        return;
    }
    fds[*fdsInd].fd = newFD;
    fds[(*fdsInd)++].events = POLLIN;
    if (debug)
        puts("Accepted a client");
    sendMsg(newFD, nameReq, SYS_MSG_LEN);
}
//
void printUsers(char names[][NAME_LEN], int i, int fd)
{
    int len;
    char msgStart[SYS_MSG_LEN] = "Online Users:\n";
    sendMsg(fd, msgStart, SYS_MSG_LEN);
    if (debug)
        printf("Online users printed for %s, %d\n", names[i], fd);

    for (int j = 0; j < MAX_CONN; j++) {
        if ((names[j][0] != 0) && (strcmp(names[j], names[i]) != 0)) {
            len = strlen(names[j]);
            names[j][len] = '\n';
            names[j][len+1] = '\0';
            sendMsg(fd, names[j], NAME_LEN);
            names[j][len] = '\0';
        }
    }
}
//
void sendAll(int i, char msgOut[], pollfd *fds, int fdsInd)
{
    pollfd *author = &fds[i];

    for (int j = 0; j < fdsInd; j++) {
        if (fds[j].fd == author->fd)  
            continue;
        if  (fds[j].fd == mySock)    
            continue;
        sendMsg(fds[j].fd, msgOut, MSG_LEN);
    }
}
//
void sendErr(char *msg)
{
    perror(msg);
    exit(1);
}
//
void sendMsg(int fd, char msg[], int len)
{
    int sent = 0;

    if ((len == MSG_LEN) && (msg[len-1]!= '\0'))
        msg[len-1] = '\0';
    if ((len == MSG_LEN) && (msg[len-2]!= '\n'))
        msg[len-2] = '\n';

    while (sent < len) {
        sent = send(fd, msg, len, 0);
        if (sent == -1)
            sendErr("Sending message failed");
        else if (sent == len)
            return;
    }
}
//
void startHost(char myIP[])
{
    struct addrinfo hints, *servinfo;
    int yes = 1; 
    char port[] = "39071";

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;     // any IPv*
    hints.ai_socktype = SOCK_STREAM;

    if (getaddrinfo(myIP, port, &hints, &servinfo) != 0)
        sendErr("Getaddinfo() failed");

    if ((mySock = socket(servinfo->ai_family, 
                  servinfo->ai_socktype, servinfo->ai_protocol)) == -1)
        sendErr("Socket() failed");

    if (-1 == setsockopt(
              mySock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)))
        sendErr("setsockopt() failed");

    if (bind(mySock, servinfo->ai_addr, servinfo->ai_addrlen) == -1)
        sendErr("Bind() failed");

    if (listen(mySock, MAX_CONN) == -1)
        sendErr("listen() failed");

    if (debug) {
        printf("Host socket is %d\n", mySock);
        printf("Listening to port %s...\n", port);
    }
}

Код клиента

#include <arpa/inet.h>
#include <ifaddrs.h>
#include <netdb.h>       //adds symbolic network constants
#include <poll.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

#define FDS_NUM            2
#define HOST_SIZE          4
#define MSG_LEN            255
#define MAX_CONN          11

enum { ERROR = -1, OFF = 0, SERV_DOWN = 0 , FAIL = 0, SUCCESS = 1 };

int debug;            //command-line argument
int mySock;           //received in prepareNet() and kept till the end

//int catchSignal(int sig, void (*handler)(int));
void chat();
//void doNoth(int sig) { sig = sig; return; }
void exit_closedConn();
int findHost(struct addrinfo *servinfo[]);
void handleArgs(int argc, char *argv[]);
void prepareNet(struct addrinfo *servinfo[]);
void sendErr(char *msg);

int main(int argc, char *argv[])
{
    struct addrinfo *servinfo[MAX_CONN];

    handleArgs(argc, argv);
    prepareNet(servinfo);
    //if (catchSignal(SIGALRM, doNoth) == -1)
    //        sendErr("Sigaction failed");
    if (!findHost(servinfo))
        sendErr("No hosts found");
    chat();

    return 0;
}
//
int catchSignal(int sig, void (*handler)(int))
{
    struct sigaction new;

    new.sa_handler = handler;
    sigemptyset(&new.sa_mask);
    new.sa_flags = 0;

    return sigaction(sig, &new, NULL);
}
//
void chat()
{
    struct pollfd pds[FDS_NUM];  
    int status;
    char msgIn[MSG_LEN];
    char usrMsg[MSG_LEN];
    pds[0].fd = 0;  //stdin
    pds[1].fd = mySock;
    pds[0].events = pds[1].events = POLLIN;
    while (1) {
        if (poll(pds, FDS_NUM, -1) == -1)
            sendErr("Poll failed");

        if (pds[0].revents & POLLIN) {
            fgets(usrMsg, MSG_LEN, stdin);
            if (send(pds[1].fd, usrMsg, MSG_LEN, 0) == -1)
                sendErr("Sent failed");
        } else if (pds[1].revents & POLLIN) {
            if ((status = recv(pds[1].fd, msgIn, MSG_LEN, 0)) == ERROR)
                sendErr("recv failed");
            else if (status == SERV_DOWN)
                exit_closedConn();
            printf("%s", msgIn);
            fflush(stdout);
        }
    }
}
//
void handleArgs(int argc, char *argv[])
{
    if (argc > 2) 
        sendErr("1 argument max");
    if ((argc == 2) && (strcmp("-d", argv[argc-1]) != 0)) 
        sendErr("input -d for debugging");
    else if (argc == 2)
        debug = 1;
}
//
void exit_closedConn()
{
    puts("Server closed connection. Exiting...");
    exit(1);
}
//
int findHost(struct addrinfo *servinfo[])
{
    puts("Searching for a server...");
    for (int i = 1; i < MAX_CONN; i++)   {
        if (debug)
            printf("Trying for 192.168.1.%d...\n", i);
        //alarm(1);
        if (connect(mySock, servinfo[i]->ai_addr, 
                    servinfo[i]->ai_addrlen) != -1)  {
            alarm(OFF);
            printf("Connected to 192.168.1.%d\n",i);
            return SUCCESS;
        }
    }
    return FAIL;
}
//
void prepareNet(struct addrinfo *servinfo[])
{
    struct addrinfo hints[MAX_CONN];
    char port[] = "39071";

    for (int i = 0; i < MAX_CONN; i++) {
        char host[HOST_SIZE];
        char ip[INET_ADDRSTRLEN] = "192.168.1.";

        memset(&hints[i], 0, sizeof(hints[i]));
        hints[i].ai_family = AF_UNSPEC;     // any IPv*
        hints[i].ai_socktype = SOCK_STREAM;
        sprintf(host, "%d", i);
        host[3] = '\0';
        strncat(ip, host, HOST_SIZE-1);

        if (getaddrinfo(ip, port, &hints[i], &servinfo[i]) != 0)
            sendErr("Getaddinfo() failed");
    }
    if ((mySock = socket(servinfo[0]->ai_family, 
            servinfo[0]->ai_socktype, servinfo[0]->ai_protocol)) == -1)
        sendErr("Socket() failed");
    if (debug)
        printf("Trying port %s using socket %d\n", port, mySock);
}
//
void sendErr(char *msg)
{
    perror(msg);
    exit(1);
}

ОБНОВЛЕНИЕ:

  1. Следуя советам Сикса и Бруно, я смог решить первую проблему. Вот подробности:
    • программа создает сокет и пытается подключиться
    • после установки второго сигнала тревоги
    • обработчик сигнала alarm () является фиктивной функцией
    • если соединение не установлено, программа закрывает сокет

Вопрос в том, насколько хорош этот подход?

int findHost(struct addrinfo *servinfo[])
{
    puts("Searching for a server...");
    for (int i = 1; i < MAX_CONN; i++)   {
        if ((mySock = socket(servinfo[0]->ai_family, 
                servinfo[0]->ai_socktype, servinfo[0]->ai_protocol)) == -1)
            sendErr("Socket() failed");
        if (debug) 
            printf("Trying for 192.168.1.%d...\n", i);
        alarm(1);
        if (connect(mySock, servinfo[i]->ai_addr, 
                    servinfo[i]->ai_addrlen) != -1)  {
            alarm(OFF);
            printf("Connected to 192.168.1.%d\n",i);
            //remove non-blocking
            return SUCCESS;
        }
        //sleep(1);
        close(mySock);
    }
    return FAIL;
}

1 Ответ

0 голосов
/ 22 апреля 2020

Здесь первая версия, когда соединения проверяются одно за другим с использованием неблокирующего сокета и select с таймаутом в 1 секунду. Я также изменил несколько вещей в клиенте, чтобы получить в качестве аргумента:

  • номер верхнего хоста, программа попытается подключиться с 192.168.1.1 до 192.168.1.upper_host включается
  • опционально -d, чтобы быть подробным

Полная программа клиента, включая неизмененные детали

#include <arpa/inet.h>
#include <ifaddrs.h>
#include <netdb.h>       //adds symbolic network constants
#include <poll.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

#define FDS_NUM            2
#define HOST_SIZE          4
#define MSG_LEN            255

#define PORT 39071

enum { ERROR = -1, OFF = 0, SERV_DOWN = 0 , FAIL = 0, SUCCESS = 1 };

int Debug;       //command-line argument
int MySock;      //the successfuly connected socket

//int catchSignal(int sig, void (*handler)(int));
void chat();
//void doNoth(int sig) { sig = sig; return; }
void exit_closedConn();
int findHost(int maxhost);
void handleArgs(int argc, char *argv[], int * maxhost);
void sendErr(char *msg);

int main(int argc, char *argv[])
{
  int maxhost;  //search 192.168.1.1 .. 192.168.1.<MaxIP>

  handleArgs(argc, argv, &maxhost);

    //if (catchSignal(SIGALRM, doNoth) == -1)
    //        sendErr("Sigaction failed");
  if (!findHost(maxhost)) {
    puts("No hosts found");
    exit(-1);
  }
  else
    puts("host found");

  chat();

  return 0;
}
//
int catchSignal(int sig, void (*handler)(int))
{
    struct sigaction new;

    new.sa_handler = handler;
    sigemptyset(&new.sa_mask);
    new.sa_flags = 0;

    return sigaction(sig, &new, NULL);
}
//
void chat()
{
    struct pollfd pds[FDS_NUM];  
    int status;
    char msgIn[MSG_LEN];
    char usrMsg[MSG_LEN];
    pds[0].fd = 0;  //stdin
    pds[1].fd = MySock;
    pds[0].events = pds[1].events = POLLIN;
    while (1) {
        if (poll(pds, FDS_NUM, -1) == -1)
            sendErr("Poll failed");

        if (pds[0].revents & POLLIN) {
            fgets(usrMsg, MSG_LEN, stdin);
            if (send(pds[1].fd, usrMsg, MSG_LEN, 0) == -1)
                sendErr("Sent failed");
        } else if (pds[1].revents & POLLIN) {
            if ((status = recv(pds[1].fd, msgIn, MSG_LEN, 0)) == ERROR)
                sendErr("recv failed");
            else if (status == SERV_DOWN)
                exit_closedConn();
            printf("%s", msgIn);
            fflush(stdout);
        }
    }
}

//

void handleArgs(int argc, char *argv[], int * maxhost)
{
  if ((argc < 2) || 
      (argc > 3) ||
      (sscanf(argv[1], "%d", maxhost) != 1) ||
      (*maxhost < 1) ||
      ((Debug = (argc == 3)) && strcmp(argv[2], "-d"))) {
    fprintf(stderr, "Usage: %s max_host [-d]\n", *argv);
    exit(-1);
  }
}

//

void exit_closedConn()
{
  puts("Server closed connection. Exiting...");
  exit(1);
}

//

int do_connect(int host, fd_set * fdset)
{
  if (Debug)
    printf("Trying for 192.168.1.%d...\n", host);

  int sock = socket(AF_INET, SOCK_STREAM, 0);

  if (fcntl(sock, F_SETFL,O_NONBLOCK) != 0)
    sendErr("fcntl nonblock");

  struct sockaddr_in sin = { 0 };

  sin.sin_addr.s_addr = htonl(0xC0a80100 + host); /* 192.168.1.host */
  sin.sin_port = htons(PORT);
  sin.sin_family = AF_INET;

  errno = 0;

  int r = connect(sock, (struct sockaddr*) &sin, sizeof(sin));

  if ((r < 0) && (errno != EINPROGRESS)) {
    if (Debug)
      printf("cannot connect to 192.168.1.%d\n", host);
    close(sock);
    return 0;
  }

  FD_SET(sock, fdset);
  return sock;
}

int findHost(int maxhost)
{
  int host;

  puts("Searching for a server...");

  for (host = 1; host <= maxhost; host += 1) {
    fd_set rset;

    FD_ZERO(&rset);
    if ((MySock = do_connect(host, &rset)) != 0) {
      fd_set wset = rset;
      struct timeval timeout;
      int r;

      timeout.tv_sec = 2;
      timeout.tv_usec = 0;

      r = select(MySock+1, &rset, &wset, NULL, &timeout);
      if (r < 0)
        sendErr("select");
      else if (r) {
        socklen_t len = sizeof(r);

        if (!getsockopt(MySock, SOL_SOCKET, SO_ERROR, &r, &len) && !r) {
          int flags;

          if (Debug)
            printf("connected to 192.168.1.%d\n", host);

          /* put socket in blocking mode */
          flags = fcntl(MySock, F_GETFL, 0);

          if (fcntl(MySock, F_SETFL, flags ^ O_NONBLOCK) < 0)
            sendErr("fcntl set non blocking");

          alarm(OFF);
          return SUCCESS;
        }
      }
      if (Debug)
        printf("cannot connect to 192.168.1.%d\n", host);
      close(MySock);
    }
  }

  return FAIL;
}

//
void sendErr(char *msg)
{
    perror(msg);
    exit(1);
}

Однако, если максимальное число хостов велико, даже ограничение 1 секунда на хост, который может сделать слишком много времени.

Здесь второе предложение, сокращающее необходимое время при выполнении попыток соединения для нескольких адресов, а не только для одного, при этом все еще используются неблокирующие сокеты и select с таймаутом 1 se c.

Клиент также модифицируется для получения в аргументе:

  • верхнего номера хоста, программа попытается соединиться с 192.168.1.1 до 192.168.1 .upper_host включал
  • опционально количество попыток, выполненных параллельно, по умолчанию 10
  • опционально -d, чтобы быть подробным, чтобы получить количество попыток в параллель также должна быть указана

Полная программа клиента, включая неизмененные части:

#include <arpa/inet.h>
#include <ifaddrs.h>
#include <netdb.h>       //adds symbolic network constants
#include <poll.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

#define FDS_NUM            2
#define HOST_SIZE          4
#define MSG_LEN            255

#define PORT 39071

enum { ERROR = -1, OFF = 0, SERV_DOWN = 0 , FAIL = 0, SUCCESS = 1 };

int Debug;       //command-line argument
int MySock;      //the successfuly connected socket

//int catchSignal(int sig, void (*handler)(int));
void chat();
//void doNoth(int sig) { sig = sig; return; }
void exit_closedConn();
int findHost(int maxhost, int npar);
void handleArgs(int argc, char *argv[], int * maxhost, int * npar);
void sendErr(char *msg);

int main(int argc, char *argv[])
{
  int maxhost;   //search 192.168.1.1 .. 192.168.1.<MaxIP>
  int npar = 10; //number of // connections

  handleArgs(argc, argv, &maxhost, &npar);

    //if (catchSignal(SIGALRM, doNoth) == -1)
    //        sendErr("Sigaction failed");
  if (!findHost(maxhost, npar))
    sendErr("No hosts found");
  else
    puts("host found");

  chat();

  return 0;
}
//
int catchSignal(int sig, void (*handler)(int))
{
    struct sigaction new;

    new.sa_handler = handler;
    sigemptyset(&new.sa_mask);
    new.sa_flags = 0;

    return sigaction(sig, &new, NULL);
}
//
void chat()
{
    struct pollfd pds[FDS_NUM];  
    int status;
    char msgIn[MSG_LEN];
    char usrMsg[MSG_LEN];
    pds[0].fd = 0;  //stdin
    pds[1].fd = MySock;
    pds[0].events = pds[1].events = POLLIN;
    while (1) {
        if (poll(pds, FDS_NUM, -1) == -1)
            sendErr("Poll failed");

        if (pds[0].revents & POLLIN) {
            fgets(usrMsg, MSG_LEN, stdin);
            if (send(pds[1].fd, usrMsg, MSG_LEN, 0) == -1)
                sendErr("Sent failed");
        } else if (pds[1].revents & POLLIN) {
            if ((status = recv(pds[1].fd, msgIn, MSG_LEN, 0)) == ERROR)
                sendErr("recv failed");
            else if (status == SERV_DOWN)
                exit_closedConn();
            printf("%s", msgIn);
            fflush(stdout);
        }
    }
}

//

void handleArgs(int argc, char *argv[], int * maxhost, int * npar)
{
  if ((argc < 2) || 
      (argc > 4) ||
      (sscanf(argv[1], "%d", maxhost) != 1) ||
      (*maxhost < 1) ||
      ((argc >= 3) && ((sscanf(argv[2], "%d", npar) != 1) || (*npar < 1))) ||
      ((Debug = (argc == 4)) && strcmp(argv[3], "-d"))) {
    fprintf(stderr, "Usage: %s max_host [n_par [-d]] (default n_par is 10)\n", *argv);
    exit(-1);
  }
}

//

void exit_closedConn()
{
  puts("Server closed connection. Exiting...");
  exit(1);
}

//

int do_connect(int host, int * highersock, fd_set * fdset)
{
  if (Debug)
    printf("Trying for 192.168.1.%d...\n", host);

  int sock = socket(AF_INET, SOCK_STREAM, 0);

  if (fcntl(sock, F_SETFL,O_NONBLOCK) != 0)
    sendErr("fcntl nonblock");

  struct sockaddr_in sin = { 0 };

  sin.sin_addr.s_addr = htonl(0xC0a80100 + host); /* 192.168.1. */
  sin.sin_port = htons(PORT);
  sin.sin_family = AF_INET; /////AF_UNSPEC;     // any IPv*

  errno = 0;

  int r = connect(sock, (struct sockaddr*) &sin, sizeof(sin));

  if ((r < 0) && (errno != EINPROGRESS)) {
    close(sock);
    if (Debug)
      printf("cannot connect to 192.168.1.%d\n", host);
    return 0;
  }

  if (sock > *highersock)
    *highersock = sock;

  FD_SET(sock, fdset);
  return sock;
}

int findHost(int maxhost, int npar)
{
  int host = 1;

  puts("Searching for a server...");

  while (host <= maxhost) {
    fd_set rset;
    int highersock = 0;
    int i = 0, nsocks = 0;
    int socks[npar];    /* socks under connection or 0 */
    int hosts[npar];    /* the next host to check */

    FD_ZERO(&rset);

    /* establish socket list */
    do {
      int sock;

      if ((sock = do_connect(host, &highersock, &rset)) != 0) {
        socks[i] = sock;
        hosts[i++] = host;
        nsocks += 1;
      }
      host += 1;
    }  while ((i != npar) && (host <= maxhost));

    /* check connects */
    while (nsocks)  {
      fd_set rset2 = rset, wset2 = rset;
      struct timeval timeout;
      int r, j;

      timeout.tv_sec = 1;
      timeout.tv_usec = 0;
      r = select(highersock+1, &rset2, &wset2, NULL, &timeout);

      if (r < 0)
        sendErr("select");

      if (r == 0) {
        /* timeout, close all */
        for (j = 0; j != i; ++j) {
          if (socks[j])
            close(socks[j]);
        }
        break;
      }

      for (j = 0; j != i; ++j) {
        int sock = socks[j];

        if (FD_ISSET(sock, &rset2) || FD_ISSET(sock, &wset2)) {
          socklen_t len = sizeof(r);

          socks[j] = 0;
          FD_CLR(sock, &rset);
          nsocks -= 1;

          if ((getsockopt(sock, SOL_SOCKET, SO_ERROR, &r, &len) < 0) || r) {
            if (Debug)
              printf("cannot connect to 192.168.1.%d\n", hosts[j]);
            close(sock);
          }
          else {
            if (Debug)
              printf("connected to 192.168.1.%d\n", hosts[j]);

            /* close other sockets */
            for (j = 0; j != i; ++j) {
              if (socks[j] && (socks[j] != sock))
                close(socks[j]);
            }

            MySock = sock;

            /* put socket in blocking mode */
            int flags = fcntl(MySock, F_GETFL, 0);

            if (fcntl(MySock, F_SETFL, flags ^ O_NONBLOCK) < 0)
              sendErr("fcntl set non blocking");

            alarm(OFF);
            return SUCCESS;
          }
        }
      }
    }
  }

  return FAIL;
}

//
void sendErr(char *msg)
{
    perror(msg);
    exit(1);
}

Остальная часть вашей программы неизменна, обратите внимание на chat вы отправляете массив фиксированного размера, поэтому он может содержать неинициализированные байты.

...