Eingenen ServerBrowser schreiben



  • Also ich habe jetzt ein paar Tage versucht die verbindung zu einem Server
    herzustellen, doch ohne Erfolg....
    Könntet ihr mir vielleicht sagen wie ich winsock in Borland C++ 6
    benutzen kann?



  • Haha,
    ich habe es mit WinSock hingekiegt eine Verbindung auf meinen WebServer herzustellen!
    Jetzt zu meiner vorherigen Frage: was muss ich an den GameServer senden
    um einen Status zu empfangen?

    Hier mein Code:

    WSADATA WSAData;
       WSAStartup(MAKEWORD(2,0), &WSAData);
       SOCKET sock;
       SOCKADDR_IN sin;
       sock = socket(AF_INET, SOCK_STREAM, 0);
       char buffer[2048];
       string got;
       string v;
    
       string request = "GET /xxxxxxx/xxx/version.dat HTTP/1.1\r\n";
       request += "Host: xxxxxxx.xxxxxxx.xxx\r\n";
       request += "User-Agent: Mozilla Firefox 3.5.3\r\n";
       request += "Accept: */*\r\n";
       request += "Referer: http://serverfavorite.de.hm\r\n";
       request += "\r\n";
    
            sin.sin_addr.s_addr = inet_addr("xxx.xx.xx.xxx");
            sin.sin_family = AF_INET;
            sin.sin_port = htons(80);
    
            if(connect(sock, (SOCKADDR *)&sin, sizeof(sin)) == SOCKET_ERROR) {
                    ShowMessage("Version check failed!\n Can not connect to server.");}
            else {
                    strcpy(buffer, request.c_str());
                    send(sock, buffer, request.size() + 1, 0);
                    while (recv(sock, buffer, sizeof(buffer), 0) != 0) {
                            got = buffer;
                            v = got.replace(0, got.find("= ") + 2, "");}}
    
            closesocket(sock);
            WSACleanup();
    

    Wenn ich diesen Befehl ausführe so wird der in halt der
    Datei(in dem Fall 0.90) ausgegeben, aber mit irgend so einem komischem Zeichen
    hinten dran! Wieso?
    Und noch eine Frage wie kann ich z.B. eine exe mit HTTP downloaden?
    Ich habe mir diesen Eintrag angeguck: http://c-plusplus.net/forum/viewtopic-var-t-is-219181-and-highlight-is-http+download.html
    , aber ich verstehe den code nicht ganz.... Danke schon mal jetzt für eure Hilfe 🙂

    MfG agent_x



  • http://c-plusplus.net/forum/viewtopic-var-t-is-169861.html

    Netzwerkprogrammierung erfordert einiges an Wissen...



  • strcpy(buffer, request.c_str()); 
                    send(sock, buffer, request.size() + 1, 0); 
                    while (recv(sock, buffer, sizeof(buffer), 0) != 0) { 
                            got = buffer; 
                            v = got.replace(0, got.find("= ") + 2, "");}}
    

    ist unnötig, fehleranfällig und zum teil auch einfach glück, dass es funktioniert...
    unnötig: warum kopierst du erst?
    fehleranfällig: du testest nirgendwo auf request.size() < sizeof(buffer)
    wobei ich direkt wieder sizeof buffer durch ne konstante ersetzen würde(die ich auch bei der array-deklaration verwenden würde) - aber das ist vrmtl geschmackssache...
    glück: send hat nur <rückgabewert> anzahl an bytes senden können - das muss nicht unbedingt alles gewesen sein
    send kann auch SOCKET_ERROR zurückgeben, wenn ich mich recht entsinne - z.bsp., wenn mit diesem aufruf noch nicht alles empfangen wurde - aber imho auch bei "richtigen" fehlern.
    got.find("= ") kann auch npos liefern("= " existiert nicht nach position {letzter parameter(= size_type(/*0*/) )}) und damit würdest du ne length_error-exception oder wie auch immer die heißt bekommen...

    bb

    PS: Can not gibt es zwar im englischen, aber imho ist es in diesem kontext nicht nur extrem ungebräuchlich sondern falsch



  • Wenn ich

    void GetLine(int socket, std::stringstream& line) {
        for(char c; recv(socket, &c, 1, 0) > 0; line << c) {
            if(c == '\n') {
                return;}}
    }
    

    versuche in meinen code einzubauen kommt bbei mir nix!!!



  • ich sollte mal mitzählen, wie oft in letzter zeit ich was in dem forum hier über winsock-send + -recv geschrieben hab 😣

    #include <string>
    #include <windows.h>
    
    enum { BUF_LEN = 1024 };
    
    std::string receive(SOCKET socket)
    {
    	char buf[BUF_LEN];
    
    	std::string R;
    	int length;
    
    	for( ;; )
    	{
    		length = recv(socket, &buf[0], BUF_LEN, 0);
    
    		if(length == 0)
    		//	"connection gracefully closed" oder so was in der richtung sollte in der msdn stehen
    		if(length == SOCKET_ERROR)
    		{
    			if(GetLastError() != WSAEMSGSIZE)
    				throw std::runtime_error("failure at receive");
    
    			R.append(&buf[0], &buf[BUF_LEN]);
    			continue;
    		}
    	}
    
    	R.append(&buf[0], &buf[length]);
    	return R;
    }
    

    wenn du nur das stück bis zum ersten zeilenumbruch haben möchtest, dann würde ich das an deiner stelle später machen... (std::string.find('\n'));
    aber dazu würd ich noch sagen, dass es nich die allerbeste idee ist, zeilenumbrüche zum trennen zu verwenden(weil die je nach system verschieden sind "\r\n", "\n", ...

    falls du fragen hast:
    http://msdn.microsoft.com/en-us/library/ms740121(VS.85).aspx
    lesen und danach kannste immernoch fragen

    bb



  • #include <iostream>
    #include <fstream>
    #include <winsock2.h>
        using namespace std;
    
    enum {buflen = 1024};
    
    int main() {
      WSADATA WSAdata;
      WSAStartup(MAKEWORD(2,0), &WSAdata);
      SOCKET sock;
      SOCKADDR_IN sin;
      sock = socket(AF_INET, SOCK_STREAM, 0);
      string stream;
      char recvbuf[buflen];
      int recvbuflen = buflen;
      int got;
      int allinall = 0;
    
      string request = "GET /serverfavorite/files/ET/serverfavorite.exe HTTP/1.1\r\n";
      request += "HOST: xxxxxxx.xxxxxxx.xxx\r\n";
      request += "Connection: closed\r\n\r\n";
      sin.sin_family = AF_INET;
      sin.sin_addr.s_addr = inet_addr("xxx.xx.xx.xxx");
      sin.sin_port = htons(80);
    
        if(connect(sock, (SOCKADDR *)&sin, sizeof(sin)) == SOCKET_ERROR) {
            cout << "Konnte nicht mit dem server verbinden!\n";}
        else {
            cout << "Mit dem Server verbunden!\n";
            if(send(sock, request.c_str(), request.size() + 1, 0) == SOCKET_ERROR) {
                cout << "Konnte Anfrage nicht senden!\n";}
            else {
                cout << "Anfrage gesendet!\n";
                fstream f("test.exe", ios::binary | ios::out);
                if(!f) {
                    cout << "Konnte datei nicht erstellen!\n";}
                else {
                    cout << "Erstelle Datei.... ";}
                while((got = recv(sock, recvbuf, recvbuflen, 0)) > 0) {
                    if(got > 0) {
                        cout << "\r" << "Empfange.... (" << got << " Bytes)" << flush;}
                        f.write(recvbuf, got);
                        allinall += got;}
                cout << "\nFertig (" << allinall << " Bytes)\n";
                f.close();}}
    
        closesocket(sock);
        WSACleanup();
    
            return 0;
    }
    

    Mein neuer Code(nur zum testen), aber erfunzt nicht richtig... 😞
    er lädt alles runter.... schreibt die HTTP Header in die Datei, den Inhalt...
    Wenn ich aber am Ende die Header manuell entferne und versuche die Datei zustarten,
    geht es nicht...



  • int main() {
    }
    

    mein neuer code - funktioniert super...

    mal im erst - teil deinen code in paar fkt auf... ich hab dir doch nun schon eine gegeben, die du nutzen kannst...
    so was guck ich mir auf jeden fall jz in nächster zeit nicht an...

    bb



  • #include <stdexcept>
    #include <string>
    #include <winsock2.h>
    #include <windows.h>
    
    namespace sockets
    {
    	class http
    	{
    	private:
    		SOCKET sock;
    
    		static std::size_t counter;
    		enum { BUF_LEN = 1024 };
    
    		void connect(const std::string &ip)
    		{
    			SOCKADDR_IN sin;
    			sin.sin_family = AF_INET;
    			sin.sin_addr.s_addr = inet_addr(ip.c_str());
    			sin.sin_port = htons(80);
    
    			int error_code = ::connect(sock, (SOCKADDR *)&sin, sizeof(sin));
    			if(error_code == SOCKET_ERROR)
    			{
    				throw std::runtime_error("Cannot connect to " + ip);
    			}
    		}
    	public:
    		http()
    		:	sock(INVALID_SOCKET)
    		{
    			if(counter++ == 0)
    			{
    				WSADATA WSAdata;
    				WSAStartup(MAKEWORD(2,0), &WSAdata);
    			}
    
    			sock = socket(AF_INET, SOCK_STREAM, 0);
    			if(sock == INVALID_SOCKET)
    			{
    				throw std::runtime_error("Cannot create socket");
    			}
    		}
    
    		~http()
    		{
    		    closesocket(sock);
    
    			if(--counter > 0)
    				return;
    
    			WSACleanup();
    		}
    
    		void send(const std::string &ip, const std::string &request)
    		{
    			connect(ip);
    
    			int error_code = ::send(sock, request.c_str(), request.size()+1, 0);
    			if(error_code == SOCKET_ERROR)
    			{
    				throw std::runtime_error("Cannot send request");
    			}
    		}
    
    		std::string recv()
    		{
    			char buf[BUF_LEN];
    
    			std::string R;
    			for( ;; )
    			{
    				const int length = ::recv(sock, &buf[0], BUF_LEN, 0);
    
    				if(length == 0)
    				{//	hier ist auch ne andere behandlung denkbar
    					throw std::runtime_error("Connection closed");
    				}
    				else if(length == SOCKET_ERROR)
    				{
    					if(GetLastError() == WSAEMSGSIZE)
    					{
    						R.append(&buf[0], &buf[BUF_LEN]);
    						continue;
    					}
    
    				//	hier evtl noch auf unterschiedliche errorcodes unterschiedlich reagieren...
    					throw std::runtime_error("failure at receive");
    				}
    				else
    				{
    					R.append(&buf[0], &buf[length]);
    					break;
    				}
    			}
    
    			return R;
    		}
    	};
    
    	std::size_t http::counter = 0;
    }
    
    //Console - helper
    #include <iostream>
    void wait()
    {
    	std::cin.clear(); 
    	std::cin.ignore( std::cin.rdbuf()->in_avail());
    	std::cin.get();
    }
    
    //Request - helper
    std::string get_request()
    {//	evtl dynamisch erstellen!?
    	std::string request = "GET /serverfavorite/files/ET/serverfavorite.exe HTTP/1.1\r\n";
    	request += "HOST: xxxxxxx.xxxxxxx.xxx\r\n";
    	request += "Connection: closed\r\n\r\n";
    	return request;
    }
    
    #include <fstream>
    
    int main()
    {
    	try
    	{
    		sockets::http http_sock;
    		std::cout << "socket created" << std::endl;
    		http_sock.send("127.0.0.1", get_request());
    		std::cout << "request transmitted" << std::endl;
    		std::string received = http_sock.recv();
    		std::cout << "completly received" << std::endl;
    		std::fstream out("test.exe", std::ios::binary | std::ios::out);
    		out.write(received.c_str(), received.size());
    		std::cout << "saved the received (" << received.size() << " Byte)" << std::endl;
    	}
    	catch(const std::exception &e)
    	{
    		std::cout << e.what() << std::endl;
    	}
    
    	wait();
    }
    

    so in etwa sollte es funktionieren...
    evtl solltest du - falls es noch immer nicht funktioniert (was gut sein kann) mal ne bessere fehlerbeschreibung liefern bzw mal mit nem hexeditor die beiden dateien öffnen und vergleichen und sagen wo und wie sich diese unterscheiden...

    bb



  • Sorry, dass ich so lange nicht geantwortet habe...
    ---edit hat sich geklärt---


Anmelden zum Antworten