PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : meine erste Client Anwendung und ich habe ein Problem



cyber_gh0st
10.09.2009, 09:35
Hi
ich habe ein Programm geschrieben dessen Quelltext so aussieht:

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

int main(void) {
struct sockaddr_in server; //Struktur vom Typ sockaddr_in deklariert.
struct hostent *host_info;
char input;
char *echo_string = malloc(50);
char echo_len;
unsigned long addr;

int sock;

//Eingabe:
printf("Bitte geben sie die Adresse an:\n");
scanf("%s",&input);
fflush(stdin);
printf("Bitte geben sie einen Echostring an:\n");
fgets(echo_string,30, stdin);
fflush(stdin);

//Socket Inizialisieren:
if(sock = socket(AF_INET, SOCK_STREAM, 0) < 0 ) {
fprintf(stderr,"Fehler beim Inizialiesieren des Sockets");
exit(EXIT_FAILURE);
}

//Ausfüllen des sockaddr_in struct:
memset( &server, 0, sizeof(server) );
if((addr = inet_addr(input)) != INADDR_NONE) {
memcpy( (char *)&server.sin_addr, &addr, sizeof(addr));
}
//Domainname in IP umwandeln:
else {
host_info = gethostbyname(input);
if(NULL == host_info) {
fprintf(stderr,"Unbekannter Server");
}
memcpy( (char *)&server.sin_addr, (*host_info).h_addr, (*host_info).h_length );
}
server.sin_family = AF_INET;
server.sin_port = htons(80);

//Verbinden:
if ( connect(sock,(struct sockaddr*)&server, sizeof(server)) < 0) {
fprintf(stderr,"Verbindung kann nicht aufgebaut werden.");
exit(EXIT_FAILURE);
}

echo_len = strlen(echo_string);

if (send(sock, echo_string, echo_len, 0) != echo_len) {
fprintf(stderr,"Fehler beim Senden des Echostrings");
exit(EXIT_FAILURE);
}
close (sock);
return EXIT_SUCCESS;
}

im Terminal sah das dann so aus:

gh0st@a450-netbook:~/Desktop$
gh0st@a450-netbook:~/Desktop$ gcc client.c
client.c: In Funktion »main«:
client.c:37: Warnung: Übergabe des Arguments 1 von »inet_addr« erzeugt Zeiger von Ganzzahl ohne Typkonvertierung
client.c:42: Warnung: Übergabe des Arguments 1 von »gethostbyname« erzeugt Zeiger von Ganzzahl ohne Typkonvertierung
gh0st@a450-netbook:~/Desktop$ ./a.out
Bitte geben sie die Adresse an:
Web.de
Bitte geben sie einen Echostring an:
Segmentation fault
gh0st@a450-netbook:~/Desktop$













Leider kann ch mit der Warnung nicht viel anfangen kann mir bitte eier von euch sagen warum das nicht Funktioniert vielleicht sogar mit einem Auskemmentiertem Quelltext?
währe sehr dankbar.
mfg cyber_gh0st

finsternacht
10.09.2009, 11:43
Ich hab zwar zugegebener Maßen wenig Erfahrung mit C und Konsorten, aber das klingt bei mir nach einem eher kleineren Problem:
Du sollst deinen Input typecasten -> explizit in den gewünschten Datentyp umwandeln.

PS: Meines Erachtens heißt das "Initialisieren"

cyber_gh0st
10.09.2009, 12:06
k danke das mit der Rechtschreibung lerne ich glaube ich nich mehr >.<

sieht mittlerweile so aus:

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

int main(void) {
struct sockaddr_in server; //Struktur vom Typ sockaddr_in deklariert.
struct hostent *host_info;
char input[40];
char *echo_string = malloc(50);
char echo_len;
unsigned long addr;

int sock;

//Eingabe:
printf("Bitte geben sie die Adresse an:\n");
fgets(echo_string,40, stdin);
fflush(stdin);
printf("Bitte geben sie einen Echostring an:\n");
fgets(echo_string,50, stdin);
fflush(stdin);

//Socket Initialisieren:
if(sock = socket(AF_INET, SOCK_STREAM, 0) < 0 ) {
fprintf(stderr,"Fehler beim Inizialiesieren des Sockets");
exit(EXIT_FAILURE);
}

//Ausfüllen des sockaddr_in struct:
memset( &server, 0, sizeof(server) );
if((addr = inet_addr(input)) != INADDR_NONE) {
memcpy( (char *)&server.sin_addr, &addr, sizeof(addr));
}
//Domainname in IP umwandeln:
else {
host_info = gethostbyname(input);
if(NULL == host_info) {
fprintf(stderr,"Unbekannter Server");
}
memcpy( (char *)&server.sin_addr, (*host_info).h_addr, (*host_info).h_length );
}
server.sin_family = AF_INET;
server.sin_port = htons(80);

//Verbinden:
if ( connect(sock,(struct sockaddr*)&server, sizeof(server)) < 0) {
fprintf(stderr,"Verbindung kann nicht aufgebaut werden.");
exit(EXIT_FAILURE);
}

echo_len = strlen(echo_string);

if (send(sock, echo_string, echo_len, 0) != echo_len) {
fprintf(stderr,"Fehler beim Senden des Echostrings");
exit(EXIT_FAILURE);
}
close (sock);
free(echo_string);
return EXIT_SUCCESS;
}


