Klient - serwer (oprogramowanie ;-)

Te, które nie mieszczą się w powyższych kategoriach, a mają coś wspólnego ze Slackware.

Moderatorzy: Moderatorzy, Administratorzy

Awatar użytkownika
haclet
Użytkownik
Posty: 40
Rejestracja: 2004-06-13, 21:34
Lokalizacja: ŁódĽ/Opole

Klient - serwer (oprogramowanie ;-)

Post autor: haclet »

Trochę z innej beczułki - jakoże nie znalazłem tutaj grupy poświęconej programowaniu... to postanowiłem posta wysłać tutaj - w końcu programowanie to pisanie oprogramowania :P

Potrzebuję pomocy - bo jush nie daję rady ... ;-)

Starałem się napisać prosty programik klient-server - a dokładnie klient'a łączącego się z www i wyświetlającego na stdout to co otrzyma, i niestety - moje plany spełzły na niczym - bo nie rozumiem dlaczego tak prosta rzecz nie działa tak jak to sobie wyobrażałem.

Kod: Zaznacz cały

#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <syslog.h>
#include <errno.h>

#define PORT 80

/*  --- Main code --- */
int main(int argc, char *argv[]) {
  int gniazdodp;
  int fd;
  int dlugosc;
  int cmd = 0, ip = 0;
  int result;
  struct sockaddr_in adres;
  char netcommand[64];
  char srv_ip[15];
  char buffer[64];
  int opt;
  
  memset(&srv_ip, 0, sizeof(srv_ip));
  memset(&netcommand, 0, sizeof(netcommand));
  strcpy(srv_ip, "192.168.1.20");
  strcpy(netcommand, "GET /");
  printf("Target: %s\n", srv_ip);
  printf("Command: %s\n", netcommand);
 
  printf("Socket: ", srv_ip, netcommand);
  if ((gniazdodp = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
    printf("Error: Can't socket\n");
    exit(1);
  } else {
    printf("OK:\n");
  }
  
  adres.sin_family = AF_INET;
  adres.sin_addr.s_addr = inet_addr(srv_ip);
  adres.sin_port = htons(PORT);
    
  dlugosc = sizeof(adres);
    
  printf("Connect: ");
  result = connect(gniazdodp, (struct sockaddr *)&adres, dlugosc);
  if (result == -1) {
    printf("Error: Can't connect: \n");
    exit(1);
  } else
    printf("OK:\n");

  printf("Send data (%d Bytes): ", strlen(netcommand));
  result = write(gniazdodp, &netcommand, strlen(netcommand));
  if (result <= 0) {
    printf("Error: Cannot sending data to server.\n");
    exit(1);
  } else {
    printf("OK:\n");
  }

  printf("Read data:\n ");
  while ((result = read(gniazdodp, &buffer, sizeof(buffer))) > 0) {
    if (result < 0) {
      printf("Error: Cannot read from socket\n");
      break;
    }
    printf("Some data...\n");
    printf(buffer);
  }
  
  shutdown(gniazdodp, SHUT_RDWR);
  close(gniazdodp);
  return 0;
}
Dane wysyłane do serwera docierają do niego - i wracają od niego. Tylko że programik zaczyna wisieć na funkcji "read". Wcale tego nie pojmuję dlaczego tak się dzieje - według mnie - dane powinny być odczytywane z deskryptora pliku dopóki nie zwróci on wartości zerowej. Niestety tak się nie dzieje i nie wiem czemu - program w pętli while wcale nie dociera do linii printf("Some data...\n") ....

Pozdrawiam bardzo serdecznie ;-)
Pozdrawiam ;-]
Nie amator - nie elita... ;-)
Awatar użytkownika
Sad Mephisto
Administrator
Posty: 2824
Rejestracja: 2004-05-22, 13:24
Lokalizacja: Zabrze
Kontakt:

Re: Klient - serwer (oprogramowanie ;-)

Post autor: Sad Mephisto »

Musiałem zdjąć ankietę - była zupełnie nie na temat. Zapraszam do działu "Nasze forum" - to jest doskonałe miejsce na tego typu sprawy :D
[i]Thank you for noticing this notice. Now that you've noticed this notice, you may have noticed that this notice is noticably unnoticable.
$ python -c "print int(''.join(map(lambda x: str(len(x)),'Kto z woli i myśli zapragnie Pi spisać cyfry ten zdoła.'.split())))/1e+10"[/i]
Awatar użytkownika
Googie
Użytkownik
Posty: 151
Rejestracja: 2004-05-23, 08:35
Kontakt:

Re: Klient - serwer (oprogramowanie ;-)

Post autor: Googie »

Rozwiązania Twojego problemu nie znam, ale zauważyłem coś innego:

Kod: Zaznacz cały

