Не удается подключиться к серверу с несколькими клиентами в Minix, но можно в Ubuntu - PullRequest
0 голосов
/ 30 апреля 2019

Я делаю сервер-клиент для Minix, который должен работать на одном экземпляре, у меня будет сервер, клиент и бот, работающие одновременно.

Как я могу заставить их одновременно подключаться на одном компьютере?

Когда я запускаю сервер в Ubuntu, он работает нормально, когда я перемещаю его на Minix, один из клиентов может подключиться, а другой (который в будущем станет ботом) не может.

Код сервера

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#define PORT 4950
#define BUFSIZE 1024

void send_to_all(int j, int i, int sockfd, int nbytes_recvd, char *recv_buf, fd_set *master)
{
    if (FD_ISSET(j, master)){
        if (j != sockfd && j != i) {
            if (send(j, recv_buf, nbytes_recvd, 0) == -1) {
                perror("send");
            }
        }
    }
}

void send_recv(int i, fd_set *master, int sockfd, int fdmax)
{
    int nbytes_recvd, j;
    char recv_buf[BUFSIZE], buf[BUFSIZE];

    if ((nbytes_recvd = recv(i, recv_buf, BUFSIZE, 0)) <= 0) {
        if (nbytes_recvd == 0) {
            printf("socket %d hung up\n", i);
        }else {
            perror("recv");
        }
        close(i);
        FD_CLR(i, master);
    }else { 
        for(j = 0; j <= fdmax; j++){
            send_to_all(j, i, sockfd, nbytes_recvd, recv_buf, master );
        }
    }   
}

void connection_accept(fd_set *master, int *fdmax, int sockfd, struct sockaddr_in *client_addr)
{
    socklen_t addrlen;
    int newsockfd;

    addrlen = sizeof(struct sockaddr_in);
    if((newsockfd = accept(sockfd, (struct sockaddr *)client_addr, &addrlen)) == -1) {
        perror("accept");
        exit(1);
    }else {
        FD_SET(newsockfd, master);
        if(newsockfd > *fdmax){
            *fdmax = newsockfd;
        }
        printf("new connection from %s on port %d \n",inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port));
    }
}

void connect_request(int *sockfd, struct sockaddr_in *my_addr)
{
    int yes = 1;

    if ((*sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("Socket");
        exit(1);
    }

    my_addr->sin_family = AF_INET;
    my_addr->sin_port = htons(PORT);
    my_addr->sin_addr.s_addr = INADDR_ANY;
    memset(my_addr->sin_zero, '\0', sizeof my_addr->sin_zero);

    if (setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
        perror("setsockopt");
        exit(1);
    }

    if (bind(*sockfd, (struct sockaddr *)my_addr, sizeof(struct sockaddr)) == -1) {
        perror("Unable to bind");
        exit(1);
    }
    if (listen(*sockfd, 10) == -1) {
        perror("listen");
        exit(1);
    }
    printf("\nWaiting for client on port %d\n", PORT);
    fflush(stdout);
}
int main()
{
    fd_set master;
    fd_set read_fds;
    int fdmax, i;
    int sockfd= 0;
    struct sockaddr_in my_addr, client_addr;

    FD_ZERO(&master);
    FD_ZERO(&read_fds);
    connect_request(&sockfd, &my_addr);
    FD_SET(sockfd, &master);

    fdmax = sockfd;
    while(1){
        read_fds = master;
        if(select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1){
            perror("select");
            exit(4);
        }

        for (i = 0; i <= fdmax; i++){
            if (FD_ISSET(i, &read_fds)){
                if (i == sockfd)
                    connection_accept(&master, &fdmax, sockfd, &client_addr);
                else
                    send_recv(i, &master, sockfd, fdmax);
            }
        }
    }
    return 0;
}

Код клиента

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>

#define PORT 4950
#define BUFSIZE 1024

void send_recv(int i, int sockfd)
{
    char send_buf[BUFSIZE];
    char recv_buf[BUFSIZE];
    int nbyte_recvd;

    if (i == 0){
        fgets(send_buf, BUFSIZE, stdin);
        if (strcmp(send_buf , "quit\n") == 0) {
            exit(0);
        }else
            send(sockfd, send_buf, strlen(send_buf), 0);
    }else {
        nbyte_recvd = recv(sockfd, recv_buf, BUFSIZE, 0);
        recv_buf[nbyte_recvd] = '\0';
        printf("%s\n" , recv_buf);
        fflush(stdout);
    }
}


void connect_request(int *sockfd, struct sockaddr_in *server_addr)
{
    if ((*sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("Socket");
        exit(1);
    }
    server_addr->sin_family = AF_INET;
    server_addr->sin_port = htons(PORT);
    server_addr->sin_addr.s_addr = inet_addr("127.0.0.1");
    memset(server_addr->sin_zero, '\0', sizeof server_addr->sin_zero);

    if(connect(*sockfd, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) == -1) {
        perror("connect");
        exit(1);
    }
}

int main()
{
    int sockfd, fdmax, i;
    struct sockaddr_in server_addr;
    fd_set master;
    fd_set read_fds;

    connect_request(&sockfd, &server_addr);
    FD_ZERO(&master);
    FD_ZERO(&read_fds);
    FD_SET(0, &master);
    FD_SET(sockfd, &master);
    fdmax = sockfd;

    while(1){
        read_fds = master;
        if(select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1){
            perror("select");
            exit(4);
        }

        for(i=0; i <= fdmax; i++ )
            if(FD_ISSET(i, &read_fds))
                send_recv(i, sockfd);
    }
    printf("client-disconnected\n");
    close(sockfd);
    return 0;
}

Вот изображение того, что происходит, когда я запускаю их

Я ожидаю, что оба клиента могут работать, один в фоновом режиме, другой на переднем плане, который будет основным входом, но в результате я пытаюсь запустить сервер с двумя клиентами, и подключается только один клиент, а другой возвращает сообщение об ошибке «Select: Bad file descriptor».

...