Monitor stdin and the socket using select to avoid blocking on either one.
fd_set read_fds;
    FD_ZERO(&read_fds);
    FD_SET(sock_fd, &read_fds);
    FD_SET(STDIN_FILENO, &read_fds);


    // Read input from the user and send it to the server. Echo any output
    // received from the server.
    while (1) {

// Read from server
        if (FD_ISSET(sock_fd, &read_fds)) {
            num_read = read(sock_fd, buf, BUF_SIZE);
        }
// Read from stdin
        if (FD_ISSET(STDIN_FILENO, &read_fds)) {
            num_read = read(STDIN_FILENO, buf, BUF_SIZE);
        }

        if (num_read == 0) {
            break;
        }
        buf[num_read] = '\0';

        /*
         * We should really send "\r\n" too, so the server can identify partial
         * reads, but you are not required to handle partial reads in this lab.
         */


        if (write(sock_fd, buf, num_read) != num_read) {
            perror("client: write");
            close(sock_fd);
            exit(1);
        }

        num_read = read(sock_fd, buf, sizeof(buf) - 1);
        if (num_read == 0) {
            break;
        }
        buf[num_read] = '\0';
        printf("[Server] %s", buf);
    }

    close(sock_fd);
    return 0;
