Vi har forsøgt og lave et klient/server ftp agtigt program. Problemet er når vi sender filer, så hvis det er et billed, så kommer der små prikker på billedet. Vi gør det at vi hakker filen op i 127 bytes pakker og sender en pakke ad gangen (vi bruger TCP). Er det en forkert måde at gøre det på? skulle vi istedet have brugt TransmitFile() funktionen?? Nogle bud?
Denne side indeholder artikler med forskellige perspektiver på Identity & Access Management i private og offentlige organisationer. Artiklerne behandler aktuelle IAM-emner og leveres af producenter, rådgivere og implementeringspartnere.
I princippet burde det i gør virke. Jeg tror, at i ikke få sat filen rigtig sammen igen. I har måske en fejl i en aller anden løkke, eller et sted, hvor i kopierer pakker over i resultat filen.
Vi bruger VC++ 6.0 ... vi mener også det burde virke. Vi ved at når vi brækker filen op i 127 bytes bider på klient siden,så går det godt. Det er når vi sender pakkerne og samler dem igen det går galt. Der kommer en periodisk fejl i billedet (ligner en 1 bit fejl pr. pakke). Du kender ikke noget til den der transmitfile?
Vi har ikke prøvet transmitfile endnu, da vi er igang med rapport skrivning. Her har du vores server kode
/* filnavn = server.cpp Denne kode repræsentere server siden af vores client/server applikation. Udviklet af Troels Aaberg Sørensen, Michael Nielsen og Henry Pedersen */
#include "server.h"
/*-----------------------------------------------------------------*/ //Implementering af SocketHjaelper metoderne. /*-----------------------------------------------------------------*/
//Initalisere Winsock API'en, en socket, og sætter socketen op på en bestemt //IP adresse og portnummer. void SocketHjaelper::init(WSADATA &wsaData, SOCKET &sockeT, SOCKADDR_IN &sockAddr) { //Requester WinSockAPI ver. 1.1. if(WSAStartup(MAKEWORD(1,1), &wsaData) != 0) { cout << "FEJL!: WinSockAPI ikke Initaliseret" << endl; exit(0); }
//Initalisere socketen: sockeT = socket(AF_INET, SOCK_STREAM, 0); //AF_INET: Brug af IP protokollen. SOCK_STREAM = Brug af TCP protokollen. if(sockeT == INVALID_SOCKET) { cout << "FEJL!: Socket IKKE initaliseret." << endl; exit(0); }
//Opsætning af en port: sockAddr.sin_port = 1060;
//Opsætning af Internet type forbindelse (TCP/IP): sockAddr.sin_family = AF_INET;
//Sætter serveren op på IP adressen: 10.20.10.198: sockAddr.sin_addr.S_un.S_un_b.s_b1 = 10; sockAddr.sin_addr.S_un.S_un_b.s_b2 = 20; sockAddr.sin_addr.S_un.S_un_b.s_b3 = 10; sockAddr.sin_addr.S_un.S_un_b.s_b4 = 198; }
void SocketHjaelper::bindOgListen(SOCKET &Socket, SOCKADDR_IN &SockAddr) { //Binder socketen til en specifik IP adresse: if(bind(Socket, (SOCKADDR *)(&SockAddr), sizeof(SockAddr)) == SOCKET_ERROR) { cout << "FEJL!: Fejl under binding." << endl; closesocket(Socket); exit(0); }
//Lytter efter indkommende forbindelser, vi tillader kune en client forbindelse: listen(Socket, 1);
//Venter på en inkommende forbindelse i en uendelig løkke, end til der kommer en //client forbindelse: SOCKET TempSock = SOCKET_ERROR; while(TempSock == SOCKET_ERROR) { TempSock = accept(Socket, NULL, NULL); } Socket = TempSock; }
//Modtager noget data over socketen (/netværks forbindelsen): int SocketHjaelper::modtag(SOCKET &Socket, char data[], int antal, ofstream *ud) { int RetVal = SOCKET_ERROR;
do { RetVal = recv(Socket, data, antal, 0); } while(RetVal==SOCKET_ERROR);
//Tester for fejl ved forbindelsen: if((RetVal == 0)||(RetVal == WSAECONNRESET)||(RetVal == WSAECONNABORTED)) { cout << "Forbindelsen blev lukket fra client siden." << endl; ud->close(); closesocket(Socket); exit(0); }
return RetVal; }
/*-----------------------------------------------------------------*/ //Implementering af FilHjaelper metoderne. /*-----------------------------------------------------------------*/
//Åbner en fil, og initaliserer fildescripteren som holder styr på hvor i filen der skrives: ofstream* FilHjaelper::aaben(ofstream *ud, char fil[], SOCKET sockeT) { ud = new ofstream(fil, ios::binary); if(!ud) { cout << "FEJL!: Kan ikke skrive til fil." << endl; ud->close(); closesocket(sockeT); exit(0); }
/*-----------------------------------------------------------------*/ //Server programmet: /*-----------------------------------------------------------------*/ int main() { //Erklærer nogle socket variabler: WSADATA wsaData; SOCKET sockeT; SOCKADDR_IN sockAddr; SocketHjaelper forbindelsen;
//Erklærer nogle fil variabler: ofstream *ud = 0; char filnavn[] = "ud.bmp"; //Filnavnet på ud filen. char Buffer[bufSize]; //Bruges til indlæsning af fil til RAM. int taeller = 0; //antal af data blokke. Bruges til at indexere med i Buffer. FilHjaelper fil;
//Sætter serveren op på adresse 10.20.10.198 port 1060 forbindelsen.init(wsaData, sockeT, sockAddr); forbindelsen.bindOgListen(sockeT, sockAddr);
//Åbner ud-filen: ud = fil.aaben(ud, filnavn, sockeT);
do { //Modtager et array af chars, taeller sættes lig med antallet af modtaget data: taeller = forbindelsen.modtag(sockeT, Buffer, bufSize, ud);
//Skriver modtaget data til fil: ud = fil.print(taeller, Buffer, ud); }while(sockeT);//så længe clienten ikke lukker for forbindelsen (socketen).
ud->close(); //lukker for filstreamen. closesocket(sockeT); //lukker socketen ned.
return 0; }
//server.h
#include <iostream> using std::cout; using std::cin; using std::ios; using std::cerr; using std::endl;
#include <fstream> using std::ofstream; using std::ifstream;
#include <winsock.h> //Bruges til Socket programmering i Windows
const int bufSize = 128;//Størelsen på datapakerne.
//Bruges til håndtering af socket forbindelsen: class SocketHjaelper { public: void init(WSADATA &wsaData, SOCKET &socket, SOCKADDR_IN &SockAddr); void bindOgListen(SOCKET &Socket, SOCKADDR_IN &SockAddr); int modtag(SOCKET &Socket, char data[], int antal, ofstream*); };
//Bruges til håndtering af filer. class FilHjaelper { public: ofstream* aaben(ofstream*, char[], SOCKET sockeT); ofstream* print(int taeller, char Buffer[], ofstream*); };
Jeg kan ikke lige umiddelbart se noget der er forkert.
Det jeg ville prøve er at udskrive det antal byte's i modtager, for hver blok i læser over socket, for at se om i også modtager det antal pakker som i mener der burde komme. Det kunne jo være, at der har snydt sig en "skrammel pakke" imellem.
I jeres motdag metode checker i for recv fejl, men i checker ikke på alle typer fejl, kun om clienten har lukket for forbindelsen, eller om i har modtaget 0 bytes.
Burde Buffer ikke være et array af unsigned char istedet for char.
Jeg tror ikke, at det er problemet, men i sender jo en binær fil. Hver byte kan have en værdi fra 0..255, men i har defineret en buffer, hvor hver entry kan antage en værdi fra 0..127. Så når i sender en byte med værdien 150, så vil der i princippet opstå en fejl i jeres modtage buffer, Dette sker dog ikke, da unsigned char og char har samme størrelse, nemlig 1 byte.
Når man som i har et problem, som ikke lige er til at forklare, så gælder det vel om at udelukke enhver lille detalje - ikke :).
k, det skal lige siges inden jeg begynder, at jeg kun har kikket på koden et par minuter, så det er langt fra sikkert det er det her, der er problemmet.
du siger at i splitter pakken op i 127 bytes, men når i modtager henter i 129 (0..128)
det her er jeres "hente kode". ------------------------------------------------------------- do { //Modtager et array af chars, taeller sættes lig med antallet af modtaget data: *** taeller = forbindelsen.modtag(sockeT, Buffer, bufSize, ud);
//Skriver modtaget data til fil: ud = fil.print(taeller, Buffer, ud); }while(sockeT);//så længe clienten ikke lukker for forbindelsen (socketen).
ud->close(); //lukker for filstreamen. -------------------------------------------------------------
den linje med de 3 *** ville jeg nok lige prøve at erstatte bufsize med (bufsize-1, eller er det 2??)
jeg ved ikke om det har noget med det at gøre da jeg ikke kender diffinitionen på "forbindelsen.modtag();"
og fejlen kunne vel også ligge i klient programmet, og ikke i server delen.
hvad er der galt med Bufer[128], er der en speciel grund til du ikke vil have den med? det er jo ikke strenge vi arbejder med har, så du har ikke en "\0" til sidst, derfor kan du bruge alle dem du har alloceret.
btw: hvis det giver 128 entry's, ville det stadig værer 1 for meget, hvis han på klient siden deler dem op i 127, og der ville medfører en pixel fejl vær 128 bytes.
hehe, jeg nu blev jeg jo lige nødtil at teste det, og desværer havde du ret.
men det ændre ikke på det faktum, at han har en bug der hvor jeg sagde, hvis han splitter sine pakker op i 127 bytes.
og lige en sidste ting, buffer[128], der ligger stacken, så den er der, men du kan ikke skrive i den, hvis jeg husker rigtigt ligger den op [0] i delphi, når men nok om det, du havde ret og det må jeg vel leve med. ;)
you can't win ém all, but you sure can try.
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.