jetzt wird vom Compiler nichts mehr ausgegeben aber ich kann mich nicht verbinden hier das Terminal:

gh0st@a450-netbook:~/Desktop$ ./a.out
Bitte geben sie die Adresse an:
217.72.195.42
Bitte geben sie einen Echostring an:
HEAD / HTTP/1.0
Unbekannter ServerSegmentation fault
gh0st@a450-netbook:~/Desktop$

blackberry
10.09.2009, 14:20
printf("Bitte geben sie die Adresse an:\n");
fgets(echo_string,40, stdin);
fflush(stdin);
printf("Bitte geben sie einen Echostring an:\n");
fgets(echo_string,50, stdin);
fflush(stdin);

cyber_gh0st
10.09.2009, 17:26
arg bin ich dumm Peinlich >.<
maaaaaaaaaaaan :S

//EDIT:
klappt mmer noch nicht:

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

int main(void) {
struct sockaddr_in server; //Struktur vom Typ sockaddr_in deklariert.
struct hostent *host_info;
char input[40];
char *echo_string = malloc(50);
char echo_len;
unsigned long addr;

int sock;

//Eingabe:
printf("Bitte geben sie die Adresse an:\n");
fgets(input,40, stdin);
fflush(stdin);
printf("Bitte geben sie einen Echostring an:\n");
fgets(echo_string,50, stdin);
fflush(stdin);

//Socket Inizialisieren:
if(sock = socket(AF_INET, SOCK_STREAM, 0) < 0 ) {
fprintf(stderr,"Fehler beim Inizialiesieren des Sockets");
exit(EXIT_FAILURE);
}

//Ausfüllen des sockaddr_in struct:
memset( &server, 0, sizeof(server) );
if((addr = inet_addr(input)) != INADDR_NONE) {
memcpy( (char *)&server.sin_addr, &addr, sizeof(addr));
}
//Domainname in IP umwandeln:
else {
host_info = gethostbyname(input);
if(NULL == host_info) {
fprintf(stderr,"Unbekannter Server\n");
}
memcpy( (char *)&server.sin_addr, (*host_info).h_addr, (*host_info).h_length );
}
server.sin_family = AF_INET;
server.sin_port = htons(80);

//Verbinden:
if ( connect(sock,(struct sockaddr*)&server, sizeof(server)) < 0) {
fprintf(stderr,"Verbindung kann nicht aufgebaut werden.");
exit(EXIT_FAILURE);
}

echo_len = strlen(echo_string);

if (send(sock, echo_string, echo_len, 0) != echo_len) {
fprintf(stderr,"Fehler beim Senden des Echostrings");
exit(EXIT_FAILURE);
}
close (sock);
free(echo_string);
return EXIT_SUCCESS;
}

blackberry
10.09.2009, 18:15
nach fprintf(stderr,"Unbekannter Server\n"); fehlt ein exit...

btw:
fgets liest den Zeilenumbruch mit ein.
Ein Host "www.google.com\n" kann nicht aufgelöst werden.
Wegen dem fehlenden exit ist dein socket nicht valid und es kommt zu Fehlern.

Wieder ein dummer Fehler ;)

cyber_gh0st
10.09.2009, 18:22
oh ja das mit dem exit() schon aber wie kann ich das \n wegmachen?

blackberry
10.09.2009, 18:27
input[strlen(input) - 1] = 0;

Mir ist außerdem noch ein Problem aufgefallen...
Jetzt verbindet es war, aber der String kommt bei meinem netcat nicht an.

Ich schau's mir nochmal genauer an.

cyber_gh0st
10.09.2009, 18:31
input[strlen(input) - 1] = 0; <-- verstehe ich irgentwie nicht...

blackberry
10.09.2009, 18:59
input[strlen(input) - 1] = 0;
Ein C-String ist im Grunde nichts anderes als ein char-Array.
Das Ende wird durch ein Null-Zeichen (\0, oder einfach 0 wenn du es als Zahl schreiben willst) bestimmt.

Die Funktion strlen liefert die Anzahl der Zeichen ihres Parameters, die vor einem solchen 0-Terminator stehen.

Beispiel:
strlen("Hello World") = 11

Unser mit fgets eingelesener String sieht aber so aus:
strlen("Hello World\n") = 12

Hinter dem \n befindet sich jedoch noch ein 0-Terminator.
meinString[strlen(meinString)] ist somit immer 0, da dort das 0-Zeichen steht

Wenn wir vom dem Index nun 1 substrahieren ist das \n-Zeichen gemeint.
Machen wir also:
meinString[strlen(meinString) - 1] = __EIN_ZEICHEN_;
so wird das \n am Ende des C-Strings druch "__EIN_ZEICHEN_" ersetzt.
In unserem Fall wäre das ein 0-Terminator.

