Сокет программирования Client Connect

Я работаю с клиент-серверным программированием. Я ссылаюсь на эту ссылку, и мой сервер успешно работает.

  1. Мне нужно постоянно отправлять данные на сервер.
  2. Я не хочу подключаться () каждый раз перед отправкой каждого пакета. Итак, впервые я просто создал сокет и отправил первый пакет, остальные данные я просто использовал функцию write() для записи данных в сокет.

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

Есть ли способ, с помощью которого я могу создать сокет только сразу и непрерывно отправлять данные, зная о сбое сервера?

Основная причина для этого заключается в том, что на стороне сервера я использую модем GPRS, и каждый раз при вызове функции connect() для каждого пакета модем зависает.

Для создания сокета я использовал приведенный ниже код

Gprs_sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (Gprs_sockfd < 0)
{
  Display("ERROR opening socket");
  return 0;
}
server = gethostbyname((const char*)ip_address);
if (server == NULL)
{               
  Display("ERROR, no such host");                
  return 0;
}

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(portno);
if (connect(Gprs_sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
{
  Display("ERROR connecting");
  return 0;
}

И каждый раз, когда я пишу в сокет, используя приведенный ниже код

n = write(Gprs_sockfd,data,length);
if(n<0)
{
  Display("ERROR writing to socket");
  return 0;
}   

Заранее спасибо.............

2 ответа

Решение

TCP был разработан, чтобы терпеть временные сбои. Он выполняет последовательность байтов, подтверждения и, при необходимости, повторную передачу. Все неподтвержденные данные хранятся в сетевом стеке ядра. Если я правильно помню, по умолчанию используется три попытки повторной передачи (кто-то поправит меня, если я ошибаюсь) с экспоненциальными таймаутами задержки. Это быстро составляет десятки секунд, если не минут.

Мое предложение будет заключаться в том, чтобы включить в ваш протокол подтверждения на уровне приложения, то есть сервер отправит короткий ответ, сообщающий, что он получал столько данных до сих пор, скажем, каждую секунду. Если клиент не получает suck ack в течение, скажем, 3 секунд, клиент знает, что соединение непригодно для использования, и может закрыть его. Кстати, это проще сделать с помощью неблокирующих сокетов и таких функций опроса, как select(2) или же poll(2),

Изменить 0:

Я думаю, что это было бы очень уместно здесь - "конечная страница SO_LINGER или: почему мой tcp ненадежен".

Николай здесь прав, поведение, которое вы здесь испытываете, является желательным, поскольку в принципе вы можете продолжить передачу данных после отключения сети без какой-либо логики в вашем приложении. Если ваше приложение должно обнаруживать сбои дольше указанного промежутка времени, вам нужно добавить пульс в ваш протокол. Это стандартный способ решения проблемы. Это также может позволить вам обнаружить ситуацию, когда с сетью все в порядке, приемник жив, но он заблокирован (из-за программной ошибки).

Как говорил Николай, сердцебиение может быть таким простым - отправка небольшого пакета каждые X секунд; если сервер не может увидеть пакет в течение N*X секунд, соединение будет разорвано.

Другие вопросы по тегам