pRoGraMerZ


Forum pRoGraMerZ Strona Główna -> Programowanie Sieciowe -> Sockety w C++ Idź do strony 1, 2, 3  Następny
Napisz nowy temat  Odpowiedz do tematu Zobacz poprzedni temat :: Zobacz następny temat 
Sockety w C++
PostWysłany: Sob 15:03, 19 Lis 2005
Popiol
Poison Headcrab

 
Dołączył: 02 Lis 2005
Posty: 16
Przeczytał: 0 tematów

Ostrzeżeń: 0/5
Skąd: Wygiełzów





Witam w nowym dziale i zachęcam do zapoznania się z Socketami w C++ pod Windowsem. Sockety są dość prymitywnym sposobem przesyłania danych przez sieć, bo potrafią przesyłać tylko łańcuchy znaków. Można jednak wykorzystać je np do wysyłania zapytań do serwera. Pokażę jak zrobić własną przeglądarkę internetową, wyświetlającą kod źródłowy strony.

Najpierw włączamy nagłówek:

Kod:
#include <winsock2.h>


Pierwszą funkcją, którą trzeba wywołać jest funkcja WSAStartup. Inicjalizuje ona korzystanie z socketów. Robimy to tak:

Kod:
  WORD wVersionRequested = MAKEWORD(2, 0);
  WSADATA wsaData;

  if (WSAStartup(wVersionRequested,&wsaData) != 0) {
    cout << "Blad funkcji WSAStartup";
    return;
  }

  if (LOBYTE(wVersionRequested) != 2 || HIBYTE(wVersionRequested) != 0)
  {
    WSACleanup();
    cout << "Nie znaleziono biblioteki w wersji 2.0";
    return;
  }


Znaczenie tych linii kodu jest bardzo mało ciekawe i równie mało istotne, więc daruję sobie komentarz. Następnym krokiem jest utworzenie socketa, przez który będziemy wysyłać i odbierać dane.

Kod:
  SOCKET s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  if (s == INVALID_SOCKET) {
    WSACleanup();
    cout << "Blad przy tworzeniu socketa";
    return;
  }


Pierwszy parametr to tzw Address Family, czyli rodzina adresów. AF_INET oznacza chyba po prostu, że jest to adres internetowy. Drugi parametr to typ socketa. Tutaj możemy podać dwie wartości: SOCK_STREAM i SOCK_DGRAM. Pierwsza oznacza, że będziemy ustanawiać połączenie (strumień) z drugim komputerem, za pomocą protokołu TCP. Połączenie daje nam pewność, że pakiety dojdą do komputera w takiej kolejności w jakiej zostały wysłane. Druga wartość oznacza, że będziemy używać datagramów (protokół UDP), czyli że nie będzie połączenia. Trzeci parametr oznacza jakiego będziemy używać protokołu. Jest on związany z dwoma poprzednimi parametrami: IP bo używamy adresów internetowych, PROTO - skrót od protocol, TCP bo używamy strumieni. Teraz trzeba ustanowić połączenie.

Kod:
  hostent * host;
  sockaddr_in adres;
  if ((host = gethostbyname("www.google.pl")) == 0) {
    cout << "Nie znaleziono hosta o podanym adresie";
    return;
  }
  adres.sin_family = AF_INET;
  adres.sin_addr = *((in_addr *)host->h_addr);
  adres.sin_port = htons(80);
  if (connect(s,(SOCKADDR*)&adres,sizeof(adres)) == SOCKET_ERROR) {
    WSACleanup();
    cout << "Blad podczas laczenia";
    return;
  }


Wiem, wiem, wygląda to dziwnie. Próbowałem zrozumieć skąd biorą się te rzutowania, ale poddaję się. Nie wiem i szczerze mówiąc mało mnie to obchodzi, ważne, że działa Smile. W tym fragmencie kodu kluczowe są dwie wartości: "www.google.pl" i 80. Pierwsza jest nazwą komputera, z którym się łączymy. Można też podać adres IP, ale wtedy zamiast adres.sin_addr = *((in_addr *)host->h_addr); trzeba napisać:

