Сокет программирования Client Connect
Я работаю с клиент-серверным программированием. Я ссылаюсь на эту ссылку, и мой сервер успешно работает.
- Мне нужно постоянно отправлять данные на сервер.
- Я не хочу подключаться () каждый раз перед отправкой каждого пакета. Итак, впервые я просто создал сокет и отправил первый пакет, остальные данные я просто использовал функцию 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 секунд, соединение будет разорвано.