Jak wyslac dane do serwera ?

Odpowiedz Nowy wątek
2011-08-23 16:25
0

Sciągnałem kod servera i kod clienta. Server i client działa na zasadzie:

  1. server nasluchuje na danym porcie
  2. client laczy sie z serverem
  3. server czeka na odebranie waidomosci
  4. client wysyla wiadomosc i czeka na odbior wiadomosci od serwer
  5. servwer czeka na wpisanie wiadomosci zeby ja odeslac do klienta

Chcialem przerobic tak zeby server nasluchiwal caly czas wiec zapetlilem program i
teraz jest ok jesli chodzi o odbieranie danych od kliku klinetow ktorzy sie polacza.
Ale w klinecie jest tak ze jak sie polacze i wysle wiadomosc to server ja odbierze
ale jak znowu wpisze kolejna to drugi raz juz jej nie widac. Musze sie rozlaczyc i
polaczyc ponownie. czy wiece jak mozna to przerobic by dzialalo tak ze klinet
moze wysylac dowolna ilosc wiadomości.

w kodzie dodalem petle while(true) ale nadal nie dziala

 #include <winsock.h>
#include <iostream.h>
#include <stdlib.h>
#include <string.h>
 
//using namespace std;
 
int main(int argc, int **argv)
{
   WSADATA wsda;                // informacja zwrocona przez WSAStartup
   struct hostent *host;        // informacja o serwerze
   char szMessage[80];          // komunikat
   int iMessageLen;
   int ret;
   char szInBuffer[128];
   int iBufferLen;
   char szAddress[64];
   int iPort;
 
   SOCKET s;                 // uzywane gniazdo
   SOCKADDR_IN addr;          // adres hosta
 
   // pobranie adresu IP
   cout << "Podaj adres IP do ktorego wyslac (np. 127.0.0.1) ...";
   cin.getline(szAddress,64,'\n');
 
   // port na ktorym sie komunikujemy (0...65535)
   iPort = 1000;
 
   // zaladuj WinSock w wersji 2.2
   WSAStartup(MAKEWORD(2,2), &wsda);
 
   // stworzenie gniazda TCP
   s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
 
   // sprawdzenie bledu
   if(s == SOCKET_ERROR)
   {
      cout << "Blad przy inicjalizacji gniazda : " << WSAGetLastError() << endl;
      system("PAUSE");
      exit(1);
   }
 
   // informacja o hoscie
   addr.sin_family = AF_INET;
   addr.sin_port = htons(iPort);
   addr.sin_addr.s_addr = inet_addr(szAddress);
 
   if(addr.sin_addr.s_addr == INADDR_NONE)  // jesli nie podano numeru IP, to odnajdz go z DNS
   {
      host = NULL;
      cout << "Szukam hosta..." << endl;
      host = gethostbyname(szAddress);  // pobierz numer IP i go zachowaj
      if(host == NULL)
      {
         cout << "Nieznany host." << endl;
         system("PAUSE");
         exit(1);
      }
      memcpy(&addr.sin_addr, host->h_addr_list[0], host->h_length);
      cout << "OK." << endl;
   }
 
   // laczenie z serwerem
   cout << "Laczenie z hostem " << szAddress << " na porcie " << iPort << endl;
   ret = connect(s, (struct sockaddr *) &addr, sizeof(addr));
 
   // sprawdzenie bledu
   if(ret == SOCKET_ERROR)
   {
      cout << "Blad przy laczeniu z serwerem : " << WSAGetLastError() << endl;
      system("PAUSE");
      exit(1);
   }
 
    while(true) {
 
     // pobranie komunikatu do bufora
   cout << "Wpisz komunikat ...";
   cin.getline(szMessage,80,'\n');
 
   // dlugosc komunikatu
   iMessageLen = strlen(szMessage);
 
   // wyslanie komunikatu
   cout << "Wysylanie pakietu..." << endl;
   ret = send(s, szMessage, iMessageLen, 0);
 
   // sprawdzenie bledu
   if(ret == SOCKET_ERROR)
   {
      cout << "Blad przy wysylaniu komunikatu : " << WSAGetLastError() << endl;
      system("PAUSE");
      exit(1);
   }
 
    }
 
   // odbior komunikatu zwrotnego
   cout << "Oczekiwanie na komunikat zwrotny..." << endl;
   ret = recv(s, szInBuffer, sizeof(szInBuffer), 0);
 
   // sprawdzenie bledu
   if(ret == SOCKET_ERROR)
   {
      cout << "Blad przy odbiorze komunikatu zwrotnego : " << WSAGetLastError() << endl;
      system("PAUSE");
      exit(1);
   }
 
   // wyswietlenie komunikatu zwrotnego
   iBufferLen = ret;
   szInBuffer[iBufferLen] = '\0';
   cout << "Otrzymano komunikat o tresci \"" << szInBuffer << "\" od hosta " << szAddress << endl;
 
   // zamkniecie gniazda
   closesocket(s);
 
   // zamkniecie WinSock
   WSACleanup();
 
   system("PAUSE");
 
   return 0;
}