Kod:
adres.sin_addr.s_addr = inet_addr( "0.0.0.0" );


Druga kluczowa wartość to numer portu. Chodzi o to, że na jednym komputerze może być od cholery serwerów, a każdy ma swój numer i to jest właśnie numer portu. Serwery WWW mają standardowo numer 80. Teraz możemy wysłać do googla zapytanie i z radością odebrać odpowiedź.

Kod:
  int ilbajt;
  char recvbuf[64];
  char sendbuf[64] = "GET / HTTP/1.0\r\nHost: [link widoczny dla zalogowanych]\r\n\r\n";

  if (send(s,sendbuf,strlen(sendbuf),0) == SOCKET_ERROR) {
    WSACleanup();
    cout << "Blad przy wysylaniu zapytania";
    return;
  }

  while (true) {
    ilbajt = recv(s,recvbuf,64,0);
    if (ilbajt == 0) break;
    if (ilbajt == SOCKET_ERROR) {
      cout << "Blad przy odbieraniu danych";
      return;
    }
    cout.write(recvbuf,ilbajt);
  }


W poleceniu send podajemy socket, przez który wysyłamy dane, wskaźnik do tablicy znaków, w której znajduje się nasze zapytanie, długość zapytania oraz flagi, które jak widać olewamy pisząc 0. Odbieranie danych jest troszkę bardziej skomplikowane, bo odpowiedź nie przychodzi w całości. W poleceniu recv podajemy znów socket, przez który pobieramy dane, następnie wskaźnik do tablicy znaków, wielkość tej tablicy i flagi, które jak zwykle olewamy. Wartość funkcji to ilość znaków, które udało się odebrać. Wypisujemy te znaki na ekran i odbieramy dalej, aż ilość odebranych znaków będzie równa 0. Na koniec wypada jeszcze zamknąć socketa i posprzątać po sobie.

Kod:
if (closesocket(s) != 0) {
  cout << "Blad przy zamykaniu socketa";
}
if (WSACleanup() != 0) {
    cout << "Blad przy sprzataniu";
}


To już powinno działać. Aby móc sprawnie używać tego kodu proponuję umieścić go w kilku przyjemnych funkcjach, np: w init() można dać WSAStartup(...) i socket(...), w polacz(adres, port) - connect(...), a w wyslij(zapytanie) - send(...) i recv(...). No i zamiast wyrzucać tekst na standardowe wyjście można zrobić aplikacje okienkową, ale to już zostawiam waszej inwencji twórczej.


Post został pochwalony 0 razy

Ostatnio zmieniony przez Popiol dnia Pią 0:29, 25 Lis 2005, w całości zmieniany 4 razy
Zobacz profil autora
PostWysłany: Sob 20:01, 19 Lis 2005
Popiol
Poison Headcrab

 
Dołączył: 02 Lis 2005
Posty: 16
Przeczytał: 0 tematów

Ostrzeżeń: 0/5
Skąd: Wygiełzów





Teraz trochę o zapytaniach. Podstawowe zapytanie protokołu HTTP to GET. Pobiera ono określony plik. Teoretycznie w najprostszej wersji wygląda tak:

GET adres \r\n

Adres może być bez nazwy hosta, czyli np /index.htm. Jeśli chcemy pobrać stronę główną to zazwyczaj wystarczy napisać jako adres /. Problem w tym, że to zapytanie nie działa. Serwer [link widoczny dla zalogowanych] zwraca informacje o błędnym żądaniu, a inne serwery, które sprawdzałem nic nie zwracają, tylko czekają na ciąg dalszy. Najprostszym zapytaniem, które już czasem działa jest:

GET adres HTTP/1.0 \r\n\r\n

