Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Сети > Ограничение на количество открытых сокетов


Автор: alltouch 7.6.2006, 13:43
Мне нужно загрузить прогой много страниц(примерно 1000)
1. Какое ограничение на количество открытых сокетов существует в винде и линухе???
2. Я гружу каждую страницу в отдельном потоке (в винде с помощью библиотеки winsock, под линухом - обычными сокетами), когда поток работает больше 5 секунд я его вырубаю. Закрывается при этом сокет или нет?? если нет то как ево закрыть в этом случае??????? 

Автор: Dian 7.6.2006, 14:25
Закрывается через closesocket;
Адресное пространство портов 0001-FFFF, скорее всего реальный предел будет  меньше, но на пару тысяч хватит
 

Автор: alltouch 13.6.2006, 10:01
а все таки можно какую-то примерную цыфру ограничения на количество одновременно открытых сокетов узнать???? 

Автор: deniska 13.6.2006, 10:15
так возьми проверь. если у тебя уже есть код для открывания 1000 страниц открой 2, 3, 4 тысячи пока все не грохнется smile  я думаю число сокетов ограничено 
Цитата

0001-FFFF
 и свободными ресурсами системы (в винде по крайней мере) с линухом не знаком 

Автор: p0s0l 13.6.2006, 11:55
Загляни сюда:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Здесь есть такие параметры:
TcpTimedWaitDelay - время, когда соединение после разрыва находится в состоянии TIME_WAIT. В это время нельзя снова установить соединение между этой же парой сокетов. Имеет значение, если очень часто открываешь-закрываешь соединения с одними и теми же хостами.

TcpNumConnections - макс. количество одновременно открытых TCP соединений. По умолчанию ограничение 16 млн с копейками.

MaxUserPort - максимально доступный открываемый № порта, по умолчанию 5000. 

Если у тебя грузится всего 1000 страниц, то этих ограничений должно по идее хватить с запасом... 

Я лишь однажды с толкнулся с ограниченим, на работе - на одном компе стоял ФТП-сервер, а другой комп часто обновлял на нем инфу, по ФТП заливал кучу файлов... Бывали моменты когда комп начинал глючить, т.к. ФТП-сервер держал очень много TIME_WAIT соединений...

Ссылки:
http://support.microsoft.com/kb/314053/
http://support.microsoft.com/?id=196271
 

Автор: alltouch 13.6.2006, 13:27
У меня такая вот проблема, когда я гружу страницы через сокеты, то через определенное время(скоре всего после n-того открытого сокета) все остальные сокеты просто висят(в моем случае оставалось открытых пару штук) и сами завершаться не хотят, что в этом случае делать???? 

Автор: ptr 18.6.2006, 08:59
Для закрытия активного соединения используются две функции shutdown и closesocket. closesocket - экстренное закрытие сокета, при этом соединение разрывается сразу. После вызова closesocket сокет будет уже недоступен. Чтобы корректно инициировать закрытие сокета, нужно вызвать shutdown, а потом closesocket. При этом будут переданы все неотправленные данные и получены еще не принятые данные и сокет не будет висеть. 

Автор: alltouch 21.6.2006, 12:50
Не все так просто, сокеты я открываю в потоках, если поток успевает завершится за 5 секунд тогда сокет сам закрывается, если же нет, то я снимаю поток, при этом в деструкторе сокета прописано чтоб он его сам завершал автоматически...
Но это не помогает бо все равно потом прога висит, чего-то ждет, чего именно я пока не знаю 

Автор: ptr 21.6.2006, 16:21
Так у тебя прога висит или сокеты? Кстати неплохо было бы видеть текст проги. 

Автор: alltouch 22.6.2006, 10:07
скорее всего высят сокеты, бо прога ничего не делает пока не завершаться все сокеты

P.S. Код очень большой, какой кусок имеено выложить????? 

Автор: ptr 22.6.2006, 11:04
Лучше всего конечно весь, но если он такой большой, то ту часть, в которой непосредственно с сокетами работаешь.

И долго твоя прога висит? Может просто она закрывает все открытые сокеты (ты же не один и не два сокета открываешь). 

Автор: alltouch 23.6.2006, 10:10
Каждый сокет открывается в отдельном потоке, диспечер пзадач показывал что в моей проге было запущено 4 потока(2 главных и два на сокетах)!!!