Pozostało 580 znaków

2011-08-23 16:37
0

Kod jest TRAGICZNY. A jakbyś go sformatował to byś wiedział w czym problem:

#include <winsock.h>
#include <iostream.h>
#include <stdlib.h>
#include <string.h>
 
//using namespace std;
 
int main(int argc, int **argv)
{
    WSADATA wsda;                                // informacja zwrocona przez WSAStartup
    struct hostent *host;                // informacja o serwerze
    char szMessage[80];                        // komunikat
    int iMessageLen;
    int ret;
    char szInBuffer[128];
    int iBufferLen;
    char szAddress[64];
    int iPort;
 
    SOCKET s;                         // uzywane gniazdo
    SOCKADDR_IN addr;              // adres hosta
 
    // pobranie adresu IP
    cout << "Podaj adres IP do ktorego wyslac (np. 127.0.0.1) ...";
    cin.getline(szAddress,64,'\n');
 
    // port na ktorym sie komunikujemy (0...65535)
    iPort = 1000;
 
    // zaladuj WinSock w wersji 2.2
    WSAStartup(MAKEWORD(2,2), &wsda);
 
    // stworzenie gniazda TCP
    s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
 
    // sprawdzenie bledu
    if(s == SOCKET_ERROR)
    {
        cout << "Blad przy inicjalizacji gniazda : " << WSAGetLastError() << endl;
        system("PAUSE");
        exit(1);
    }
 
    // informacja o hoscie
    addr.sin_family = AF_INET;
    addr.sin_port = htons(iPort);
    addr.sin_addr.s_addr = inet_addr(szAddress);
 
    if(addr.sin_addr.s_addr == INADDR_NONE)         // jesli nie podano numeru IP, to odnajdz go z DNS
    {
        host = NULL;
        cout << "Szukam hosta..." << endl;
        host = gethostbyname(szAddress);        // pobierz numer IP i go zachowaj
        if(host == NULL)
        {
            cout << "Nieznany host." << endl;
            system("PAUSE");
            exit(1);
        }
        memcpy(&addr.sin_addr, host->h_addr_list[0], host->h_length);
        cout << "OK." << endl;
    }
 
    // laczenie z serwerem
    cout << "Laczenie z hostem " << szAddress << " na porcie " << iPort << endl;
    ret = connect(s, (struct sockaddr *) &addr, sizeof(addr));
 
    // sprawdzenie bledu
    if(ret == SOCKET_ERROR)
    {
        cout << "Blad przy laczeniu z serwerem : " << WSAGetLastError() << endl;
        system("PAUSE");
        exit(1);
    }
 
    while(true)
    {
        // pobranie komunikatu do bufora
        cout << "Wpisz komunikat ...";
        cin.getline(szMessage,80,'\n');
 
        // dlugosc komunikatu
        iMessageLen = strlen(szMessage);
 
        // wyslanie komunikatu
        cout << "Wysylanie pakietu..." << endl;
        ret = send(s, szMessage, iMessageLen, 0);
 
        // sprawdzenie bledu
        if(ret == SOCKET_ERROR)
        {
            cout << "Blad przy wysylaniu komunikatu : " << WSAGetLastError() << endl;
            system("PAUSE");
            exit(1);
        }
 
    }
 
    // odbior komunikatu zwrotnego
    cout << "Oczekiwanie na komunikat zwrotny..." << endl;
    ret = recv(s, szInBuffer, sizeof(szInBuffer), 0);
 
    // sprawdzenie bledu
    if(ret == SOCKET_ERROR)
    {
        cout << "Blad przy odbiorze komunikatu zwrotnego : " << WSAGetLastError() << endl;
        system("PAUSE");
        exit(1);
    }
 
    // wyswietlenie komunikatu zwrotnego
    iBufferLen = ret;
    szInBuffer[iBufferLen] = '\0';
    cout << "Otrzymano komunikat o tresci \"" << szInBuffer << "\" od hosta " << szAddress << endl;
 
    // zamkniecie gniazda
    closesocket(s);
 
    // zamkniecie WinSock
    WSACleanup();
 
    system("PAUSE");
 
    return 0;
}
 