Wiesza się jednak na onecie, a google zwraca informacje o tym, że dokument znajduje się pod innym adresem. Ten drugi problem łatwo rozwiązać, wystarczy jako adres napisać: www.google.pl, albo zrobić to tak jak w poprzednim poście, czyli:

GET adres HTTP/1.0 \r\nHost: adres_hosta\r\n\r\n

Trzeba pamiętać o tym, żeby nie zrobić niepotrzebnej spacji, np przed Host, albo po adresie hosta.

Jeśli przyglądniecie się temu co przyszło w odpowiedzi, to na początku zobaczycie nagłówek, a dopiero po nim kod źródłowy strony. Można pobrać też sam nagłówek. Wystarczy w zapytaniu zamienić GET na HEAD.

W ten sam sposób można pobierać nie tylko stronki, ale też np obrazki. Wystarczy podać odpowiedni adres. Np jak łączymy się z googlem to pod adresem /images/hp0.gif jest fragment loga. Zauważcie, że w nagłówku jest wielkość pliku (Content-Length: 4277). Aby zapisać obrazek do pliku wystarczy zamiast na standardowe wyjście wrzucać zawartość recvbuf do pliku, tzn. wszystko to co jest po nagłówku, a nagłówek od reszty oddziela "\r\n\r\n". Trzeba tylko uważać, żeby znaki specjalne były dobrze zapisane, czyli np używając strumieni plikowych (fstream) trzeba użyć flagi ios::binary przy otwieraniu. Gdyby zależało nam bardzo na szybkości ściągania to chyba lepiej użyć datagramów i protokołu UDP, ale nie bardzo chce mi się w to wnikać.


Post został pochwalony 0 razy
Zobacz profil autora
PostWysłany: Nie 2:51, 04 Gru 2005
Popiol
Poison Headcrab

 
Dołączył: 02 Lis 2005
Posty: 16
Przeczytał: 0 tematów

Ostrzeżeń: 0/5
Skąd: Wygiełzów





A teraz będzie o tym jak zrobić klienta [link widoczny dla zalogowanych] Wykorzystamy kod z pierwszego posta, ale trzeba go trochę rozbudować. Po pierwsze łączymy się z jakimś serwerem FTP, więc trzeba podać jego adres, zamiast "www.google.pl". Po drugie numer portu serwerów FTP to 21, więc tą liczbę wpisujemy zamiast 80. Przykładowe zapytania jakie możemy wysłać to:

USER login\r\n
PASS hasło\r\n
SYST\r\n
HELP\r\n
STAT\r\n
PWD\r\n
PORT nasze_ip_i_port\r\n
LIST\r\n
QUIT\r\n

Pierwsze dwa służą do logowania. Czasami wystarczy, że podamy login anonymous i puste hasło, żeby zalogować się anonimowo. SYST zwraca informacje o systemie operacyjnym na serwerze. HELP zwraca listę zapytań jakie obsługuje serwer. STAT zwraca status serwera. PWD zwraca ścieżkę aktualnego katalogu. LIST pobiera listę plików i folderów aktualnego katalogu (czyli to co się pojawia jak napiszemy dir, albo ls u siebie w linii poleceń). QUIT wylogowuje nas.

Celowo pominąłem zapytanie PORT, bo najpierw trzeba opisać jak wogóle wygląda komunikacja z serwerem [link widoczny dla zalogowanych] Jeśli teraz odpalicie program bez zapytania PORT, to pierwsze pięć zapytań i ostatnie powinny zadziałać, natomiast przy próbie pobrania listy powinien wyjść błąd 425 Can't open data connection, albo coś w tym stylu. Otóż do poprawnej komunikacji z serwerem FTP potrzebne są dwa połączenia. Jedno nazywa się control connection, czyli połączenie kontrolne. Służy ono do wysyłania zapytań i odbierania odpowiedzi. Drugie nazywa się data connection, czyli połączenie danych i służy do (wybaczcie ten trywializm Smile) odbierania danych. Teraz jest najlepsze: aby ustanowić połączenie danych, nasz program musi pełnić również rolę serwera, tzn. czekać na połączenie. To połączenie, które my ustanawiamy to jest połącznie kontrolne, natomiast połączenie danych ustanawia serwer [link widoczny dla zalogowanych] My musimy to połączenie odebrać.