Вот мой класс для работы с сокетами:
Код

    class a_socket //объявление класса
    {
        public:
            a_socket(string needle_method, string needle_url, bool use_proxy, string proxy);
            ~a_socket();
            string get_content();
            int get_socket_data();
        private:
            string host, port, page, method, content, proxy_ip, proxy_port;
            bool is_set_proxy;
#ifdef WINDOWS
            SOCKET sock;  //Об"являем идентификатор сокета
#else
            int sock;     //Об"являем идентификатор сокета
#endif
    };

    a_socket::a_socket(string needle_method, string needle_url, bool use_proxy, string proxy) //конструктор
    {
        method=needle_method;  //needle_method

        string temp_string=needle_url;  //needle_url
        if(temp_string.substr(0,7).compare("http://")==0) temp_string=temp_string.substr(7);
        if(temp_string.find('/')==-1)
        {
            host=temp_string;
            page="/";
        }
        else
        {
            host=temp_string.substr(0,temp_string.find('/'));
            page=temp_string.substr(temp_string.find('/'));
        }
        if(host.find(':')==-1) port="80";
        else 
        {
            port=host.substr(host.find(':')+1);
            if(port.compare("")==0) port="80";
            host=host.substr(0,host.find(':'));
        }
        
        is_set_proxy=use_proxy; //proxy
        if(is_set_proxy)
        {
            if(proxy.find(':')==-1)
            {
                proxy_ip=proxy;
                proxy_port="80";
            }
            else
            {
                proxy_ip=proxy.substr(0,proxy.find(':'));
                proxy_port=proxy.substr(proxy.find(':')+1);
                if(proxy_port.compare("")==0) port="80";
            }
            if(inet_addr(&proxy_ip[0])==-1) is_set_proxy=FALSE;
        }
        
        content=""; //content
    }

    a_socket::~a_socket()
    {
        if(sock)
        {
            shutdown(sock, 0x02);
#ifdef WINDOWS
            closesocket(sock);
#else
            close(sock);
#endif
        }
    }

    string a_socket::get_content()
    {
        return content;
    }

    int a_socket::get_socket_data()
    {
        sockaddr_in server_addr;    // структура для адреса
        string send_text="";
        if(is_set_proxy)
        {
            if( ( server_addr.sin_addr.s_addr =inet_addr(proxy_ip.c_str()))==(-1))  // проверим, возможно host содержит просто ip
            {
                // нет, адрес не есть ip, тогда возможно это dns адрес
                hostent* server_host;
                server_host=gethostbyname(proxy_ip.c_str());
                if(server_host==NULL)
                {
                    return 1;  //ошибка, не возможно определить айпи-адрес сайта
                }
                memcpy(&server_addr.sin_addr.s_addr, server_host->h_addr_list[0], server_host->h_length);  //присваиваем айпишник
            }
            server_addr.sin_family = AF_INET;  //указываем что будем использовать айпишники
            server_addr.sin_port =  htons(atoi(proxy_port.c_str()));   //переводим порт в правильный вид
            if((sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)   //создаем сокет
            {
                return 2;   //ошибка, не возможно приконектиться
            }
            if( connect( sock, (sockaddr *)&server_addr, sizeof(server_addr)) != 0)  //соединяемся
            {
                return 3;  //ошибка, не возможно соединиться с хостом
            }  
            send_text=method+" http://"+host+page+" HTTP/1.0\r\n"+
                     +"Host: "+host+"\r\n"+
                     +"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.1) Gecko/20060111 Firefox/1.5.0.1\r\n"+
                     +"Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n"+
                     +"Accept-Language: en-us,en;q=0.8\r\n"+
                     +"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"+
                     +"Referer: http://"+host+"\r\n"+
                     +"Connection: close\r\n\r\n";
        }
        else
        {
            if( ( server_addr.sin_addr.s_addr =inet_addr(host.c_str()))==(-1))  // проверим, возможно host содержит просто ip
            {
                // нет, адрес не есть ip, тогда возможно это dns адрес
                hostent* server_host;
                server_host=gethostbyname(host.c_str());
                if(server_host==NULL)
                {
                    return 1;  //ошибка, не возможно определить айпи-адрес сайта
                }
                memcpy(&server_addr.sin_addr.s_addr, server_host->h_addr_list[0], server_host->h_length);  //присваиваем айпишник
            }
            server_addr.sin_family = AF_INET;  //указываем что будм использовать айпишники
            server_addr.sin_port =  htons(atoi(port.c_str()));   //переводим порт в правильный вид
            if((sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)   //создаем сокет
            {
                return 2;   //ошибка, не возможно приконектиться
            }
            if( connect( sock, (sockaddr *)&server_addr, sizeof(server_addr)) != 0)  //соединяемся
            {
                return 3;  //ошибка, не возможно соединиться с хостом
            }
            send_text=method+" "+page+" HTTP/1.0\r\n"+
                     +"Host: "+host+"\r\n"+
                     +"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.1) Gecko/20060111 Firefox/1.5.0.1\r\n"+
                     +"Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n"+
                     +"Accept-Language: en-us,en;q=0.8\r\n"+
                     +"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"+
                     +"Referer: http://"+host+"\r\n"+
                     +"Connection: close\r\n\r\n";
        }
        send(sock, send_text.c_str(), send_text.length(), 0);  //посылаем запрос
        char receive_buf[DEF_BUF_SIZE+5];   //буфер для приема
        int receive_buf_len = recv(sock, receive_buf, DEF_BUF_SIZE, 0);
        while(receive_buf_len>0)
        {
            receive_buf[receive_buf_len]='\0';
            content.append(receive_buf);
            receive_buf_len = recv( sock, receive_buf, DEF_BUF_SIZE, 0);
        }
        shutdown(sock, 0x02);
#ifdef WINDOWS
        closesocket(sock);
#else
        close(sock);
#endif
        return 0;
    }


Использую я его потом так:
Код

a_socket sock("GET",url, use_proxy, proxy);    
sock.get_socket_data();
string page=sock.get_content();

 

Автор: ptr 23.6.2006, 14:01
1. Ты пытаешься два раза закрыть сокет. Первый раз в конце get_socket_data(), второй раз в деструкторе. Тогда в get_socket_data нужно ещё делать sock=0.
Допустим в твоём коде:

a_socket sock("GET",url, use_proxy, proxy);     
sock.get_socket_data(); 
string page=sock.get_content(); 

всё отработало правильно, тогда в get_socket_data() вызовется close (closesocket)+shutdown, а потом в деструкторе ещё раз вызовется close (closesocket), поскольку будет sock!=0.

2. Зачем вообще нужно два раза закрывать сокет. Закрывай его либо в самой функции, либо в деструкторе.

Ну это, пожалуй на первый взгляд, и всё.   

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)