Aesmade Δημοσ. 21 Αυγούστου 2007 Δημοσ. 21 Αυγούστου 2007 Καλησπέρα. Πρόσφατα άρχισα να ασχολούμαι με winsocks. Έφτιαξα μερικά προγράμματα που επικοινωνούν με winsocks κτλ. χωρίς κάποια δυσκολία, σήμερα όμως έφτιαξα ένα πρόγραμμα που κατεβάζει αρχεία, αν και λειτουργεί με αρχεία .html, όταν το δοκίμασα με ένα .gif κατέβασε μόνο ένα μικρό κομμάτι της εικόνας. Το source του είναι: > #include <windows.h> #include <stdio.h> #include <string.h> int main() { WSADATA wsdata; WSAStartup(MAKEWORD(2,0),&wsdata); char *path=new char[MAX_PATH],*lfile=new char,*tmp=new char,*ns=new char,*packet=new char[512]; printf("File path:\n"); gets(path); if (strstr(path,"http://")==path) path+=7; tmp=strrchr(path,'/')+1; sprintf(lfile,"C:\\%s",tmp); strncpy(ns,path,strchr(path,'/')-path); hostent *host; DWORD ip=inet_addr(ns); if (ip==INADDR_NONE) host=gethostbyname(ns); else host=gethostbyaddr((char*)&ip,4,AF_INET); SOCKET wsock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); sockaddr_in sin; sin.sin_port=htons(80); sin.sin_family=AF_INET; sin.sin_addr.s_addr=*(DWORD*)host->h_addr; connect(wsock,(sockaddr*)&sin,sizeof(sin)); printf("Connected to %s (%s) successfully\n",host->h_name,inet_ntoa(*(in_addr*)host->h_addr)); FILE *dl=fopen(lfile,"w+"); printf("Opened file %s for writing\n",lfile); tmp=strchr(path,'/'); sprintf(packet,"GET %s\r\n\r\n",tmp,ns); DWORD plen; send(wsock,packet,strlen(packet),0); printf("Sent packet: %s\n",packet); do { plen=recv(wsock,packet,512,0); fprintf(dl,"%.*s",plen,packet); } while(plen); printf("Transfer completed\n"); fclose(dl); closesocket(wsock); WSACleanup(); getchar(); return 1; } Κάτι που με παραξενεύει είναι πως βρήκα ένα παρόμοιο πρόγραμμα στο codeproject που λειτουργεί χωρίς πρόβλημα, αν και δεν μπορώ να βρω κάποια σημαντική διαφορά: > char buff[512]; CString s; WSADATA wsaData; struct hostent *hp; unsigned int addr; struct sockaddr_in server; CString servername; CString filepath; CString filename; ParseURL(m_url,servername,filepath,filename); int wsaret=WSAStartup(0x101,&wsaData); if(wsaret) return; s.Format("Initialized WinSock"); m_list.AddString(s); SOCKET conn; conn=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if(conn==INVALID_SOCKET) return; s.Format("SOCKET created"); m_list.AddString(s); if(inet_addr(servername)==INADDR_NONE) { hp=gethostbyname(servername); } else { addr=inet_addr(servername); hp=gethostbyaddr((char*)&addr,sizeof(addr),AF_INET); } if(hp==NULL) { closesocket(conn); return; } s.Format("hostname/ipaddress resolved"); m_list.AddString(s); server.sin_addr.s_addr=*((unsigned long*)hp->h_addr); server.sin_family=AF_INET; server.sin_port=htons(80); if(connect(conn,(struct sockaddr*)&server,sizeof(server))) { closesocket(conn); return; } s.Format("Connected to server :- %s %s",servername,); m_list.AddString(s); sprintf(buff,"GET %s\r\n\r\n",filepath); send(conn,buff,strlen(buff),0); s.Format("sending command :- GET %s to server",filepath); m_list.AddString(s); CFile f; int y; CString fname="c:\\"; fname+=filename; f.Open(fname,CFile::modeCreate | CFile::modeWrite); s.Format("starting to receive file"); m_list.AddString(s); while(y=recv(conn,buff,512,0)) { f.Write(buff,y); } f.Close(); s.Format("File downloaded and saved :- %s",fname); m_list.AddString(s); closesocket(conn); s.Format("SOCKET closed"); m_list.AddString(s); WSACleanup(); s.Format("De-Initialized WinSock"); m_list.AddString(s); Ξέρετε τι πρέπει να διορθώσω; Ευχαριστώ εκ' των προτέρων.
bookysmell2004 Δημοσ. 21 Αυγούστου 2007 Δημοσ. 21 Αυγούστου 2007 Δεν κατάφερα να κάνω compile τον κώδικά σου. Παρόλ' αυτά θα κάνω μερικές παρατηρήσεις. Διορθώστε με αν κάνω λάθος. Η συνάρτηση recv ορίζει το δείκτη packet σε έναν πίνακα από byte (char *). Δεν είναι αλφαριθμητικό! Προσπαθώντας να χρησιμοποιήσεις fprintf(dl,"%.*s",plen,packet) για εγγραφή στο αρχείο ουσιαστικά την φορμάρεις σαν αλφαρηθμητικό με αποτέλεσμα η εγγραφή να σταματάει στο πρώτο σημείο που συναντάει μηδέν. Αυτό δε συμβαίνει με τα αρχεια .html τα οποία έχουν plain text format. Για να το επιβεβαιώσεις κάνε debugging την εφαρμογή σου μέχρι και πριν από την εντολή fprintf(dl,"%.*s",plen,packet) και σύγκρινε το μέγεθος του packet με το πραγματικό μέγεθος της εικόνας. Εάν όντως αυτό είναι το πρόβλημα (όπως σου είπα δεν κατάφερα να το τρέξω κι έτσι δεν μπορώ να είμαι σίγουρος) μπορείς να αντικαταστήσεις το γράψιμο σε μορφή binary και όχι plain text (wb+ για παράδειγμα). Επίσης μπορείς να δοκιμάσεις να αυξήσεις το μέγεθος του packet (ή να ορίσεις καινούριο δείκτη char *m_Handle = new char[plen] έπειτα από την κλήση στην recv).
Aesmade Δημοσ. 22 Αυγούστου 2007 Μέλος Δημοσ. 22 Αυγούστου 2007 Σ'ευχαριστώ πολύ, δεν το είχα σκεφτεί από πλευράς bytes, νόμιζα πως έκανα κάποιο λάθος με τα send/recv... Χρησιμοποίησα fwrite και w+b mode και δουλεύει μια χαρά. Απο περιέργεια όμως, μπορείς να μου πεις τι compiler έχεις και τι errors σου δίνει;
bookysmell2004 Δημοσ. 22 Αυγούστου 2007 Δημοσ. 22 Αυγούστου 2007 VS2005 Pro. Έχω κάποια linking errors σε σύμβολα του WinSock. Προφανώς κάποιο πρόβλημα με την WinSock2.h.
Aesmade Δημοσ. 22 Αυγούστου 2007 Μέλος Δημοσ. 22 Αυγούστου 2007 Α, αυτό πρέπει να διορθωθεί αν γράψεις #pragma comment(lib,"wsock32.lib") στον κώδικα ή αν βάλεις το wsock32.lib στα library modules.
bookysmell2004 Δημοσ. 22 Αυγούστου 2007 Δημοσ. 22 Αυγούστου 2007 Σωστά Πρέπει να δηλώσεις static library. Είδες τι κάνει η C#; Σε κάνει και ξεχνάς τα παλιά
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.