while ((result = read(gniazdodp, &buffer, sizeof(buffer))) > 0) { 
     if (result < 0) {
jest bez sensu. Najpierw while sprawdza czy result > 0, a potem if sprawdza czy result <0. Moze while powinno miec warunek ((result = read(gniazdodp, &buffer, sizeof(buffer))) != 0)?
Googie [ http://scripts.one.pl ]
Awatar użytkownika
haclet
Użytkownik
Posty: 40
Rejestracja: 2004-06-13, 21:34
Lokalizacja: ŁódĽ/Opole

Re: Klient - serwer (oprogramowanie ;-)

Post autor: haclet »

8)

W teorii, którą wyczytałem to read - powinien zwracać długość przeczytanych danych, lub 0 jeżeli nie ma nic do przeczytania (skończył już czytać).... A jeżeli wartość będzie < 0, oznacza to problemy z połączeniem w gnieĽdzie - sytuacja abstrakcyjna aczkolwiek zawsze się może coś takiego przydarzyć ;)
Pozdrawiam ;-]
Nie amator - nie elita... ;-)
Awatar użytkownika
Googie
Użytkownik
Posty: 151
Rejestracja: 2004-05-23, 08:35
Kontakt:

Re: Klient - serwer (oprogramowanie ;-)

Post autor: Googie »

No dobrze, ale chodzi o czysta logike zapisu tego urywku kodu. Tlumaczac na nasze to brzmi tak:
Czy result jest wieksze od 0? Jeśli tak to czy result jest mniejsze od 0? Czyli result mysialo by byc rownoczesnie wieksze i mniejsze od 0, zeby spelnilo warunek ze jest blad :)
Googie [ http://scripts.one.pl ]
Awatar użytkownika
Corvin
Administrator
Posty: 1143
Rejestracja: 2004-05-21, 15:04
Lokalizacja: Gdańsk

Re: Klient - serwer (oprogramowanie ;-)

Post autor: Corvin »

coś mi się zdaje choć nie mam w tej chwili do tego głowy, że powinieneś coś poczytać o nieblokowalnych gniazdach, ....
"Spróbuj zapalić maleńką świeczkę zamiast przeklinać ciemność."
Konfucjusz
Awatar użytkownika
Googie
Użytkownik
Posty: 151
Rejestracja: 2004-05-23, 08:35
Kontakt:

Re: Klient - serwer (oprogramowanie ;-)

Post autor: Googie »

Mialem to mowic, ale myslalem ze to tylko w TCL jest ;)
Googie [ http://scripts.one.pl ]
Awatar użytkownika
Sad Mephisto
Administrator
Posty: 2824
Rejestracja: 2004-05-22, 13:24
Lokalizacja: Zabrze
Kontakt:

Re: Klient - serwer (oprogramowanie ;-)

Post autor: Sad Mephisto »

Źle jest ustawiony operator przypisania.
Przykład:

Kod: Zaznacz cały

int res;
res = 8 > 5;  // res = 0
res = 4 < 5; // res= 1
Oczywiście zamiast 8 i 4 powinien być wynik zwracany przez funkcję.

Niestety, nie możesz tego wrzucić do jednej funkcji...
[i]Thank you for noticing this notice. Now that you've noticed this notice, you may have noticed that this notice is noticably unnoticable.
$ python -c "print int(''.join(map(lambda x: str(len(x)),'Kto z woli i myśli zapragnie Pi spisać cyfry ten zdoła.'.split())))/1e+10"[/i]
Awatar użytkownika
haclet
Użytkownik
Posty: 40
Rejestracja: 2004-06-13, 21:34
Lokalizacja: ŁódĽ/Opole

Re: Klient - serwer (oprogramowanie ;-)

Post autor: haclet »

Googie masz całkowią rację - aż palę się że wstydu że tego nie zobaczyłem wcześniej :cry:

Sad Mephisto: Na tyle programowanie pojmuję ;-) wciąż się zastanawiam jak coś takiego napisałem .... może to było póĽno w nocy z jasnym w ręku, albo jasno nad ranem ;-) :(

Zabieram się za czytanie o tych nieblokowanych gniazdach ;-)
Pozdrawiam ;-]
Nie amator - nie elita... ;-)
pako

Re: Klient - serwer (oprogramowanie ;-)

Post autor: pako »

Każde przesyłane dane powinno się kończyć znakiem \r i \n bo inaczej (w tym akurat
przypadku serwer httpd) nie odbierze owych danych. Tak więc:

strcpy(netcommand, "GET /\r\n");

i już wszystko będzie działać ;]
Awatar użytkownika
haclet
Użytkownik
Posty: 40
Rejestracja: 2004-06-13, 21:34
Lokalizacja: ŁódĽ/Opole

Re: Klient - serwer (oprogramowanie ;-)

Post autor: haclet »

pako pisze:Każde przesyłane dane powinno się kończyć znakiem \r i \n bo inaczej (w tym akurat
przypadku serwer httpd) nie odbierze owych danych. Tak więc:

strcpy(netcommand, "GET /\r\n");

i już wszystko będzie działać ;]
Faktycznie.... ;-) Serdeczne dzięki - nie wpadłem na to że znak końca lini jest taki ważny... ;-)

Ale dziwne dla mnie to jest - bo przy poprzedmin przypadku (GET /) jak zapuszczałem sniffera - to dane docierały... ale nie były wyświetlane - teraz jest już ok.

Thx.
Pozdrawiam ;-]
Nie amator - nie elita... ;-)
ODPOWIEDZ