Archiv verlassen und diese Seite im Standarddesign anzeigen : gehversuche socketprogrammierung in C
nasontyphalt
08-02-2006, 18:07
Ahoi!
Ich versuche mich zur Zeit an der Socketprogrammierung und folgender, nicht funktionierender Code ist dabei bis jetzt herausgekommen.
Wenn ich das Programm starte gibt es nur
connect(): connection timed out
Broken pipe
aus.
Alles andere was es eigentlich ausgeben sollte gibt es nicht aus, auch die sachen, die vor connect() stehen.
#include <stdio.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#define PUFFER 1024
main(){
int schuh=socket(PF_INET,SOCK_STREAM,0);
struct sockaddr_in{
sa_family_t sin_family;
unsigned short int sin_port;
struct in_addr sin_addr;
char pad[8];
};
struct sockaddr_in addr;
addr.sin_family=PF_INET;
addr.sin_addr.s_addr=inet_addr("xxx.xxx.xxx.xxx");
addr.sin_port=htons(80);
char login[255]="bla";
char timestamp_string[11];
time_t timestamp;
time(×tamp);
sprintf(timestamp_string,"%l",timestamp);
printf("%s",timestamp_string);
strcat(login,timestamp_string);
strcat(login,"bla");
printf("%s",login);
if(connect(schuh,(struct sockaddr *)&addr,sizeof(addr))==-1)perror("connect()");
if(send(schuh,login,strlen(login),0)==-1)perror("send()");
if(recv(schuh,login,PUFFER,0)==-1)perror("recv()");
if(close(schuh)==-1)perror("close()");
}
Ich hoffe, dass mir irgendjemand helfen kann. Am besten wäre noch ein Ansatz, wie ich an die Lösung solcher Probleme herangehe. Bei Netzwerkgeschichten, kann mir ja wohl gdb auch nicht wirklich weiterhelfen, oder?
Auf den ersten Blick stellt sich für mich die Frage, warum Du die Struktur sockaddr_in definierst. Diese steht doch bereits in sys/socket.h.
nasontyphalt
08-02-2006, 22:05
In erster Linie, weil es in dem Tutorial nach dem ich vorgegangen bin so drinstand... kann natürlich sein, dass ich das falsch verstanden habe.
Ohne sockaddr_in ändert sich jedoch nichts. Die Ausgaben sind die gleichen.
addr.sin_family=AF_INET; (nicht PF_INET)
und anstatt der veralteten Funktion
unsigned long int inet_addr(const char *cp);
solltest Du
int inet_aton(const char *cp, struct in_addr *inp);
verwenden.
nasontyphalt
09-02-2006, 16:40
Was hat es eigentlich mit AF_INET und PF_INET auf sich? Ich habe im Netz beide Versionen gefunden.
Nach den von dir vorgeschlagenen Änderungen, gibt das Programm jetzt folgendes aus:
connect(): Address family not supported by protocol
Broken pipe
Einmal ist es die Protokollfamilie (PF_INET) und das andere Mal die Adressfamilie (AF_INET).
Ersteres steht im socket-Aufruf, letzteres im connect-Aufruf bzw. in der Struktur der Socket-Adresse (sockaddr_in).
Wie schaut Dein Programm mittlerweilen aus?
Und bitte in einem schöneren Stil (Variablen-Deklarationen am Anfang und einen Block innerhalb geschweifter Klammern etwas einrücken).
Auch Leerzeilen erhöhen die Übersicht.
P.S. Bin ab morgen im Skifahren. Es sollte sich dann also noch jemand anders mit dranhängen.
nasontyphalt
09-02-2006, 19:26
#include <stdio.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#define PUFFER 1024
main(){
int schuh=socket(PF_INET,SOCK_STREAM,0);
struct sockaddr_in addr;
char login[255]="eine Information";
/* Einen Timestamp erzeugen und als String an 'login' ranhängen: */
char timestamp_string[11];
time_t timestamp;
time(×tamp);
sprintf(timestamp_string,"%l",timestamp);
strcat(login,timestamp_string);
/* nach dem Timestamp weitere Informationen ranhängen: */
strcat(login,"eine weitere Information");
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=inet_aton("xxx.xxx.xxx.xxx",&addr);
addr.sin_port=htons(80);
if( connect(schuh,(struct sockaddr *)&addr,sizeof(addr))==-1 ) perror("connect()");
if( send(schuh,login,strlen(login),0) == -1 ) perror("send()");
if( recv(schuh,login,1024,0) == -1 ) perror("recv()");
if( close(schuh) == -1 ) perror("close()");
}
Diese Zeile ist noch falsch!
addr.sin_addr.s_addr=inet_aton("xxx.xxx.xxx.xxx",&addr); inet_aton gibt einen int zurück: 0, wenn keine gültige IP-Adresse referiert wird (Eingabe in der falschen Form).
Deshalb muss es so heißen:
inet_aton("xxx.xxx.xxx.xxx", &addr.sin_addr);
kleiner Tipp:
Gut wäre noch, wenn Du dies in eine if-Abfrage einbindest und bei einem Fehler (eine Exception wirfst oder) eine Fehlerausgabe machst. Gleiches gilt für die Aufrufe von socket, connect usw.
Anhand des Codes wuerd ich mal sagen du programmierst noch ned lange ! Soll keine Vorwurf oder ne herabwuerdigung sein, weil jeder von uns faengt mal an.
Aber ich wuerd meine gehversuche nicht gleich mit so nem komplexen Thema beginnen. C iss schon schwer, sich dann noch zusaetzlich mit sockets auseinander zu setzen kann schnell frustrierend werden ....
if( recv(schuh,login,1024,0) == -1 ) perror("recv()");
dein login is 255 byte gross, du laesst den socket aber 1024 byte da reinschreiben, wenn die gegenstelle mal wirklich mehr wie 255 byte sendet, wirst an der stelle hier viel freude haben ^^
entweder nimm nen anderen buffer oder schraub die groesse runter ...
noch nen genereller tip ....
wenn du in buffer / char arrays schreibst, wo du die Groesse kennst (weils selber deklariert hasst) dann nimm statt den str funktionen (strcpy,strcat) lieber die strn funktionen (strncpy, strncat) . Ist sicherer ....
Ciao ...
nasontyphalt
10-02-2006, 17:59
Das ich noch nicht lange programmiere stimmt schon, ich denke aber schon, dass ich soweit bin, mich auch mit sockets auseinanderzusetzen. Solange ich die Motivation dazu aufbringen kann ist das doch in Ordnung...
Was den Stil angeht, sehe ich auch, dass es vieles zu verbessern gibt, allerdings will ich erstmal erfolgreich überhaupt eine Verbindung hinbekommen, und mich dann um das drumherum kümmern.
Die Verbindung kommt übrigens immernoch nicht zu stande. connect() gibt, egal zu welcher Adresse ich verbinden will, nur nen timeout aus.
Kann das vielleicht noch an den Routereinstellungen liegen? Port 80 ist auf alle Fälle frei, ist ja auch standard...
Meine Firewallkonfiguration habe ich testweise auch mal kurz leergespühlt, was auch keine anderen resultate hervorbrachte...
Was den Stil angeht, sehe ich auch, dass es vieles zu verbessern gibt, allerdings will ich erstmal erfolgreich überhaupt eine Verbindung hinbekommen, und mich dann um das drumherum kümmern.
Die Verbindung kommt übrigens immernoch nicht zu stande. connect() gibt, egal zu welcher Adresse ich verbinden will, nur nen timeout aus.
nun ja, wenn du vorneweg gleich den stil übst, dann ist das programm leichter lesbar und wird auch lieber gelesen ;-). somit finden sich auch leichter fehler.....
hier noch eine quelle zu dem thema ...(socket)
http://www.zotteljedi.de/doc/socket-tipps/druckversion.html
vielleicht hilft es dir bei der fehlersuche ...
gruesse
Vincent Vega
23-02-2006, 13:23
Also ich hab' jetzt keine Lust zu versuchen, Deinen Code zu verstehen, aber hier gibt's ein Beispiel, das mit Sicherheit funktioniert:
http://www.openbsd.org/cgi-bin/man.cgi?query=getaddrinfo&apropos=0&sektion=0&manpath=OpenBSD+Current&arch=i386&format=html
hmm also was du mit deinem Code bezweckst ist mir nicht so ganz klar ... Allerdings bin ich der Meinung das du deinen Stil zu programmieren mal überdenken solltest, die nicht vorhandenen Einrückungen sowie das Fehlen von Header-Files spricht nicht grad dafuer das du dich mit der Thematik beschäftigt hast. Mein Code ist nicht perfekt, allerdings bin ich auch kein Freund von vorgefertigten lösungen also hab ich nicht alles bearbeitet, sondern es erstmal nur die groebsten Fehler behoben:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/types.h>
#include <time.h>
#define PUFFER 1024
int main(int argc, char *argv[]) {
int sockfd;
char login[255];
struct sockaddr_in addr;
memset(login, 0, 255);
if((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
exit(1);
}
addr.sin_family=AF_INET;
inet_aton("127.0.0.1", &addr.sin_addr);
addr.sin_port=htons(80);
if(connect(sockfd, (struct sockaddr *) &addr, sizeof(addr)) <0) {
perror("connect()");
close(sockfd);
exit(1);
}
/* XXX
* anstatt send und recv wuerde ich write und read empfehlen
*/
if(send(sockfd, login, strlen(login), 0) < 0)
perror("send()");
/* XXX
* hier ist nen ganz bloeder fehler, du willst 1024 Bytes
* in nen 255 char-Array schieben
*/
if( recv(sockfd, login, 1024, 0) == -1 )
perror("recv()");
if(close(sockfd) < 0)
perror("close()");
return 0;
}
Ein weitere Fehler war das du nach einem nicht geklappten connect trotzdem einen send() ausführst was zu deinem Fehler brokenpipe führt. Ein paar Fehler hab ich dir noch gelassen! ;)
Zum übersetzen und linken empfehle ich dir folgende Zeile:
gcc -Wall -g -Werror -o test test.c
Achja selbsterklärende Variablenbezeichnung dienen nicht nur dir sondern auch uns wenn wir dein Programm verstehen sollen und du willst das wir dir helfen.
mfg tanis
hallo
ich habe mich auch vor kurzem damit ausseinander gesetzt und habe das hier benutzt
http://www.pronix.de/pronix-865.html
ich fand es deswegen gut weil es auch alles gut erklaert. Noch ein Tipp von mir FALLST du die moeglichkeit dazu hast versuche den code man auf einem solaris 10 zu schreiben, dann gewoehnt man sich schnell daran mal die 'man' mal anzuschauen da steht dann eine menge dazu drin, und das braucht man dann weil der code doch sehr verschieden zu linux z.B dann wird
mfg
gsus
Powered by vBulletin® Version 4.2.5 Copyright ©2025 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.