Damit wird der String um 1 gekürzt.
Das \n ist weg.


--------------------------------

Back2Topic

Ok ich hab den Sinn deines Programms mal selbst implementiert...
So funktioniert es auf jeden Fall.
Warum es bei deiner Version bei mir nur verbindet und send das richtige Ergebnis liefert, jedoch nichts ankommt weiß ich nicht...

#ifdef _WIN32
/* sorry, bin grad mit Windows on und kann nur so testen... */
#include <winsock2.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define PORT 80


int main(void)
{
char serv[100];
char echo[100];
struct sockaddr_in server;
struct hostent *dns;
int sock;

#ifdef _WIN32
// WinSock starten
WSADATA wsa;
if (WSAStartup(MAKEWORD(2, 0), &wsa) == -1)
{
printf("Error: WSAStartup\n");
return 1;
}
#endif

// Daten einlesen
printf("Host: ");
fgets(serv, sizeof(serv), stdin);
fflush(stdin);

printf("Echo: ");
fgets(echo, sizeof(echo), stdin);
fflush(stdin);

// Länge checken und \n entfernen
if (strlen(serv) < 2 || strlen(echo) < 2)
{
printf("Error: host || echo [strlen]\n");
return 2;
}
serv[strlen(serv) - 1] = 0;
echo[strlen(echo) - 1] = 0;

// Hostname auflösen
if (!(dns = gethostbyname(serv)))
{
printf("Error: gethostbyname\n");
return 3;
}

// Struktur ausfüllen
memset(&server, 0, sizeof(server));
memcpy(&server.sin_addr.s_addr, dns->h_addr_list[0], sizeof(server.sin_addr.s_addr));
server.sin_family = AF_INET;
server.sin_port = htons(PORT);

// Socket erstellen
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
printf("Error: socket\n");
return 4;
}

// Verbinden
if (connect(sock, (struct sockaddr *) &server, sizeof(server)) == -1)
{
printf("Error: connect\n");
return 5;
}

// Daten senden
if (send(sock, echo, strlen(echo), 0) < strlen(echo))
{
printf("Error: send\n");
return 6;
}

// Socket schließen
#ifdef _WIN32
closesocket(sock);
// WinSock DLL freigeben
WSACleanup();
#else
close(sock);
#endif
return 0;
}

cyber_gh0st
10.09.2009, 19:12
Ausgabe von deinem Programm:
gh0st@a450-netbook:~/Desktop$ gcc test.c
gh0st@a450-netbook:~/Desktop$ ./a.out
Host: web.de
Echo: HEAD / HTTP/1.0
gh0st@a450-netbook:~/Desktop$

Klappt ich versuche es nochmal also ich schreibe nochmal neu irgentwann klappts und dann Poste ich das ganze hier. :)

wacked
10.09.2009, 19:44
zotteljedi hilf!!

blackberry
10.09.2009, 19:55
Bevor jemand fragt wer oder was ein Zotteljedi ist... es handelt sich um folgende Webseite:
http://www.zotteljedi.de/socket-tipps/

Da wir gerade bei diesem Thema sind: das Buch von Jürgen Wolf (C++ von A bis Z) ist wegen seines Socket-Kapitels sehr zu empfehlen.


mfG. BlackBerry

cyber_gh0st
11.09.2009, 17:14
Ich habe C von A bis Z gekauft und finds richtig gut

EDIT:
klappt immer noch nicht
//client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>

void error(char *str) {
printf("%s\n",str);
exit(EXIT_FAILURE);
}

int main(void) {
char input[50];
char echostr[] = "HEAD / HTTP/1.0";
int sock;
struct sockaddr_in serv;
unsigned long addr;

printf("Bitte geben sie die Adresse an:\n");
fgets(input,sizeof(input),stdin);

if(sock = socket(AF_INET, SOCK_STREAM, 0) < 0) {
error("Socket konnte nicht initialisiert werden :(");
}

input[strlen(input-1)] = 0;
if((addr = inet_addr(input)) == INADDR_NONE) {
error("Es konnt keine Internetadresse erstellt werden :(");
}

memset(&serv, 0, sizeof(serv));
memcpy((char *)&serv.sin_addr, &addr, sizeof(addr));
serv.sin_family = AF_INET;
serv.sin_port = htons(80);

if(connect(sock,(struct sockaddr*)&serv, sizeof(serv)) < 0) {
error("Verbindung kann nicht hergestellt werden :(\n");
}

if(send(sock,echostr,strlen(echostr), 0) != strlen(echostr)) {
error("Echostring konnte nicht gesendet werden");
}

else {
printf("Echostring wurde gesendet");
}
return EXIT_SUCCESS;
}

hier das terminal:


gh0st@a450-netbook:~$ cd Desktop
gh0st@a450-netbook:~/Desktop$ ./a.out
Bitte geben sie die Adresse an:
77.91.225.228
Es konnt keine Internetadresse erstellt werden :(
gh0st@a450-netbook:~/Desktop$


liegt an der Eingabe was mache ich falsch?
(sry wenn ich langsam nerve :S)