LINUX.ORG.RU

Работа из сокетами


0

1

Здравствуйте. Стоит задача, написать в линукс программу: некий http клиент который устанавливает соединение из http сервером и периодически посылает туда запросы POST, GET. Работает через сокет. Столкнулся с проблемой, - после отправки одного запроса сервер закрывает соединение, следующие попытки что-нибудь считать из соекта ни к чему не приводят, то есть послал запрос в сокет считал ответ и все сервер на своей стороне закрыл соединение, что б работать дальше нужно закрывать сокет и открывать опять. Вопрос можно как та обойти ето? Хидеры «Keep-Alive: 300\r\n» «Connection: keep-alive\r\n»"

не помогают. :(.

Обязательно писать всё самому? Мб проще готовое взять? libcurl там, или в Qt посмотри

TERRANZ ★★★★ ()
Ответ на: комментарий от Reset

int init_connect(const char* url) { struct addrinfo hints, *addr; struct sockaddr_in *addrInfo; errors = NO_ERROR; load_host_info(url); int rc; int sock; memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_ADDRCONFIG; if( (rc = getaddrinfo(hostInfo.host, NULL, &hints, &addr)) ) { //fprintf(stderr, «Can't find host name: %s, Error:%s\n», hostInfo.host, gai_strerror(rc)); errors = CANT_FIND_HOSTNAME; return 0; } addrInfo = (struct sockaddr_in *) addr->ai_addr; if( (sock = socket(addrInfo->sin_family, addr->ai_socktype, addr->ai_protocol)) < 0 ) { //fprintf(stderr, «Can't create socket to host name: %s, Error:%s\n», hostInfo.host, gai_strerror(rc)); errors = CANT_CRETE_SOCKET; return 0; } addrInfo->sin_port= htons(80); int bOptVal = 1; int bOptLen = sizeof(int); setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &bOptVal, bOptLen); if( connect(sock, (struct sockaddr *) addrInfo, addr->ai_addrlen) ) { //fprintf(stderr, «Can't connect to host name: %s, Error:%s\n», hostInfo.host, gai_strerror(rc)); errors = CANT_CONNECT_TO_HOST; return 0; } freeaddrinfo(addr); return sock; }

char* connector_get(int socket_fd) { char* header = getHeader(); char* request = (char*)malloc( sizeof(char) * strlen(header) * strlen(hostInfo.host) * 4 * strlen(hostInfo.url)); sprintf( request, header, «GET»,hostInfo.url,hostInfo.host); printf(«Request: %s\n», request); ssize_t number_characters_read; //write (socket_fd, request, strlen(request)); send (socket_fd, request, strlen(request),0); int bufSize = 500; if( response != NULL ) { free(response); } response = malloc( sizeof(char) *(bufSize + 1)); //number_characters_read = read(socket_fd, response, bufSize); number_characters_read = recv(socket_fd, response, bufSize,0); if( number_characters_read == 0 ) { strcpy(response, «EMPTY»); return response; } response[number_characters_read+1]='\0'; free(request); return response; }

char* getHeader() { return «%s %s HTTP/1.1\r\n» «Host: %s\r\n» «Accept: text/html\r\n» «Accept: */*\r\n» «Keep-Alive: 300\r\n» «Connection: keep-alive\r\n» «User-Agent: Mozilla/5.0 (X11; U; Linux i686; ru; rv:1.9.0.8) Gecko/2009032600 SUSE/3.0.8-1.1.1 Firefox/3.0.8\r\n\r\n»;     }

Не работает SO_KEEPALIVE, может я что то там пропустил? Готовое решение не подходит, клиент должен работать в без Х-ов, занимать как можно меньше места и не требовать дополнительных библиотек, curl не подходит так как он при новом запросе создает новый конекшын, клиент часто отсылает запросы, создаются много конекшинов, и в результате отрубиваетса фаерволом (

suse_qt ()
Ответ на: комментарий от suse_qt

int init_connect(const char* url)
{
struct addrinfo hints, *addr;
struct sockaddr_in *addrInfo;

errors = NO_ERROR;

load_host_info(url);

int rc;
int sock;

memset(&hints, 0, sizeof(hints));

hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_ADDRCONFIG;

if( (rc = getaddrinfo(hostInfo.host, NULL, &hints, &addr)) ) {
//fprintf(stderr, «Can't find host name: %s, Error:%s\n», hostInfo.host, gai_strerror(rc));
errors = CANT_FIND_HOSTNAME;
return 0;
}


addrInfo = (struct sockaddr_in *) addr->ai_addr;

if( (sock = socket(addrInfo->sin_family, addr->ai_socktype, addr->ai_protocol)) < 0 ) {
//fprintf(stderr, «Can't create socket to host name: %s, Error:%s\n», hostInfo.host, gai_strerror(rc));
errors = CANT_CRETE_SOCKET;
return 0;
}

addrInfo->sin_port= htons(80);

int bOptVal = 1;
int bOptLen = sizeof(int);
setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &bOptVal, bOptLen);

if( connect(sock, (struct sockaddr *) addrInfo, addr->ai_addrlen) ) {
//fprintf(stderr, «Can't connect to host name: %s, Error:%s\n», hostInfo.host, gai_strerror(rc));
errors = CANT_CONNECT_TO_HOST;
return 0;
}

freeaddrinfo(addr);

return sock;
}

char* connector_get(int socket_fd)
{
char* header = getHeader();

char* request = (char*)malloc( sizeof(char) * strlen(header) * strlen(hostInfo.host) * 4 * strlen(hostInfo.url));

sprintf( request, header, «GET»,hostInfo.url,hostInfo.host);

printf(«Request: %s\n», request);

ssize_t number_characters_read;

//write (socket_fd, request, strlen(request));
send (socket_fd, request, strlen(request),0);

int bufSize = 500;

if( response != NULL ) {
free(response);
}

response = malloc( sizeof(char) *(bufSize + 1));

//number_characters_read = read(socket_fd, response, bufSize);
number_characters_read = recv(socket_fd, response, bufSize,0);
if( number_characters_read == 0 ) {
strcpy(response, «EMPTY»);
return response;
}

response[number_characters_read+1]='\0';

free(request);

return response;
}

char* getHeader()
{
return «%s %s HTTP/1.1\r\n»
«Host: %s\r\n»
«Accept: text/html\r\n»
«Accept: */*\r\n»
«Keep-Alive: 300\r\n»
«Connection: keep-alive\r\n»
«User-Agent: Mozilla/5.0 (X11; U; Linux i686; ru; rv:1.9.0.8) Gecko/2009032600 SUSE/3.0.8-1.1.1 Firefox/3.0.8\r\n\r\n»;
   
}

suse_qt ()

считать из соекта ни к чему не приводят

в смысле сокет готов на чтение а данных оттуда 0? Это значит удалённая сторона закрыла соединение. man read, man recv

true_admin ★★★★★ ()
Ответ на: комментарий от Reset

Данные отсылаются но результат 0. И чем код ужасен, можно конкретние? Просто давно писал на С :).

По 500 потому что тестовый код, цель - узнать работает ли это )). Сейчас использую курл, проблемы из фаерволом решаются увеличением числа допустимых конекшинов, или разрешением IP. Но это плохое решение. :(

suse_qt ()
Ответ на: комментарий от suse_qt

И чем код ужасен, можно конкретние?

Слишком низкоуровнево, слишком много херни из-за которой программа будет падать. Нет обработки ошибок, неправильная работа с массивами.

Reset ★★★★★ ()
Ответ на: комментарий от Reset

насколько я знаю возвращается столько сколь есть,( есть 400 возвращает 400, есть 5 возвращает 5, есть 600 возвращает 500 ). Сейчас при посылке двух GET -ов от первого recv возвращает > 0 от второго приходит О.

suse_qt ()
Ответ на: комментарий от suse_qt

Потому что надо прочитать всё что есть перед тем как отправлять следующий запрос. А для этого надо распарсить content-length.

Reset ★★★★★ ()
Ответ на: комментарий от suse_qt

SO_KEEPALIVE ни на что не влияет, проблема в другом. Где-то либо что-то не дочитано, либо наоборот. Можно для начала отладиться в telnet, чтобы убедиться, что заголовки http правильные.

Reset ★★★★★ ()
Ответ на: комментарий от suse_qt

curl не подходит так как он при новом запросе создает новый конекшын, клиент часто отсылает запросы, создаются много конекшинов, и в результате отрубиваетса фаерволом

Естественно, если ты пошлешь на обработку _одновременно_ 100 запросов, libcurl 100 соединений и создаст, т.к. будет пытаться обработать их параллельно. Очередь запросов нужно поддерживать самому и не давать libcurl одновременно работать больше чем с выбранным лимитом _одновременных_ соединений. Грубо говоря: послали 4 запроса, ждем, как один запрос выполнился, посылаем следующий. При этом существующие соединения закрываться не будут и весь профит от Keep-Alive будет налицо.

Deleted ()
Ответ на: комментарий от Deleted

Одновременно не посылается. Посылка запроса, ожидание ответа, считывание, обработка, посылка нового, да, забыл сказать сама софтина (если можно так назвать)написана на пхп и соответственно использует курл разширение к пхп.

suse_qt ()
Ответ на: комментарий от suse_qt

Значит ты сам где-то говоришь curl'у закрыть соединение, либо curl расширение к пыху криво написано.

Reset ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.