I w tym momencie pojawia się zagadnienie wątków w programowaniu sieciowym. To co teraz nieudolnie postaram się opisać jest totalną podstawą w programowaniu sieciowym wogóle, nie tylko na socketach. Ten pierwszy program jeszcze udało się napisać bez wątków, ale tylko dlatego, że był strasznie prymitywny. Generalnie bez wątków ani rusz. Zarówno wysyłanie danych jak i odbieranie powinny być w osobnych wątkach, a już na pewno odbieranie, gdyż nigdy nie wiadomo kiedy inny komputer będzie chciał nam coś wysłać. Tak po prawdzie to w komunikacji z serwerem FTP akurat wiadomo kiedy można się spodziewać danych, ale po pierwsze coś może pójść nie tak i program się wiesza, bo czeka na połączenie, a po drugie pobierane dane mogą być duże i przez cały czas ich ściągania w programie nic nie dałoby się zrobić.

Nie będę opisywał jak robi się wątki, bo to zależy jakiej biblioteki użyjemy. W devie np możemy wstawić plik process.h i utworzyć wątek pisząc

Kod:
_beginthread(funkcja, 0, NULL);


gdzie funkcja to nazwa funkcji, która ma być wątkiem. Ja korzystam z Buildera, a tam jest dostępna klasa TThread. W każdym razie kod, który odbiera zapytania umieszczamy w wątku. Możemy zrobić tak, że ten wątek cały czas będzie próbował odebrać dane. W tym celu kod odbierający dane umieszczamy w jeszcze jednej nieskończonej pętli. Należy pamiętać, żeby zakończyć wątek zamykając program. Tak trzeba robić gdy danych możemy spodziewać się cały czas. Komunikując się z serwerem FTP możemy też uruchamiać wątek po wysłaniu zapytania i przerywać go gdy odbierzemy odpowiedź.

Teraz najważniejsze, czyli jak za pomocą socketów odebrać połączenie. Najpierw tworzymy sobie drugą zmienną typu SOCKET i ustawiamy dla niej adres i port:

Kod:
  SOCKET serwer;
  sockaddr_in serwerAdres;
  serwerAdres.sin_family = AF_INET;
  serwerAdres.sin_addr.s_addr = inet_addr("0.0.0.0");
  serwerAdres.sin_port = htons(1000);
  bind(serwer, (sockaddr*)&serwerAdres, sizeof(serwerAdres));
  listen(serwer,SOMAXCONN);


W funkcji inet_addr trzeba podać własny numer ip. Numer portu może być właściwie dowolny. Funkcja bind łączy socketa z adresem. Już nawet wiem skąd się bierze się to rzutowanie. W poprzedniej wersji socketów była klasa sockaddr, a teraz jest sockaddr_in, ale dla zgodności funkcje bind i connect przyjmują wskaźnik do sockaddr. Funkcja listen tworzy dla socketa kolejkę przychodzących połączeń. Drugi parametr oznacza wielkość tej kolejki. Stała SOMAXCONN jest równa maksymalnej dopuszczalnej wielkości.

Teraz trzeba zrobić wątek i wpisać w nim coś takiego:

Kod:
  int ilbajt;
  char bufor[200];
  SOCKET s;

  while (true) {
    s = accept(serwer,NULL,NULL);
    if (s == INVALID_SOCKET) continue;
    while (true) {
      ilbajt = recv(s,bufor,200,0);
      if (ilbajt == 0) break;
      if (ilbajt == SOCKET_ERROR) break;
      cout.write(bufor,ilbajt);
    }
    closesocket(s);
  }


