C - fopen (+priklad)
Robert Vojta
vojta na ipex.cz
Neděle Červenec 30 17:59:04 CEST 2000
# ako sa da v C pod linuxom otvorit subor(vyslednu stranku) z napr. z takehoto
Zdravim,
nejdrive se zamyslete na co to potrebujete, jestli neni vhodnejsi pouzit
neco jiz hotoveho jako je treba wget (man wget) nebo pouzit jiny jednodussi
nastroj, jako je treba Perl (i kdyz ho moc nemusim ;-). Pokud potrebujete
tuto stranku analyzovat a neco s ni dal delat, spis bych vam doporucil pouzit
Perl, ale to je uz na vas.
Pokud si to opravdu potrebujete napsat sam, staci vam na to nasledujici
funkce: socket, connect, read, write, close (u vsech lze pouzit man). Ukazka
je castecne vytazena z knihy UNIX Network Programmin od Stevense (doporucuji).
Nebo existuje i ceska kniha napriklad UNIX POSIX PLAN 9 od pana Skocovskeho kde
je toto vse take krasne popsano a mnohem vice.
Dale k tomu potrebujete znalost HTTP protokolu, nevzpomenu si na cislo RFC
dokumentu, ale naprosto postacujici popis naleznete v knize PHP od pana Koska
a to primo na strane 435.
Nyni k samotne ukazce, zde je oquotovana ukazka jak toto muzete udelat v C.
Pokud ji vyjmete z mailu, muze prekompilovat a bude vam to chodit.
<EXAMPLE>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define SERV_TCP_PORT 80
#define SERV_HOST_ADDR "194.45.127.81" /* <- www.buyersguidechem.de */
char *GETrequest = "GET /cgi-bin/BGlief.idc?pn=7356 HTTP/1.1\nHost: www.buyersguidechem.de\n\n";
/* podle HTTP protokolu je za pozadavkem prazdny radek, proto \n\n */
/* zapis n bytu do socketu, resp. posli n bytu serveru */
int writen(register int fd, register char *ptr, register int nbytes) {
int nleft, nwritten;
nleft = nbytes;
while (nleft > 0) {
nwritten = write(fd,ptr,nleft);
if (nwritten <= 0) return (nwritten);
nleft -= nwritten;
ptr += nwritten;
}
return (nbytes-nleft);
}
/* funkce nacte vami zadany dokument */
void getURL(int sockfd) {
char buffer[BUFFER_SIZE], *screen;
int readn, headerGone = 0;
/* posli pozadavek a zjisti, jestli je OK */
if (writen(sockfd,GETrequest,strlen(GETrequest)) != strlen(GETrequest)) {
fprintf(stderr,"error during posting request\n");
close(sockfd);
exit(1);
}
/* cti odpoved ... */
readn = read(sockfd,buffer,BUFFER_SIZE-1);
buffer[readn] = '\0';
/* ... zjisti prvni reakci, je kladna odpoved? */
if ((char *)strstr((const char*)buffer,(const char *)"HTTP/1.1 200 OK") ==
(char *)buffer) {
/* cti dokud ti neco posila */
while (readn > 0) {
/* tato promenna zjistuje, zda uz sme za hlavickou nebo ne, zase */
/* prazdny radek \n\n nebo \r\n\r\n */
if (headerGone == 0) {
/* nejsme za hlavickou, hledej prazdny radek */
screen = (char *)strstr((const char*)buffer,(const char *)"\n\n");
if (screen == NULL) {
/* nenasel? zkus windozi konce radku */
screen = (char *)strstr((const char*)buffer,(const char *)"\r\n\r\n");
/* nasel? preskoc prazdny radek */
if (screen != NULL) { screen += 4; }
} else {
/* nasel unixovy prazdny radek, preskoc ho */
screen += 2;
}
/* nasel ten radek? pokud ano, tak vypis vse za nim z bufferu */
if (screen != NULL) {
printf("%s",screen);
/* a nastav, ze je hlavicka za nama */
headerGone = 1;
}
} else {
/* hlavicka je za nama, vypis cely buffer, je to to co chceme */
printf("%s",buffer);
}
/* pokus se nacist dalsi data */
readn = read(sockfd,buffer,BUFFER_SIZE-1);
buffer[readn] = '\0';
}
} else {
/* nevratila se odpoved HTTP/1.1 200 OK, vypis chybu a odpoved serveru */
screen = (char *)strstr(buffer,"\n"); *screen = '\0';
fprintf(stderr,"error received: %s\n",buffer);
exit(1);
}
}
int main(int argc, char *argv[]) {
int sockfd;
struct sockaddr_in serv_addr;
/* priprav strukturu na spojeni ze serverem na urcity port */
bzero((char *)&serv_addr,sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(SERV_HOST_ADDR);
serv_addr.sin_port = htons(SERV_TCP_PORT);
/* vytvor socket a vrat jeho deskriptor */
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
fprintf(stderr,"can't open stream socket\n");
return 1;
}
/* inicializuj spojeni socketu, proste navaz spojeni */
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0) {
fprintf(stderr,"can't connect to the server\n");
return 1;
}
/* zavolej nasi funkci */
getURL(sockfd);
/* zavri socket z zmiz */
close(sockfd);
return 0;
}
</EXAMPLE>
--
Robert Vojta aka Penguin (Oo.oO) // ICQ 64746424 // Phone 0608-170783
http://www.(ipex|gin).cz/ mailto: vojta@(ipex|gin).cz
GCS d? s+: a-- C++ SL++++ P+ L++++ E--- W+ N+ K w--- O- M- V-
PS+ PE Y+ PGP++ t 5? X R tv- b+++ DI? D G+ e+ h-- r++ x?
Další informace o konferenci Linux