С сокетами только начал разбираться, и возникла проблема, что клиент иногда не загружает полностью запрошенную Web-страницу. Код примерно такой: Код (Text): #include <sys/socket.h> #include <sys/types.h> #include <sys/un.h> #include <unistd.h> #include <stdio.h> #include <netinet/in.h> #include <netdb.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #define HOSTNAME "philka.ru" int ret = 0, count = 0; int sock = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in addr; memset(&addr, 0, sizeof(struct sockaddr)); addr.sin_family = AF_INET; addr.sin_port = htons(80); struct hostent *resaddrs=gethostbyname(HOSTNAME); if (resaddrs==NULL) { //Address resolution error printf("address not found\n"); } addr.sin_addr = *(in_addr*)resaddrs->h_addr_list[0]; ret = connect(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr)); if (ret==-1) { //error creating connecting printf("Connect() error\n"); return -1; } char buf[10000]; sprintf(buf, "%s%s%s%s%s%s%s%s", "GET /news.php HTTP/1.1\x0d\x0a", "Accept: */*\x0d\x0a", "Accept-Language: ru\x0d\x0a", "Accept-Encoding: gzip, deflate\x0d\x0a", "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)\x0d\x0a" "Host: ", HOSTNAME, "\x0d\x0a", "Connection: Keep-Alive\x0d\x0a\x0d\x0a" ); printf(buf); //Что мы отправляем count = write(sock, buf, strlen(buf)); printf("\n%i bytes were written", count); while(1) { //читаем пока есть что читать (Web-сервер может возвращать данные по кускам, в несколько приемов) count = read(sock, buf, 10000); if (count==0) return 0; printf(buf); } В результате - в консоли печатается только часть текста, хотя счетчики count в сумме дают значения поля заголовка Content-Length, Wireshark показывает, что HTML код передается полностью. Почему он не считывается из буфера до конца? Такое случается со многими сайтами ОС Linux, gcc, оболочка xterm
и еще, количество выводимой в консоль информации зависит от значения поля Connection: Keep-Alive или Close. Почему так? Спасибо
Код (Text): count = read(sock, buf, 10000); if (count==0) return 0; printf(buf); count может быть равен нулю, если выполнение read было прервано сигналом. Правильно будет так: Код (Text): while (count > 0) { do { count = read (sock, buf, sizeof (buf) - 1); } while (count < 0 && errno == EINTR); if (count < 0) { perror ("read"); exit (1); } if (count > 0) { buf[count] = '\0'; printf (buf); } }
эхм. код вроде правильный, а вот утверждение что если errno == EINTR то count == 0 неверно. count < 0 в случае прерывания сигналом. Кстати твой код будет делать что-то странное в этом случае.
r90 Большое спасибо за ответ, а нету функций "безопасных" относительно других сигналов? напрмер, блокирующие другие сигналы на время своего исполнения? Или не реагирующие таким образом? Кстати, почему разработчики решили зделать возврат 0, вместо того чтобы продолжить чтение? А в Windows нужно предусматривать такую ситуацию?
Вот странно, теперь вызов read() блокируется, прочитав почти весь файл - кроме последней строки. Хотя с вашим вариантом читает намного больше, чем в моем случае
я в си не понимэ, но разве это: Код (Text): .... printf("\n%i bytes were written", count); while(1) {... правильно? )
а что за read/write, не проще заюзать send/recv или это не windows?) я бы сделал так: Код (Text): while ( rcv = recv( Socket, RecvBuffer + recved, 256, 0 ) ) { recved += rcv; } RecvBuffer[recved] = '\0'; ну и нужно учесть что буффера выделенного тобою для скачки страницы может не хватить. и еще тут: Код (Text): while(1) { //читаем пока есть что читать (Web-сервер может возвращать данные по кускам, в несколько приемов) count = read(sock, buf, 10000); if (count==0) return 0; printf(buf); } после printf, надо бы буффер мемсетом зачистить)
simnet_ Вероятно из-за: Connection: Keep-Alive. Выдери из ответа сервера Content-Length, считай принятые байты и не читай больше чем надо прочитать.