Funkcja accept ma za zadanie odebrać połączenie. Jeśli ta sztuka jej się uda to zwraca socketa (tak na marginesie to typ SOCKET jest zdefiniowany jako long czy coś takiego i jest jakby deskryptorem połączenia). Jeśli nikt nie chciał się z nami połączyć to zwrócona będzie wartość INVALID_SOCKET. Jeśli już się połączymy to możemy robić różne rzeczy, ale w przypadku połączenia data connection mamy po prostu odebrać dane, a następnie zamknąć połączenie.

Teraz w końcu mogę opisać zapytanie PORT. Pod nasze_ip_i_port wpisujemy coś co wygląda np tak: 192,168,0,143,3,232. Pierwsze cztery liczby to numer ip, z którym serwer FTP ma nawiązać połączenie danych, czyli nasze ip. Ostatnie dwie liczby to numer portu. Haczyk polega na tym, że pomiędzy przecinkami wpisujemy liczby jednobajtowe. Dlatego zapis 3,232 oznacza 3*256+232 = 1000, a taki właśnie użyłem numer portu.

No teraz to już powinno działać. Inne przydatne zapytania:

RETR plik\r\n
STOR plik\r\n
DELE plik\r\n
CWD katalog\r\n
CDUP\r\n
RMD katalog\r\n
MKD katalog\r\n


Pierwsze pobiera określony plik (zamiast na ekran trzeba go zrzucić do pliku). Drugie wysyła plik i to jest trochę bardziej skomplikowane, bo trzeba ustanowić samemu połączenie danych i wysłać plik jako tekst, tak samo jak wysyła się zapytanie. Jak do tej pory nie robiłem tego więc nie mogę tego dokładniej opisać. DELE usuwa określony plik. CWD zmienia katalog. CDUP zmienia katalog na wyższy. RMD usuwa katalog, MKD tworzy katalog.


Post został pochwalony 0 razy
Zobacz profil autora
PostWysłany: Wto 0:42, 07 Mar 2006
Popiol
Poison Headcrab

 
Dołączył: 02 Lis 2005
Posty: 16
Przeczytał: 0 tematów

Ostrzeżeń: 0/5
Skąd: Wygiełzów





Zamieszczam kod programiku, który realizuje prosty serwer HTTP. Coś dla miłośników socketów i programowania obiektowego.

Najpierw klasa Sockecik, która obudowuje zwykłego socketa w przydatne funkcje.

sockecik.h:
Kod:
#ifndef socketyH
#define socketyH

#include <string>
#include <winsock2.h>

using namespace std;

class Sockecik {
protected:
  SOCKET s;
  string wiadomosc;
public:
  Sockecik(SOCKET sock = 0);
  void tcpSocketInit();
  void bind(string ip, int port);
  void listen();
  void connect(string adr, int port);
  void send(string tekst);
  short int recv(); //0: nic nie przeczytano; -1: zamknieto polaczenie; 1 - przeczytano cos 
  virtual void accept();
  void serwuj();
  virtual void serw();
  void close();
  virtual Sockecik * utworzSockecik(SOCKET sock);
  ~Sockecik();
};

#endif

sockecik.cpp:
Kod:
#include <iostream>
#pragma hdrstop
#include "sockety.h"
#pragma package(smart_init)

using namespace std;

Sockecik::Sockecik(SOCKET sock) : s(sock) {
  BYTE lowbyteVer = 2, highbyteVer = 0;
  WORD wVersionRequested = MAKEWORD( lowbyteVer, highbyteVer );
  WSADATA wsaData;

  if (WSAStartup(wVersionRequested,&wsaData) != 0) {
    cout << "Błąd przy WSAStartup\n";
  }

  if (lowbyteVer != 2 || highbyteVer != 0) {
    WSACleanup();
    cout << "Nie znaleziono biblioteki w wersji 2.0\n";
  }
}

void Sockecik::tcpSocketInit() {
  s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  if (s == INVALID_SOCKET) {
    cout << "Błąd przy tworzeniu socketa\n";
  }
}

