Bonjour,
Voila, mon code envoie une requete http a un serveur meteo (www.weather.Com), stocke une partie du code desiré dans un fichier, recupere ses infos, les trie et les affiche a l'ecran, c tout !
La ville choisie est Nimes, mais la liste est tres longue, j'ai mis cette ville car j'y habite, mettez la ville que vous voulez !
Source / Exemple :
#include <stdio.h>
#include <windows.h>
#include <winsock.h>///weather/local/FRXX0165
#pragma comment(lib, "ws2_32.lib")
enum {FAIL, SUCCESS};
#define NBRE_SEARCH 7
//Requete HTTP
char sCmdToSend[] = "GET http://fr.w3.weather.com/weather/local/FRXX0165 HTTP/1.1\r\nAccept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, */*\r\nAccept -Language: fr\r\nContent-Type: application/x-www-form-urlencoded\r\nAccept -Encoding: gzip , deflate\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt)\r\nHost: fr.w3.weather.com\r\nReferer : http://fr.w2.weather.com/common/jump2_fr.html?/weather/tenday/FRXX0004\r\n\r\n";
char sGood_Buffer[] = "<!-- Begin Main Content Here-->";
char sEnd_Buffer[] = "<TD COLSPAN=\"3\" ALIGN=\"CENTER\" VALIGN=\"middle\">";
//Balise entourant les commandes de 2 à 8
char sBalise_Deb[] = "<TD CLASS=\"currentObsText\">";
char sBalise_End[] = "</TD>";
//Balise entourant les 2premiers resultats (Temp et temp ressentie, Temp n'est pas dans la
//liste des cmd car elle ne figure pas dans la source de la page
char sBalise_FirstDeb[] = "\"TOP\"> ";
char sBalise_FirstEnd[] = "°C";
char sSearch[NBRE_SEARCH][30] = { "", //NUMERIQUE
"Temp. ressentie", //NUMERIQUE
"Vent", //NON NUMERIQUE (je sais pas comment le dire !!)
"Point de ros", //NUMERIQUE
"Humidit", //NUMERIQUE
"Visibilit", //NUMERIQUE
"Pression barom" }; //NON NUMERIQUE (en effet, les données a recuperer sont numeriques mais j'ai eu quelques difficultés à cause d'un 'à' recalcitrant...
char sCmdFound[NBRE_SEARCH][40];
char sFile[] = "c:\\fuck.htm";
int iInitWinsock(void);
int iTreatCmd();
int iRequete(SOCKET);
char *sSearchIn(char *, const char *, const char *, const char *, int, int);
int iIsNumeric(char);
//Initialisation de Winsock
int iInitWinsock()
{
WORD wVersionRequested;
WSADATA wsaData;
int iReturn = 0;
wVersionRequested = MAKEWORD(2, 0);
if (iReturn = WSAStartup(wVersionRequested, &wsaData)) {
printf("Erreur lors de l'initialisation de winsock...\n");
system("PAUSE");
return FAIL;
}
return SUCCESS;
}
int main(int argc, char **argv)
{
struct sockaddr_in sinAddr;
struct hostent *hstServIP; //Stocke l'IP du serveur
SOCKET sckActiv;
int iReturn = 0;
int i = 0, j = 0;
if (iReturn = iInitWinsock()) { //Initialisation de winsock
printf("Initialisation de winsock effectu\202e...\n");
}
sckActiv = socket(AF_INET, SOCK_STREAM, 0); //Creation du socket
if (!(hstServIP = gethostbyname("fr.w3.weather.com"))) { //Recuperation de l'addresse IP du serveur
printf("Erreur lors de la r\202solution du nom de domaine...\n");
system("PAUSE");
return FAIL;
}
sinAddr.sin_addr.s_addr = *((u_long *)hstServIP->h_addr_list[0]); //"Stockage" de l'adresse IP convertie en unsigned long (u_long)
sinAddr.sin_port = htons(80); //Port 80 = HTTP
sinAddr.sin_family = AF_INET; //AF_INET = Protocole TCP/IP
while (iReturn = connect(sckActiv, (const struct sockaddr *)&sinAddr, sizeof(sinAddr))) { //Connexion du socket au serveur
printf("Impossible de se connecter au serveur...\n");
}
printf("Connexion avec le serveur \202tablie...\n");
iRequete(sckActiv); //Envoi de la requetre HTTP et puis "stockage" d'une partie de la source dans un fichier
iTreatCmd(); //Traite les infos contenus le fichier et stocke ces infos dans sCmdFound
printf("M\202t\202o a N\214mes : \n");
for (i = 0; i < NBRE_SEARCH; ++i) {
switch (i) {
case 0:
sprintf(sSearch[i], "Temp\202rature : %s Degr\202s C" , sCmdFound[i]);
break;
case 1:
sprintf(sSearch[i], "Temp. ressentie : %s Degr\202s C", sCmdFound[i]);
break;
case 2:
sprintf(sSearch[i], "Vent : %s", sCmdFound[i]);
break;
case 3:
sprintf(sSearch[i], "Point de ros\202e : %s Degr\202s C", sCmdFound[i]);
break;
case 4:
sprintf(sSearch[i], "Humidit\202 : %s%%" , sCmdFound[i]);
break;
case 5:
sprintf(sSearch[i], "Visibilit\202 : %s km", sCmdFound[i]);
break;
case 6:
sprintf(sSearch[i], "Pression barom\202trique : %s", sCmdFound[i]);
break;
}
printf("%s\n", sSearch[i]);
}
closesocket(sckActiv); //Fermeture du socket que l'on peut preceder de la fonction shutdown, mais ce n'est pas obligatoire...shutdown permet de "mettre en veille" la socket
WSACleanup(); //Ferme Winsock
system("PAUSE");
return SUCCESS;
}
// <TD CLASS="currentObsText">....</TD>
int iRequete(SOCKET sckOpen)
{
FILE *fSave;
char sPacket[8192]; //8192octets = limite de la taille d'un packet
char *sBuffer = NULL; //Pointeur sur sPacket
char *sRet_Str = NULL; //Pointeur char pour retour fonction strstr
int iRecup_Buf = 0; //Flag indiquant si le prog soit stocker le packet (sPacket) dans le fichier
int iReturn = 0; //Nbre d'octets recus par la fonction recv
send(sckOpen, sCmdToSend, sizeof sCmdToSend, 0); //Envoie de la requete http
fSave = fopen(sFile, "w"); //Ouvre le fichier en mode ecriture
while (iReturn = recv(sckOpen, sPacket, sizeof sPacket, 0)) { //Tant ke recv n'est pas nul (donc kon recoit un packet)
sBuffer = sPacket; // sBuffer pointe maintenant sur sPacket
if (!iRecup_Buf) { // Si iRecup_Buf est nul
if (sRet_Str = strstr(sBuffer, sGood_Buffer)) { // Si dans le packet se trouve la "balise" sGood_Buffer (permettant de couper la source au nivo des infos interessantes)
iRecup_Buf = 1; // Mise a 1 du flag iRecup_Buf permettant de "dire" au prog kil doit recuperer les packets suivants
sBuffer = sRet_Str; // sBuffer pointe alors sur la balise sGood_Buffer (dont l'adresse a été renvoyée par strstr)
fputs(sBuffer, fSave); // Ecriture dans le fichier du packet
} // Fin si
} else { // Fin Si, Sinon (si iRecup_Buf n'est pas nul donc ke la balise de depart (sGood_Buffer) a été trouvé)
if (sRet_Str = strstr(sBuffer, sEnd_Buffer)) { // Si la balise de fin (sEnd_Buffer) est presente dans le packet
sRet_Str[0] = 0; // Mettre a zero le premier caractere de la chaine renvoyée par strstr permet de "couper la chaine" a la balise de fin (Pour ne conserver ke les infos necessaires)
iRecup_Buf = 0; // Mettre a zero iRecup_Buf pour signaler ke le prog ne doit plus recuperer de packet (ayant trouve le dernier)
} // Fin Si
fputs(sBuffer, fSave); // Peu importe que la balise de fin soit trouvée, il faut, si iRecup_Buf n'est pas nul, ecrire le packet dans le fichier
} // Fin Si
memset(sPacket, 0, sizeof sPacket); // Mettre zero tous les octets de sPacket
sBuffer = NULL; // sBuffer ne pointe plus sur rien
} //Fin while
fclose(fSave); //Fermer le fichier
return SUCCESS;
}
int iTreatCmd()
{
FILE *fCmd;
char *sLine = NULL;
char *sRet_Search = NULL;
char *sBalise_Dep = sBalise_FirstDeb; //On initialise le pointeur de Balise de depart avec sBalise_FirstDeb car les 2 premiers commandes a trouver debutent par cette balise
char *sBalise_Arr = sBalise_FirstEnd; //Et au final, sont finis par cette balise
int iReturn = 0;
int iNumeric = 1; //Valeur passée en argument de la fonction sSearchIn ki permet de dire le les infos a recuperer sont de type numerik
int i = 0;
sLine = calloc(4608, sizeof(char)); //Alloue 4608octets au pointeur sLine, et initialise tous les octets a 0
fCmd = fopen(sFile, "r"); //Ouvre le fichier en mode lecture
iReturn = fread(sLine, sizeof(char), 4608, fCmd); //Lis la totalité du fichier, iReturn renvoie le nombre d'octets lus
sLine[iReturn] = 0; //A l'élément iReturn, place le caractere de fin de chaine '\0' (ou 0)
for (i = 0; i < NBRE_SEARCH; ++i) { //Tant ke i est inferieur au nombre de commandes...
if (i == 1) { //Si i == commande("Temp. Ressentie")
sBalise_Dep = strtok(sBalise_Dep, "\"TOP\">"); // "Decouper" une partie de la balise sBalise_Dep car elle ne correspond pas a la balise de depart de cette commande
} else if (i == 2 || i == 6) { //Si i == commande("Vent" ou "Pression barométrique")
iNumeric = 0; // Mettre a 0 le flag iNumeric permettant de dire a la fonction sSearchIn que les infos a recuperer sont numerik
if (i == 2) { // Si et seulement si i == commande("Vent")
sBalise_Dep = sBalise_Deb; // Changer les balise de depart
sBalise_Arr = sBalise_End; // Et de fin
} // Fin Si
} else { //Fin Si, Sinon (si i != 1, 2 ou 6)
iNumeric = 1; // Mettre a 1 le flag iNumeric
} //Fin Si
if (sRet_Search = sSearchIn(sLine, sSearch[i], sBalise_Dep, sBalise_Arr, i, iNumeric)) { //Si la fonction sSearchIn renvoie un pointeur non NULL
sLine = sRet_Search; // Faire pointer sLine sur la valeur de retour de sSearchIn (ki a été "decoupé" dans cette fonction ce qui permet de reduire le champ de recherche d'une commande)
} //Fin Si
}
sRet_Search = NULL; //sRet_Search point sur du vent !
fclose(fCmd); //Fermer le fichier
//free(sLine);*/ //J'alloue de la memoire dinamikement, mais le free ne marche po, je pense ke c du au fait ke je le fais pointer sur d'autres donnée...
return SUCCESS;
}
char *sSearchIn(char *sIn, const char *sCmd, const char *sBalise_D, const char *sBalise_E, int iNum_Cmd, int IsNumeric)
{
char *sRet_Str = NULL;
char *sDeb_Str = NULL;
char *sFin_Str = NULL;
int i = 0;
if (sRet_Str = strstr(sIn, sCmd)) { //Cherche la commande dans le fichier
sIn = sRet_Str + strlen(sCmd); //sIn "saute" la commande
if (sDeb_Str = strstr(sIn, sBalise_D)) { //Cherche la premiere balise
sDeb_Str += strlen(sBalise_D);
sIn = sDeb_Str; //sIn "saute" la balise
if (IsNumeric) { //Si l'argument est IsNumeric > 0 alors rechercher les infos "numeriques"
while (iIsNumeric(*sIn)) { //Tant que les caracteres sont numeriques; les recuperer...
sCmdFound[iNum_Cmd][i++] = sIn[0];
sIn++;
}
} else { //Si les données a recuperer ne sont pas numeriques
if (sFin_Str = strstr(sIn, sBalise_E)) { //Recherche de la balise de fin
while (sFin_Str - sDeb_Str) {
sCmdFound[iNum_Cmd][i++] = sDeb_Str[0]; //Recuperation des infos
sDeb_Str++;
}
}
}
sCmdFound[iNum_Cmd][i] = 0;
}
}
return sIn;
}
//Teste si le caractere en argument est numerique ou pas
int iIsNumeric(char cInt)
{
if (cInt >= '0' && cInt <='9') {
return SUCCESS;
}
return FAIL;
}
Conclusion :
C un code compilé avec VC.net, mais doit etre compatible avec gcc ou vc6, j'ai pas testé...C bien sur un code avec Winsock...
J'attends des remarques sur le prog lui mm, mais plus precisement sur la fonction sSearchIn et encore plu particulierement des boucles While, car je ne sais pas si la maniere dont j'ai traité le pb est bien, ou tres lente, enfin je veux savoir si ce ke j'ai fait est correct ou totalement a revoir...
Mettez des commentaires plz !!
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.