Reputation: 79
I have a client connected to the server (TCP connection). In the case when server crashes (I disconnect it) my client needs to be connected to another server, in order to continue service. But when the first server comes back, I need to reconnect client to it again.
I was able to connect my client to the back up server after the first server crashes, but I have a problem with reconnecting my client to the first server. I made a function create_newconnect()
for reconnecting to the server, but it doesn't work (that is why I'm not calling it in the code)
I tried to simplify my program as much as I could, so it wouldn't be to big
This is a client side
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
#include <string.h>
#include <arpa/inet.h>
#include <time.h>
#define SIZE sizeof(struct sockaddr_in)
struct sockaddr_in server;
void tcp_protocol();//execute client tcp protocol
void server_check();
void tcp();
void create_newconnect();
int main (int argc, char *argv[])
{
int portno;
//Test for correct number of arguments
if (argc != 3)
{
fprintf(stderr, "Usage: %s Port# IP Address \n", argv[0]);
exit(1);
}
portno = atoi(argv[1]);//convert port # to int
server.sin_family = AF_INET;
server.sin_port = htons(portno);
server.sin_addr.s_addr = inet_addr(argv[2]);//use client ip address
tcp();//call tcp function
return 0;
}
void tcp()
{
int sockfd;
char c ;
//create socket
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0))==-1)
{
perror ("socket call faild");
exit (1);
}
//connect to the server
if (connect (sockfd, (struct sockaddr *)&server, SIZE)==-1)
{
perror ("connect call faild");
exit (1);
}
while(1)
{
printf("Enter char\n");
scanf("%c",&c);
server_check(sockfd);
//send packet to server
if (send(sockfd, &c, sizeof(c),0)<0)
{
printf("error sending\n");
}
//if packet is received from server
if(recv(sockfd, &c, sizeof(c),0)>0)
{
printf("server's respond %c\n", c);//print result
}
}
close(sockfd);
}
void server_check(int sock)
{
char b ='b';
//send packet to server
if (send(sock, &b, sizeof(b),0)<0)
printf("error sending\n");
//if packet is received from server
if((recv(sock, &b, sizeof(b),0)>0))
{
printf("server responded\n");
}
else//if server is not responding
{
printf("server crashed\n");
close(sock);//close socket
server.sin_port = htons(5002);
server.sin_addr.s_addr = inet_addr("127.0.0.1");
tcp();//create new connection
}
}
void create_newconnect()
{
int newsockfd;
server.sin_port = htons(5001);
//create socket
if ((newsockfd = socket(AF_INET, SOCK_STREAM, 0))==-1)
{
perror ("socket call faild");
exit (1);
}
//connect to the server
if (connect (newsockfd, (struct sockaddr *)&server, SIZE)==-1)
{
perror ("connect call faild");
exit (1);
}
tcp();//call function to execute tcp protocol
}
Upvotes: 6
Views: 1073
Reputation: 3654
Your program recursively calls tcp()
after reconnecting. This is almost certainly not correct and will result in resource (mainly stack) use on each disconnection.
You need to avoid having the code pass the socket file descriptor (sockfd) by value to the functions as it will change after each new connection.
As a general principle, you can have a list of (two or more) hosts in order of preference. Then, at all times attempt to create connections to those that have higher preference than the one you currently have a connection to. Then, when a connection is established, close all the other open sessions, and switch to the new preferred connection.
Keep this encapsulated and have it return the current active sockfd for use by all the other functions.
Upvotes: 0
Reputation: 73294
I think the first thing you're going to have to consider is: after your first server has crashed and your client has successfully reconnected to the backup server, how would your client ever know that that the first server has come back on line?
I can think of two possibilities: one might be that the backup server might notify the client about the re-appearance of the primary server (e.g. by sending some sort of PRIMARY_SERVER_ONLINE message over the TCP connection, or perhaps simply by closing the TCP connection, with the expectation that that would cause the client to try to connect to the primary server again).
The other approach would be to make your client smart enough that it can periodically (e.g. once per minute) try to reconnect to the primary server even while it is using the TCP connection to the backup server. That is doable, but not with a single thread and blocking I/O like your posted code has... (because if your program is blocked in a recv() call, there is no way for it to do anything else like try to connect a TCP connection). You'd need to either use non-blocking I/O and select() (or similar), or asynchronous I/O, or multiple threads, in order to do it properly.
Upvotes: 6