Не удается выполнить повторное подключение Sock STREAM к серверу, пока сервер не запустился?


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

Вот в чем проблема :

сервер не запустился : клиент ждет 3 секунды, затем делает еще один запрос connect ().

когда я запускаю сервер : клиент все еще пытается подключиться каждые 3 второй.

Сообщение об ошибке при запуске клиентской программы:

$./client localhost
Cannot connect to the server. Retrying...: Connection refused 
Cannot connect to the server. Retrying...: Invalid argument 
Cannot connect to the server. Retrying...: Invalid argument
...

Вот код клиента:

#include <stdio.h>
#include <sys/types.h>
#include <netdb.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#define SERVER_PORT "9734"
#define WAIT_SERVER_TIME 3
int main(int argc, char* argv[]){
    if(argc<2){
        printf("usage: %s MACHINE_NAMEn",argv[0]); 
        exit(EXIT_SUCCESS);
    }else{
        int client_socket_fd = 0 ;
        struct addrinfo hints,*results;
        /* Get the address info of the server to be connected */
        memset(&hints,0,sizeof hints);
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_STREAM;
        if( getaddrinfo(argv[1],SERVER_PORT,&hints,&results) !=0){
            printf("Cannot recognize the given server name");
            exit(EXIT_FAILURE);
        }
        /* Create the client socket */
        if((client_socket_fd = socket( AF_INET, SOCK_STREAM, 0))<0){
            perror("Cannot create the client socket.");
            exit(EXIT_FAILURE);
        }
        if(results->ai_addr == NULL){
            perror("Cannot find the given server name.");
            exit(EXIT_FAILURE);
        }
        /* Set up the connection */
        while(connect(client_socket_fd,results->ai_addr, 
                    results->ai_addrlen) < 0 ){
            perror("Cannot connect to the server. Retrying...");
            sleep(WAIT_SERVER_TIME);
        }
        printf("Successfully connected to the server.n");
        // DO STUFFS HERE
        exit(EXIT_SUCCESS);
     }
}

Вот код сервера для тестирования:

#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <signal.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <ifaddrs.h>
int main(int argc, char* argv[]){

    /* SERVER SET UP */
    int enable_reuse_socket = 1;
    struct sockaddr_in server_address;
    socklen_t server_address_len=0;
    int server_socket_fd ;

    server_socket_fd = socket( AF_INET, SOCK_STREAM, 0);
    // Handle error creating a socket
    if( server_socket_fd < 0){
        perror("Cannot initialize the socket for connection.");
        exit( EXIT_FAILURE);
    }

    // Set up the INET address
    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr= htonl(INADDR_ANY);
    server_address.sin_port = htons(SERVER_PORT);
    server_address_len = sizeof( server_address);
    // Bind the socket to the given address
    if(setsockopt(server_socket_fd,SOL_SOCKET,SO_REUSEADDR,&enable_reuse_socket
                ,sizeof(int))<0){
        perror("Fail to reuse socket.");
    }
    if(bind(server_socket_fd,(struct sockaddr*) &server_address,
                server_address_len) !=0){
        perror("Cannot bind the socket to the given address.");
        exit(EXIT_FAILURE);
    }
    // Allow the socket to listen to the clients
    if(listen(server_socket_fd, MAX_CLIENT)!=0){
        perror("Cannot allow the socket to listen to incoming client 
                messages");
        exit(EXIT_FAILURE);
    }
    struct sockaddr_in client_addr;
    socklen_t client_addr_len;
    while(1){
         int client_fd = accept(server_socket_fd,(struct sockaddr*)&client_addr,
            &client_addr_len);
         printf("Gotcha!");
    }
}
2 3

2 ответа:

Некоторые реализации сокета оставляют сокет в несогласованном состоянии после сбоя connect(). Попробуйте что-нибудь вроде этого:

int client_socket_fd = 0 ;
struct addrinfo hints,*results;
/* Get the address info of the server to be connected */
memset(&hints,0,sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
if( getaddrinfo(argv[1],SERVER_PORT,&hints,&results) !=0){
    printf("Cannot recognize the given server name");
    exit(EXIT_FAILURE);
}
if(results->ai_addr == NULL){
    perror("Cannot find the given server name.");
    exit(EXIT_FAILURE);
}
/* Set up the connection */
while(1) {
    /* Create the client socket */
    if((client_socket_fd = socket( AF_INET, SOCK_STREAM, 0))<0){
        perror("Cannot create the client socket.");
        exit(EXIT_FAILURE);
    }

    if (connect(client_socket_fd,results->ai_addr, 
            results->ai_addrlen) == 0 ) {
        break;
    }

    perror("Cannot connect to the server. Retrying...\n");
    close(client_socket_fd);
    sleep(WAIT_SERVER_TIME);
}
printf("Successfully connected to the server.\n");

Вы также можете сделать так, чтобы ваш клиент следовал за вами. Это не использование getaddrinfo ().

    #include"sock_header.h"
    #include<string.h>
    #define MAXLEN 20
    #define SERVER_PORT "9734"
    #define WAIT_SERVER_TIME 3

    int main(int argc, char **argv)
    {   
        struct sockaddr_in server_sock;
        int ret, sockfd;
        int connect_failed = 1;

        while(connect_failed == 1)
        {
            if((sockfd = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
            {
                return -1;
            }

            bzero(&server_sock, sizeof(server_sock));
            server_sock.sin_family = AF_INET;
            server_sock.sin_port = htons(SERVER_PORT);
            inet_pton(AF_INET, argv[1], &server_sock.sin_addr);

            if(Connect(sockfd, (struct sockaddr *)& server_sock, sizeof(server_sock)) == -1)
            {
                Close(sockfd);
                goto close_sock;
            }

            connect_failed = 0;

            char writeline[MAXLEN];
            char readline[MAXLEN];
            int len ;
            char * buf;

            buf = (char *) malloc(sizeof(char)*strlen(argv[1]));    

            Writen(sockfd, buf, strlen(buf));

        close_sock:
            close(sockfd);

            sleep(WAIT_SERVER_TIME);
        }

        return 0;
    }