崩溃后恢复与服务器的连接

时间:2013-11-23 02:19:04

标签: c sockets networking tcp

我有一个连接到服务器的客户端(TCP连接)。在服务器崩溃(我断开连接)的情况下,我的客户端需要连接到另一台服务器,以便继续服务。但是当第一台服务器回来时,我需要再次将客户端重新连接到它。 在第一台服务器崩溃后,我能够将我的客户端连接到备份服务器,但是我将客户端重新连接到第一台服务器时出现问题。我创建了一个函数create_newconnect()来重新连接到服务器,但它不起作用(这就是为什么我不在代码中调用它) 我试图尽可能地简化我的程序,所以它不会很大 这是客户端

#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

 }

2 个答案:

答案 0 :(得分:6)

我认为您首先需要考虑的是:在您的第一台服务器崩溃并且您的客户端已成功重新连接到备份服务器之后,您的客户端将如何知道第一台服务器已重新启动线?

我可以想到两种可能性:一种可能是备份服务器可能会通知客户端主服务器的重新出现(例如,通过TCP连接发送某种PRIMARY_SERVER_ONLINE消息,或者可能只是通过关闭TCP连接,期望这会导致客户端再次尝试连接到主服务器)。

另一种方法是让您的客户端足够智能,即使在使用TCP连接到备份服务器时,也可以定期(例如每分钟一次)尝试重新连接到主服务器。这是可行的,但不是单个线程和阻止I / O像你发布的代码有...(因为如果您的程序在recv()调用中被阻止,它没有办法做任何其他事情,如尝试连接TCP连接)。您需要使用非阻塞I / O和select()(或类似),或异步I / O或多个线程,才能正确执行。

答案 1 :(得分:0)

您的程序在重新连接后以递归方式调用tcp()。这几乎肯定是不正确的,并且会导致每次断开连接时使用资源(主要是堆栈)。

您需要避免让代码按值传递套接字文件描述符(sockfd),因为它会在每次新连接后更改。

作为一般原则,您可以按优先顺序列出(两个或更多)主机。然后,始终尝试创建与具有比您当前连接的优先级更高的优先级的连接。然后,建立连接后,关闭所有其他打开的会话,并切换到新的首选连接。

保持此封装并让它返回当前活动的sockfd以供所有其他功能使用。