Здравствуйте, помогите пожалуйста, голову уже сломал Нужно из списка доменов грабить главные странички, страничек много и делать надо все быстро поэтому приложение многопоточное. Если обращаться к серверам через 1 поток, то все в порядке. Но при более одного потока при запросе на recv приходит очень много лишнего, то есть при сохрании ответа сервера получается страница и еще часть этой страници... не понимаю почему так происходит. Код (Text): string message = "GET / HTTP/1.0\r\nHost:"+domain+" \r\n\r\n\r\n"; апрос формируется нормально pthread_mutex_lock ( &mutex); мьютексы от отчаяния включены, помоему они здесь не в кассу. char text[1500]; буфер для приема char * request=&message[0]; тк send берет char* перевод сообщения. //cout<<request<<endl; для проверки send(sock, request, strlen(request), 0); посылаем запрос int nsize; string page; text[0]=0; тоже от отчаяние обнуление буфера nsize = recv(sock,text,sizeof(text) -1,0); получаем первую часть page=page+text; if (check_page(page)) проверка кода ответа (200 300 301) { domain=create_folder(domain); создается чтото типа файловой базы данных char * ch; domain+="index.html"; ch=&domain[0]; ofstream out(ch,ios::out); поток ввода в файл out<<text; кидаем первую часть в файл text[0]=0; while (((nsize = recv(sock,text,sizeof(text) -1,0)))!=0) получаем ответ и сохраняем его пока не получем 0 от сервера { out<<text; text[0]=0; } close(sock); pthread_mutex_unlock ( &mutex) ; } Вот такая вот проблема. Не знаю в чем загвоздка по идее сервер долже присылать только один раз аждый пакет потом recv возвращать 0 . но все работает нормально если в одном патоке. Помогите плз!
а ты не пробовал создавать для каждого потока отдельный сокет? иначе, имхо, с синхронизацией жуткие запарки будут
сокет у каждого потока свой естественно, опять же ради перестрахивки дескрипторы раздаются при лоченом мьютексе...
Код (Text): while (1) все это находитсся в потоковой функции { string domain; int sock; pthread_mutex_lock ( &mutex); sock = socket(AF_INET, SOCK_STREAM, 0); раздача сокета на всякий случай при мьютексе pthread_mutex_unlock ( &mutex) ; if (!domainStack.empty()) в стеке хранятся имена { pthread_mutex_lock ( &mutex); domain=domainStack.top(); //cout<<sock<<" "<<domain<<endl; поток берет одно имя. каждый пото берет разное проверял domainStack.pop(); pthread_mutex_unlock ( &mutex) ; struct sockaddr_in addr; if(sock < 0) проверка создания (всегда ок) { cout<<"error create socket"<<endl; totaler++; continue; } addr.sin_family = AF_INET; addr.sin_port = htons(80); hostent *d_addr; char * st= &domain[0]; d_addr = gethostbyname (st); if (d_addr==NULL) собственно, проверка существования днс { close(sock); totaler++; continue; } addr.sin_addr.s_addr = *((unsigned long *) d_addr->h_addr); if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { totaler++; close(sock); continue; } else { а здесь идет предыдущая часть кода мистика........ блин, а я так надеялся что я гдето ошибся..... Доп.Инфо: При изменении размера буфера text дабавочные лишние куски меняются. Каким должен быть буфер? Может решение здесь?
Для примера пирведу что выдает Например для сайта ya.ru выдает весть код страницы + еще часть примерно от половины до конца... То есть повторение второго пакета... ингда больше чем одно повторение. П.Сэто при одном запросе и чтении в цикле....
Код (Text): text[0]=0; nsize = 0; while (((nsize += recv(sock, text, sizeof(text) -1, 0))) != 0) { text[nsize] = '\0'; out<<text; text[0]=0; } ?
Нужно только цикл переделать, чтобы nsize обновлялось и проверялось условие Вроде этого: Код (Text): nrecvd = 0; nsize = 0; while (1) { nrecvd = recv(sock, &text[nsize], sizeof(text) - nsize -1, 0)); if (nrecvd == 0) { text[nsize] = '\0'; out bla-bla; break; } nsize += nrecvd; }
ну да nsize это код ответа. он ДОЛЖЕН возврящать 0 если сервер закрыл соединение. но что то хдесь не так и 0 возвращаетсяя (тк файл всетаки сохраняется) позже 1. Файл сохраняется => сервер отвечает о закрытии соединения. 2 Буфер обнуляется после кажого ответа 3. Сокет каждвм потоком получается свой( проверенно и невозможно вследствии закрытого мьютекса при получении сокета) 4. Сервер должен по протоколу HTTP 1.0 посылать не разнопотоковый а поток из последовательных сообщений. 5. Приходит несколько последних пакетов.............. ПОЧЕМУ?
??? понятия не имею о чем ты говоришь)) Пробывал смотреть что приходит только через cout там тоже дубли причем при одинаковом буфере одинаковые. Обьясни плз как и где смотреть через tcpdump(или Ethereal) сорри за нубскость, но я реально с этим не сталкивася никогда)
Так... почитал вопрос на форуме "Длинна HTTP сообщения?" обьясниете ктонибудь если я в запросе пишу connectin:close мне присылается один пакет или се покеты до конца? может в этом загвоздка?
Почитай мануал к tcpdump, и с ним смотри что и куда делает твоя прога. Примерно вот так: tcpdump -i 3 -n -nn -s 512 port 80 Но это под Win, в *nix параметры могут немного отличаться, в первую очередь именем интерфейса. Сделай ifconfig и посмотри как у тебя называется интерфейс, через который ты в интернет выходишь (к примеру, eth0 для Linux или rl0 - для FreeBSD), а потом делай tcpdump -i eth0 -n -nn -s 512 port 80 Подробнее читай мануал (man tcpdump или на opennet.ru сходи, там, кажется, есть русский) [added] Параметр пролюбил. tcpdump -i eth0 -n -nn -X -s 512 port 80
Проблема исправлена nester7 спасибо На интерфейс приходило все нормально, вся загвоздка заключалась в том что буфер text накапливал куски, и когда приходил последний кусок в буфере (даже при его обнулении, чего кстати не происходило) содержался кусок конца предыдущей части. Обнуление не проходит пробывал text[0]='\0'; chat text=new text[1024]; единственное что помогло это уменьшение буфера до 20 (причем программа стала значительно шустрее и ручное обнуление text[0]='\0'; text[1]='\0'; text[2]='\0'; и тд Может кто обьяснит как его обнулить? Зарание благодарен Всем спасибо за ответы)
Где-то бага, его не нужно полностью обнулять Но можно тупо - перед циклом получения занулить буфер целиком через memset(buf, 0, size).
Вот так должно работать: Код (Text): while (((nsize = recv(sock,text,sizeof(text) -1,0)))!=0) { text[nsize] = 0; out<<text; }
Огромное спасибо, извиняюсь уезжал надолго ( жил без нета 6 дней!))) ) А представленный код не работает ( и кстате не правильный) memset не пробывал еще но думаю и без него обойдусь. Еще раз спасибо
Вообще то нелохо было бы обрабатывать код ошибки от recv, потому как при этом данный код ведет себя сильно некорретно.