C++ Переподключение TCP-сервера к клиенту после перезапуска клиента
Я хочу реализовать "гибкое" TCP-соединение, при котором я могу произвольно завершить работу и перезапустить как Сервер, так и Клиент. Другой должен автоматически обнаружить выключение и ввести попытку повторного подключения. Я успешно реализовал эту я могу выключить и перезапустить сервер. Клиент обнаруживает выключение (через recv(...) == 0
) и затем закрывает соединение (поэтому закрывает сокеты close(this->sockfd_)
а также close(this->newsockfd_)
).
К сожалению, я не могу заставить это работать наоборот. Я инициализирую сервер (используя конструктор класса) следующим образом:
tcpServer::tcpServer(int _port) {
this->sockfd_ = -1;
this->port_ = _port;
this->connected_ = false;
if ((this->sockfd_ = socket(AF_INET, SOCK_STREAM, 0)) < 0)
this->dieWithError("ERROR opening Socket");
else
printf("-> Port %d: Socket opened\n", this->port_);
// get rid of "address already in use" error message
int yes = 1;
setsockopt(this->sockfd_, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
/* assign values to the fields of struct sockaddr_in */
bzero((char *) &this->serv_addr_, sizeof(this->serv_addr_));
this->serv_addr_.sin_family = AF_INET;
this->serv_addr_.sin_port = htons(this->port_);
this->serv_addr_.sin_addr.s_addr = INADDR_ANY;
/* bind the socket to an address */
if (bind(this->sockfd_, (struct sockaddr *) &this->serv_addr_, sizeof(this->serv_addr_)) < 0) {
printf("-> Port %d:", this->port_);
this->dieWithError("ERROR on binding");
}
printf("-> Binding successful. Start TCP client in new terminal\n");
fflush(stdout);
/* listen for connections and accept a connection */
listen(this->sockfd_, 5);
this->clilen_ = sizeof(this->cli_addr_);
if ((this->newsockfd_ = accept(this->sockfd_, (struct sockaddr *) &this->cli_addr_, &this->clilen_)) < 0)
this->dieWithError("Error on accept");
else {
printf("-> Connection established\n");
this->connected_ = true;
}
}
Поэтому, когда сервер обнаруживает, что соединение закрыто, он входит в цикл, где он пытается восстановить соединение, используя следующий код:
void tcpServer::connect() {
if (this->sockfd_ == -1) {
/* create socket */
if ((this->sockfd_ = socket(AF_INET, SOCK_STREAM, 0)) < 0)
this->dieWithError("ERROR opening Socket");
else
printf("-> Port %d: Socket opened\n", this->port_);
// get rid of "address already in use" error message
int reuse_address = 1;
setsockopt(this->sockfd_, SOL_SOCKET, SO_REUSEADDR, &reuse_address, sizeof(int));
/* listen for connections and accept a connection */
listen(this->sockfd_, 5);
this->clilen_ = sizeof(this->cli_addr_);
if ((this->newsockfd_ = accept(this->sockfd_, (struct sockaddr *) &this->cli_addr_, &this->clilen_)) < 0)
this->dieWithError("Error on accept");
else {
printf("-> Connection established\n");
this->connected_ = true;
}
}
}
Некоторые простые выходные данные отладки говорят мне, что в режиме повторного подключения сервер застревает в accept(this->sockfd_, (struct sockaddr *) &this->cli_addr_, &this->clilen_)
вызов. Еще одно наблюдение, которое я сделал, заключается в том, что клиент не выключается должным образом (через ctrl-c
), то есть он где-то застревает в цикле и неправильно закрывает соединение.
Поскольку я новичок в работе с TCP, я был бы очень рад, если бы кто-то указал мне верное направление. Спасибо.