Zauważ ze wiadomość zwrotną odbierasz tylko raz bo jest poza pętlą...

Pozostało 580 znaków

2011-08-23 16:54
0

wiem wiem bo ja nie chce zeby klient odbieral wiadomosc zwrotna chce zeby mogl wysylac wiadomosci do serwera ale nie chce zeby za kazdym razem sie znim laczyl tylko zeby na tym ustanowioanym polaczeniu mogl wysylac w petli te wiadomosci to jak to zrobic ?

Pozostało 580 znaków

2011-08-23 17:00
0

W takim razie masz to napisane poprawnie, klient będzie wysyłał do serwera wielokrotnie wiadomości. Ale zapewne po stronie serwera tego nie przewidziałeś...

Kurcze dzieki za sugestie bo moze faktycznie nie odbiera w serwie wiecej niz raz . Bo jak zamkne klienta i otworze i sie polacze to ok ale drugiej wiadomosci nie odbiera...wiec skoro mowisz ze w cliencie jest ok to zajme sie serverem - masterO 2011-08-23 17:12

Pozostało 580 znaków

2011-08-23 17:18
0

Server wyglada tak:

#include <iostream.h>
#include <winsock.h>
#include <stdlib.h>
#include <string.h>
#include<iostream.h>
 
//using namespace std;
 
