Добрый день. Относительно недавно начал программировать под unix, опыта пока малова-то, поэтому, требуется помощь. Пишу простенький ftp клиент и пока что запнулся на следующем. Когда программа просто прогоняется всё выполняется корректно. Под отладчиком (работаю в SUSE 10.3 KDevelop) он после строчки fdopen и fclose иногда писал Cannot access memory 0x0
а иногда 0xfffffff причём появляются ошибки нерегулярно=(( Под suse 11 которая у меня дома такого вообще не происходит и никакие ошибки не вылазят. Если что-то где-то можно написать красивее и грамотнее было бы здорово услышать предложения=)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <cctype>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <iostream>
using namespace std;
#define MAX_SLEEP_CONNECT 128
bool connect_retry(int &sock, const struct sockaddr *addr, socklen_t len);
struct addrinfo* GetFtpAddr(const char *host);
int ReturnSimpleRequest(int &sock, string* text);
bool connect_retry(int &sock, const struct sockaddr *addr, socklen_t len)
{
if ((sock = socket(addr->sa_family, SOCK_STREAM, 0)) < 0)
return false;
int nsec = 0;
/*
* Пытаемся установить соединение с экспоненциальной задержкой
*/
for (nsec = 1; nsec <= MAX_SLEEP_CONNECT; nsec <<=1)
{
if (connect(sock, addr, len) == 0)
{
return true;
}
if (nsec <= MAX_SLEEP_CONNECT/2)
sleep(nsec);
}
return false;
}
struct addrinfo* GetFtpAddr(const char *host)
{
/*
Функция возвращает адрес хоста по имени.(Адрес структуру addrinfo)
Причём первый из его адресов.
*/
int err = 0;
struct addrinfo address, hint, *spisok, *next;
struct addrinfo *sinp = NULL;
address.ai_flags = AI_CANONNAME;
address.ai_family = 0;
address.ai_socktype = 0;
address.ai_protocol = 0;
address.ai_addrlen = 0;
address.ai_canonname = NULL;
address.ai_addr = NULL;
address.ai_next = NULL;
if ((err = getaddrinfo("ftp.freebsd.org", "ftp", &address, &spisok)) !=0 )
printf("Err getaddrinfo: %s\n\n", gai_strerror(err));
// Мы возвращаем первый же адресс который встречаем.
for (next = spisok; next != NULL; next=next->ai_next)
{
if (next->ai_family == AF_INET)
{
sinp = next;
break;
}
}
/*
По идее здесь должнен освобождать память выделенную под адреса
,тоесть freeaddrinfo(spisok); но почему-то я не знаю как это и где удобнее сделать.
*/
return sinp;
}
int main(int argc, char *argv[])
{
int socket_ftp;
int err = 0;
const char *ad;
char abuf[INET_ADDRSTRLEN];
struct addrinfo *address = GetFtpAddr(argv[1]);
if (address!=NULL)
{
struct sockaddr_in *sinp = (struct sockaddr_in *)address->ai_addr;
ad = inet_ntop(AF_INET, &sinp->sin_addr, abuf, INET_ADDRSTRLEN);
printf("Адрес %s ", ad?ad:"не известен");
printf("Порт %d", ntohs(sinp->sin_port));
printf("\n");
}
if (!connect_retry(socket_ftp, address->ai_addr, address->ai_addrlen))
{
printf("\nНе успешно");
exit(1);
}
string str = "error";
int n = ReturnSimpleRequest(socket_ftp, &str);
printf("Code: %d\n", n);
close(socket_ftp);
exit(0);
}
int ReturnSimpleRequest(int &sock, string *text)
{
#define BUFLEN 100
if (sock >0)
{
const char c = 'r';
char buf[BUFLEN];
char ccode[3];
int code;
FILE* socket_fd = NULL;
if ((socket_fd = fdopen(sock, &c)) != NULL);
{
fgets(buf, 100, socket_fd);
if (text!=NULL)
{
text->clear();
text->append(buf);
printf("%s",text->c_str());
}
else
printf("%s", buf);
fclose(socket_fd);
if (isdigit(buf[0]) && isdigit(buf[1]) && isdigit(buf[2]))
return atoi(strncpy (ccode,buf,5));
}
}
return -1;
}