2016-09-21 2 views
0

Я использую сокеты для синхронизации нескольких удаленных процессов.Подключение к разъему отказалось из-за всплеска соединений

Идея заключается в том, что процесс создает PTHREAD, который управляет на стороне сервера, так же, как что:

void *listener(void * in) { 
    int sockfd; 
    socklen_t clilen; 
    struct sockaddr_in serv_addr, cli_addr; 
    int n = *((int *) in); 

    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (sockfd < 0) 
     error("ERROR opening socket"); 

    int option = 1; 
    setsockopt(sockfd, SOL_SOCKET, (SO_REUSEPORT | SO_REUSEADDR), (char*) &option, sizeof (option)); 
    bzero((char *) &serv_addr, sizeof (serv_addr)); 
    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_addr.s_addr = INADDR_ANY; 
    serv_addr.sin_port = htons(PORT); 

    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) 
     error("ERROR on binding"); 

    if (listen(sockfd, n) < 0) 
     error("ERROR when listening"); 

    clilen = sizeof (cli_addr); 
    int cnt = 0; 
    while (cnt < n) { 
     int newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); 
     if (newsockfd < 0) { 
      error("ERROR on accept"); 
     } 
     cnt++; 
    } 
    close(sockfd); 
    return 0; 
} 

В то же время, будет выполнять другие процессы:

int sockfd; 
struct sockaddr_in serv_addr; 
struct hostent *server; 

sockfd = socket(AF_INET, SOCK_STREAM, 0); 
if (sockfd < 0) 
    error("ERROR opening socket"); 

server = gethostbyname(_managementHost); //managementHost); 
if (server == NULL) 
    error("ERROR, no such host\n"); 

bzero((char *) &serv_addr, sizeof (serv_addr)); 
serv_addr.sin_family = AF_INET; 
bcopy((char *) server->h_addr, (char *) &serv_addr.sin_addr.s_addr, server->h_length); 
serv_addr.sin_port = htons(PORT); 

if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) 
    error("ERROR connection"); 

close(sockfd); 

Теперь проблема я есть, когда у меня есть много процессов, пытающихся подключиться одновременно к серверу, некоторые из них бросают соединение отказано ошибок.

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

Может ли кто-нибудь пролить свет на вопрос?

Возможное решение, которое возникает для меня, заключается в создании потока для каждого принятия, но я бы предпочел избежать его.

спасибо.

EDIT: исправлена ​​двойная инициализация сокета на сервере. Благодаря @Remy Lebeau.

+0

Я не думаю, что хорошо понимаю, что вы пытаетесь сделать. Что должно быть достигнуто путем принятия соединений, а затем их утечки? Как происходит любая синхронизация? Или вы вырезали некоторые важные биты, которые питают ваши задачи синхронизации и не-ресурса? –

+0

Идея состоит в том, что первый процесс будет ждать 'pthread_join', пока другие не достигнут заданной точки. Я использую только сокеты для их синхронизации, мне не интересно передавать процессы. – siserte

ответ

1

Теперь проблема заключается в том, что у меня есть много процессов, пытающихся подключиться одновременно к серверу, некоторые из них бросают соединение с отказавшимися ошибками.

У прослушивающего сокета TCP есть отставание от ожидающих соединений. Второй параметр listen() указывает, сколько подключений разрешено находиться в очереди хранения до их принятия. Если новый клиент пытается подключиться при заполнении резервной копии, клиент получает отказ. Клиенту или серверу ничего не поделаешь. Клиент обязан обнаруживать ошибку и повторно подключаться позднее.

Ваш listener() принимает клиентов, пока не достигнет определенного количества соединений, но вы также используете тот же номер для размера очереди прослушивания. Количество активных соединений и количество ожидающих соединений - это две разные вещи. Если вы ожидаете, что многие клиенты будут подключаться одновременно, вам понадобится большой размер задержек, чтобы избежать ошибок отказа. Но это отставание должно быть пропорционально трафику, который вы ожидаете. Если у вас 1000 клиентов, но они подключаются только по 20 за раз, вы должны установить отставание, скажем, 25, а не 1000.

У вашего listener() есть некоторые другие логические ошибки. Он вызывает socket() дважды и сохраняет два сокета в одну и ту же переменную sockfd, поэтому она пропускает первый сокет. Вам нужно удалить второй звонок до socket() (тот, который был непосредственно перед setsockopt()). Вы также просачиваете сокеты, которые возвращает accept(). После того, как вы это сделаете, вам понадобится close().

+0

Итак, несмотря на то, что процесс подключается, и 'accept()' еще не был выпущен, соединение с клиентом останется в отставании, верно? Что касается ошибок, вы правы, у меня слишком много вызовов 'socket()'. Тем не менее, я не могу закрыть сокет после 'accept()', потому что у меня только один сокет открыт (это только один поток, который выполняет 'listener()'. Должен ли я создать поток для каждого 'accept()'? – siserte

+0

@SergioIserte yes, соединение остается в отставании до тех пор, пока не будет удалено с помощью 'accept()'. Если вы намерены одновременно обслуживать несколько клиентов, вам нужно будет создать новый поток/процесс для каждого принятого клиента (не для вызова 'accept()' самостоятельно) или иным образом мультиплексировать несколько клиентов в потоке (например, чтобы блокировать сокеты, а затем использовать 'select()'/'epoll()' для управления ими), поэтому вы можете вернуться к 'accept()' регулярно. –

+0

Извините, я не уверен, что вы имеете в виду с _accepted client_. То, что я упоминал, заключалось в создании потоков 'n', каждый из которых вызывал' accept() '. Какая у вас точка? для вашего времени. – siserte

0

Просто сделайте свой сервер одновременным, вызвав fork, чтобы порождать ребенка для каждого клиента. Самый простой способ сделать это, ИМО. Избегайте потоковой передачи и прекратите отказ в подключении.

РЕДАКТИРОВАТЬ: Вы также можете изучить предварительный просмотр вашего сервера. Вам придется исследовать, как вы хотите справиться с блокировкой вокруг принятия, хотя (если вы вообще блокируете).

+0

Я бы предпочел избежать появления новых процессов, если это возможно ... – siserte

Смежные вопросы