void Sockecik::bind(string ip, int port) {
  sockaddr_in adres;
  adres.sin_family = AF_INET;
  adres.sin_addr.s_addr = inet_addr(ip.c_str());
  adres.sin_port = htons(port);
  ::bind(s, (sockaddr*)&adres, sizeof(adres));
}

void Sockecik::listen() {
  ::listen(s, SOMAXCONN);
}

void Sockecik::connect(string adr, int port) {
  sockaddr_in adres;
  adres.sin_family = AF_INET;
  adres.sin_addr = *((in_addr *)gethostbyname(adr.c_str())->h_addr);
  adres.sin_port = htons(port);
  if (::connect(s,(SOCKADDR*)&adres,sizeof(adres)) == SOCKET_ERROR) {
    cout << "Blad przy laczeniu sie z " << adr << ':' << port << '\n';
  }
}

void Sockecik::send(string tekst) {
  if (::send(s,tekst.c_str(),tekst.length(),0) == SOCKET_ERROR) {
    cout << "Blad przy wysylaniu tekstu:" << tekst << '\n';
  }
}

short int Sockecik::recv() {
  int ilbajt;
  char bufor[201];
  wiadomosc.clear();

  while (true) {
    ilbajt = ::recv(s,bufor,200,0);
    if (ilbajt == 0) break;
    if (ilbajt == SOCKET_ERROR) {
      cout << "Blad przy recv\n";
      return -1;
    }
    bufor[ilbajt] = '\0';
    wiadomosc.append(bufor);
    if (ilbajt < 200) break;
  }

  if (wiadomosc.length() == 0) return 0;
  return 1;
}

void Sockecik::close() {
  if (closesocket(s) != 0) {
    cout << "Blad przy zamykaniu socketa\n";
  }
}

Sockecik::~Sockecik() {
  close();
  if (WSACleanup() != 0) {
    cout << "Blad przy WSACleanup";
  }
}

void Sockecik::accept() {
  listen();
  Sockecik * nowySerwer;
  SOCKET nowySocket;
  while (true) {
    nowySocket = ::accept(s,NULL,NULL);
    if (nowySocket != INVALID_SOCKET) {
      nowySerwer = utworzSockecik(nowySocket);
      nowySerwer->serwuj();
    }
  }
}

Sockecik * Sockecik::utworzSockecik(SOCKET sock) {
  return new Sockecik(sock);
}

DWORD WINAPI serwujThread(LPVOID sockecik) {
  Sockecik * sock = (Sockecik*)sockecik;
  sock->serw();
  return 0;
}

void Sockecik::serwuj() {
  CreateThread(NULL,0,serwujThread,this,0,NULL);
}

void Sockecik::serw() {
  short int result;
  listen();
  while (true) {
    result = recv();
    if (result == 1) cout << wiadomosc;
    else if (result == -1) break;
  }
}

A teraz klasa SerwerHTTP, która dziedziczy po Sockecik.

serwerhttp.h:
Kod:
#ifndef socketyhttpH
#define socketyhttpH

#include "sockety.h"

class SerwerHTTP : public Sockecik {
public:
  SerwerHTTP(SOCKET s, int port) : Sockecik(s) {
    bind ("0", port);
  }
  SerwerHTTP(int port) : Sockecik() {
    tcpSocketInit();
    bind ("0", port);
  }
  SerwerHTTP(SOCKET s) : Sockecik(s) {}
  void serw();
  Sockecik * utworzSockecik(SOCKET sock);
};

#endif

serwerhttp.cpp:
Kod:
#include <iostream>
#include <fstream>
#pragma hdrstop
#include "socketyhttp.h"
#pragma package(smart_init)

void dopiszInt(string& s, int i) {
  char str[30]; itoa(i,str,10);
  s.append(str);
}

