Не удается выполнить повторное подключение 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 ответа:
Некоторые реализации сокета оставляют сокет в несогласованном состоянии после сбоя
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; }