int main(int argc, int **argv)
{
   WSADATA wsda;              // informacja zwrocona przez WSAStartup
   char szRepMessage[80];     // komunikat zwrotny
   int iMessageLen;
   int ret;
   char szInBuffer[128];        // bufor na otrzymany komunikat
   int iBufferLen;
   int iPort, iAddrLen;
 
   SOCKET sListen, sClient;         // gniazdo dla nasluchu oraz do klienta
   SOCKADDR_IN addr,remote_addr;    // interfejs lokalny oraz polaczonego klienta
 
   // port na ktorym sie komunikujemy (0...65535)
   iPort = 1000;
 
   // zaladuj WinSock w wersji 2.2
   WSAStartup(MAKEWORD(2,2), &wsda);
 
   // stworzenie gniazda TCP
   sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
 
   // sprawdzenie bledu
   if(sListen == SOCKET_ERROR)
   {
      cout << "Blad przy inicjalizacji gniazda : " << WSAGetLastError() << endl;
      system("PAUSE");
      exit(1);
   }
 
   // laczenie gniazda z adresem/portem
   addr.sin_family = AF_INET;
   addr.sin_port = htons(iPort);
   addr.sin_addr.s_addr = htonl(INADDR_ANY);
   ret = bind(sListen, (struct sockaddr *) &addr, sizeof(addr));
 
   // sprawdzenie bledu
   if(ret == SOCKET_ERROR)
   {
      cout << "Blad przy wiazaniu gniazda : " << WSAGetLastError() << endl;
      system("PAUSE");
      exit(1);
   }
   while(true) {
   // ustaw tryb nasluchu
   ret = listen(sListen, 10);
 
   // sprawdzenie bledu
   if(ret == SOCKET_ERROR)
   {
      cout << "Blad przy trybie nasluchu : " << WSAGetLastError() << endl;
      system("PAUSE");
      exit(1);
   }
 
   // oczekiwanie na polaczenie
   cout << "Oczekiwanie na polaczenie (nacisnij CTRL-C zeby przerwac)..." << endl;
   iAddrLen = sizeof(remote_addr);
   sClient = accept(sListen, (struct sockaddr *) &remote_addr, &iAddrLen);
 
   // sprawdzenie bledu
   if(sClient == SOCKET_ERROR)
   {
      cout << "Blad przy nawiazywaniu polaczenia : " << WSAGetLastError() << endl;
      system("PAUSE");
      exit(1);
   }
 
   cout << "Polaczono z hostem " << inet_ntoa(remote_addr.sin_addr) << endl;
 
   // odbior komunikatu
   cout << "Oczekiwanie na odpowiedz..." << endl;
   ret = recv(sClient, szInBuffer, sizeof(szInBuffer), 0);
 
   // sprawdzenie bledu
   if(ret == SOCKET_ERROR)
   {
      cout << "Blad przy odbiorze komunikatu " << WSAGetLastError() << endl;
      //system("PAUSE");
     // exit(1);
   }
 
   // wyswietlenie komunikatu od klienta
   iBufferLen = ret;
   szInBuffer[iBufferLen] = '\0';
   cout << "Otrzymano komunikat o tresci \"" << szInBuffer << "\"" << endl;
 
     }
 
   // wczytanie i wyslanie komunikatu zwrotnego
   cout << "Wpisz komunikat zwrotny...";
   cin.getline(szRepMessage,80,'\n');
   iMessageLen = strlen(szRepMessage);
   ret = send(sClient, szRepMessage, iMessageLen, 0);
 
   // sprawdzenie bledu
   if(ret == SOCKET_ERROR)
   {
      cout << "Blad przy wysylaniu komunikatu zwrotnego : " << WSAGetLastError() << endl;
      system("PAUSE");
      exit(1);
   }
 
   // zamkniecie gniazda
   closesocket(sClient);
 
   // zamkniecie WinSock
   WSACleanup();
 
   system("PAUSE");
 
   return 0;
 
}
 

w sumie nie wiem co moze byc zle ze nie odbiera komuniaktow ?

moze trzeba to zrobic na zasadzie watkow ? ze kazdy klient ma swoj oddzielny watek i tam sie dzieje costam costam ? - masterO 2011-08-23 17:38

Pozostało 580 znaków

2011-08-24 09:08
0

W twoim kodzie serwera odbierasz tylko jedną wiadomość od klienta a potem znów oczekujesz na połączenia. Możesz to zrobić na wątkach:

  • socket który dostajesz z accept() przekazujesz do wątku który odczytuje sobie wiadomości w pętli
  • główny wątek programu jedynie odbiera połączenia przez accept() i odpala nowe wątki.
No wlasnie wczoraj przegrzebalem to wszystko i masz racje bo nie da sie zrobic nieskonczonej petli a w niej nieskonczona kolejna petla. Wiec zostaje watek ,dzieki za pomoc ogarne i dam znac - masterO 2011-08-24 09:49
@masterO: a złożymy się, że się da? :D - Patryk27 2011-08-24 10:01
Nie da się bo nie moze byc wyjscia z petli tej drugiej bo musi odbierac dane - masterO 2011-08-24 10:06

Pozostało 580 znaków

2011-08-24 14:11
0

Proponuje poczytać http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio.html

stwierdzisz, że te wypociny przyniosą Ci gorsze efekty i więcej pracy


░█░█░█░█░█░█░█░█░█░█░█░
edytowany 1x, ostatnio: krwq, 2011-08-24 14:11

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0