void SerwerHTTP::serw() {
  if (recv() == 1) {
    wiadomosc = wiadomosc.substr(0,wiadomosc.find('\r',0));
    cout << "Odebrano zapytanie:\n" << wiadomosc << '\n';
  }

  string komenda = wiadomosc.substr(0,wiadomosc.find(' ',0));
  wiadomosc = wiadomosc.substr(wiadomosc.find(' ',0)+1,wiadomosc.length());
  string nazwapliku = wiadomosc.substr(1,wiadomosc.find(' ',0)-1);
  if (nazwapliku == "") nazwapliku = "index.html";

  fstream plik(nazwapliku.c_str(),ios::in);
  string head, body;
  if (!plik.is_open()) {
    body = "404 Nie ma takiego pliku";
    head = "HTTP/1.1 404 Not Found\r\n"
           "Connection: Keep-Alive\r\n"
           "Content-Type: text/plain\r\n"
           "Content-Length: ";
           dopiszInt(head,body.length()); head += "\r\n";
  } else {
    char buf[200]; int ilbajt;
    while (true) {
      ilbajt = plik.readsome(buf,200);
      if (ilbajt == 0) break;
      body.append(buf,ilbajt);
    }
    plik.close();

    string typ = nazwapliku.substr(nazwapliku.find('.',0)+1,nazwapliku.length());
    if (typ == "txt") typ = "plain";

    head = "HTTP/1.1 200 OK\r\n"
                "Connection: Keep-Alive\r\n"
                "Content-Type: text/";
                head += typ; head += "\r\n"
                "Content-Length: ";
                dopiszInt(head,body.length()); head += "\r\n";
  }
  if (komenda == "GET") {
    send(head+"\r\n"+body);
    cout << "Wyslano:\n" << head << "\r\n" << body << "\n\n";
  }
  else if (komenda == "HEAD") {
    send(head+"\r\n");
    cout << "Wyslano:\n" << head << "\r\n" << "\n\n";
  }
}

Sockecik * SerwerHTTP::utworzSockecik(SOCKET sock) {
  return new SerwerHTTP(sock);
}

I wreszcie program główny, który wygląda zdecydowanie najładniej:
Kod:
#include "socketyhttp.h"

SerwerHTTP serwer(4321); //parametr to numer portu

int main(int argc, char* argv[])
{
  serwer.accept();
  return 0;
}

Teraz trzeba wejść do przeglądarki i napisać jako adres numer ip kompa, na którym odpaliliśmy serwer, a po numerze ip ':' i numer portu, który w tym przypadku wynosi 4321. Czyli piszemy coś w rodzaju http://123.456.0.0:4321. Jeśli ustawimy port 80 w programie to w przeglądarce nie trzeba wpisywać numeru portu, bo 80 to numer domyślny dla http. Możemy też dopisać nazwę pliku, który chcemy ściągnąć. Jeśli takiego pliku nie będzie to serwer zwróci kod 404. Ścieżką wyjściową, z której serwer pobiera pliki jest folder, w którym odpaliliśmy serwer. Miłego serfowania.


Post został pochwalony 0 razy
Zobacz profil autora
PostWysłany: Pon 19:08, 12 Lut 2007
Encedicktardup0
Headcrab

 
Dołączył: 12 Lut 2007
Posty: 2
Przeczytał: 0 tematów

Ostrzeżeń: 0/5





Catherine Zeta Jone Throatjob!
[link widoczny dla zalogowanych]


Post został pochwalony 0 razy
Zobacz profil autora
Sockety w C++
Forum pRoGraMerZ Strona Główna -> Programowanie Sieciowe
Możesz pisać nowe tematy
Możesz odpowiadać w tematach
Nie możesz zmieniać swoich postów
Nie możesz usuwać swoich postów
Nie możesz głosować w ankietach
Wszystkie czasy w strefie EET (Europa)  
Strona 1 z 3  
Idź do strony 1, 2, 3  Następny
  
  
 Napisz nowy temat  Odpowiedz do tematu  


fora.pl - załóż własne forum dyskusyjne za darmo
Powered by phpBB © 2001-2003 phpBB Group
Theme created by Vjacheslav Trushkin
Regulamin