socket()-problem
-
Hi folks,
hab meinen code soweit mal geschrieben, das prog läuft auch, nur kann ich
die bind() funktion nicht 2 mal hintereinander aufrufen. Woran liegt das?
Wie gesagt, einmal kann ich eine datei empfangen, beim 2ten mal kommt bind() error. Hat jemand ne idee, das ich meinen kerm1t zum laufen krieg.#include <stdio.h> #include <string.h> #include <ctype.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <arpa/inet.h> #define CLS printf("\033[H\033[2J") #define CKB while(getchar()!='\n') #define PORT 4666 #define BUF_SIZE 1024 //declarations int send_file(void); int recv_file(void); //functions int send_file(void) { FILE *fp; char file[128], ip[16], *buffer, c; int sockfd, i=0, block=0; struct sockaddr_in target; printf("\n\tf1le, u like t0 s3nd: "); scanf("%s", file); CKB; printf("\n\tip-addr of t4rget syst3m: "); scanf("%s", ip); CKB; if ( (sockfd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == -1 ) { printf("socket() error\n"); return 2; } target.sin_family=AF_INET; target.sin_port=htons(PORT); target.sin_addr.s_addr=inet_addr(ip); printf("\tconnect... "); if ( connect(sockfd,(struct sockaddr *)&target, sizeof(target)) == -1 ) { printf("connect() error\n"); return 3; } printf(" OK\n\tn0w, s3nd 7he f1le...\n"); if ( (buffer=(char *)malloc(sizeof(char)*BUF_SIZE)) == NULL ) { printf("\ncouldn´t allocate 1024byte\n"); return 4; } if ( (fp=fopen(file,"rb")) == NULL ) { printf("open file failed\n"); return 1; } while ((buffer[i]=fgetc(fp)) != EOF) { if (i == 1023) { if ( send(sockfd,buffer,BUF_SIZE,0) != 1024 ) { printf("send() error\n"); return 5; } block++; i=0; } i++; } if ( send(sockfd,buffer,i,0) != i ) { printf("send() error\n"); return 5; } printf("\t%d bytes were send to %s \n\n", i+block*1024, ip); printf("-------------------------------------------\n"); fclose(fp); close(sockfd); return 0; } int recv_file(void) { int s, sockfd, len, tmp; char c, file[128]; struct sockaddr_in me, client; FILE *fp; printf("\n\tf1lename t0 wr1te d4t4 1n: "); scanf("%s", file); CKB; printf("\n\tw4it1ng f0r d4ta...\n"); if ( (fp=fopen(file,"wb")) == NULL ) { printf("couldn´t open file %s", file); return 5; } if ( (s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == -1 ) { printf("socket() error\n"); return 1; } me.sin_family=AF_INET; me.sin_port=htons(PORT); me.sin_addr.s_addr=htonl(INADDR_ANY); if ( bind(s,(struct sockaddr*)&me, sizeof(me)) == -1 ) { printf("bind() error\n"); return 2; } if ( listen(s,5) == -1 ) { printf ("listen() error\n"); return 3; } len=sizeof(client); if ( (sockfd=accept(s,(struct sockaddr*)&client,&len)) == -1 ) { printf ("accept() error\n"); return 4; } len=0; while ( recv(sockfd, &c, 1, 0) ) { fprintf(fp,"%c", c); len++; } printf("\n\t%d bytes received\n", len); printf("\td4t4 s4v3d 1n %s\n", file); printf("-------------------------------------------\n"); fclose(fp); close(s); close(client); return 0; } int main(int argc, char *arvg[]) { char choice, ret; CLS; while (1) { printf("\n\t\tkerm1t ;-)\tby b4sh0r\n\n"); printf("\t(0) --> exit \n"); printf("\t(1) --> send a file \n"); printf("\t(2) --> recv a file \n\n\t>"); scanf("%c", &choice); CKB; switch (choice) { case '0' : return 0; case '1' : ret=send_file(); if (ret!=0) return ret; break; case '2' : ret=recv_file(); if (ret!=0) return ret; break; default : perror("not a valid option, a******, so cu\n"); return 1; } } printf("bye...\n"); return 0; }
tH><
-
Nabend,
das funktioniert deshalb nicht, weil der Port dann noch besetzt ist.
Folgendes hebt das auf:
int opt = 1; if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) == -1) { perror("(setsockopt) "); return; }
mfg
v R
-
jo, danke @Realisticer, das funzt super, ich muss mir jedoch noch über die bedeutung der funktion setsockopt klar werden.
THX
-
/bin/bash0R schrieb:
jo, danke @Realisticer, das funzt super, ich muss mir jedoch noch über die bedeutung der funktion setsockopt klar werden.
THX
Damit hat man die Moeglichkeit, Socketoptionen zu manipulieren. Fuer eine
ausfuehrliche Beschreibung, schaust du dir am besten die Manpage an.mfg
v R
-
@/bin/bash0R
Nächste Aufgabe
Warum funktioniert der kerm1t bei Dir und bei mir nicht?
Ich habe den Code erstmal so übernommen (ohne die Änderung von virtuell Realisticer). Kopilieren ließ er sich ohne Probleme und arbeiten tut das Proggi auch, aber die Dateien, die ich senden will, kommen nicht heil an! immer nur ein paar Bytes. Mal 105 und mal wieder 724. Wie siehts bei Dir aus?
-
Dieser Thread wurde von Moderator/in AJ aus dem Forum ANSI C in das Forum Linux/Unix verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
gamma schrieb:
@/bin/bash0R
Nächste Aufgabe
Warum funktioniert der kerm1t bei Dir und bei mir nicht?
Ich habe den Code erstmal so übernommen (ohne die Änderung von virtuell Realisticer). Kopilieren ließ er sich ohne Probleme und arbeiten tut das Proggi auch, aber die Dateien, die ich senden will, kommen nicht heil an! immer nur ein paar Bytes. Mal 105 und mal wieder 724. Wie siehts bei Dir aus?Das liegt daran, dass send bzw. recv nicht in einer Schleife aufgerufen werden.
Angenommen du hast eine 5MB-Datei, wie soll diese auf einmal gesendet werden?
Du sendest ja immer nur buff_size-grosse Pakete. Genauso muss recv ebenfalls in
eine Schleife gepackt werden.mfg
v R
-
Frohes Neues!
@virtuell Realisticer
Schön, daß Du mithilfst, danke!Ich habe nun auch noch ein bißchen Zeit gefunden, um zu testen!
Ich habe dazu auch Deinen Codeschnipsel mit der setsockopt() funktion oberhalb von bind() kopiert und somit kann man nun bind() x- beliebig oft aufrufen.Angenommen du hast eine 5MB-Datei, wie soll diese auf einmal gesendet werden?
Keine Ahnung, aber vielleicht mit einer Schleife, die warscheinlich schon längst da ist!?:), denn mit einer Textdatei geht es! Zwar nicht besonders gut, aber ein Ansatz ist da .
Also mit verschiedenen anderen Dateien, wie bmp,exe, bin etc habe ich es auch versucht und da kommt nichts vernünftiges bei rum. Unabhängig von der "Ausgangsgröße" der Datei, kommen auf der anderen Seite nur ein paar Bytes angekleckert. Mal mehr mal weniger.
Das lustige ist, wenn ich meine 5 MBgroße Textdatei versende kommen auf der anderen Seiter mehr Bytes an, als ich versandt habe. Ich habe die Files mit diff verglichen und dabei festgestell, daß der Kerm1t alle 1023 bytes ein "h" mit einfügt.
Wobei er das bei kleinen Dateien nicht tut, aber dafür macht er den Zeilenumbrüche an beliebigen Stellen etc.
Also ich bin echt gern bereit mit zu testen, aber ich weiß beim besten Willen nicht wo man da was ändern kann, Hab ja nun schon lange genug die Stelle gesucht, an der man die Schleife einbauen kann.
-
so, ich nochmal
Also weshalb man mit diesem Code eine Textdatei nicht richtig versenden kann, liegt wohl an der verkorksten Schleife. Verstehe auch nicht, warum send 2x aufgerufen wird und warum 1023 bytes in den buffer geschrieben werden und 1024 gesendet werden.while ((buffer[i]=fgetc(fp)) != EOF) {
if (i == 1023) {
if ( send(sockfd,buffer,BUF_SIZE,0) != 1024 ) {
printf("send() error\n");
return 5;
}
block++;
i=0;
}
i++;
}if ( send(sockfd,buffer,i,0) != i ) {
printf("send() error\n");
return 5;
}Also ich habe jetzt mal den 2ten send Call rausgenommen,
if (i == 1023) auf if (i == 1024) gesetzt. Damit kommt dann schon mal die richtige Anzahl an Bytes an, aber aufgrund der "komischen" Schleife, wird das erste Zeichen aus der zu versendenden Textdatei immer wieder mit dem nächsten send Call verschickt. Ich meine daran ist das i++ Schuld. Der zweite send Call startet ja dann schon mit 1 und nicht mit 0.block++;
i=0;
}
i++;so gehts aber auch nicht:
[quote]
while ((buffer[i]=fgetc(fp)) != EOF)
{
if (i == 1024)
{if ( send(sockfd,buffer,BUF_SIZE,0) != 1024 )
{
printf("send() error\n");
return 5;
}
block++;
i=-1;
}
printf("\ti = %d \n", i);
i++;
}
[quote]Hat jemand da mal ne clevere Lösung zur Hand?
-
sorry, der letzte Abschnitt ist bißchen verunglückt.
meinte so hier gehts auch nicht:
while ((buffer[i]=fgetc(fp)) != EOF)
{
if (i == 1024)
{
if ( send(sockfd,buffer,BUF_SIZE,0) != 1024 )
{
printf("send() error\n");
return 5;
}
block++;
i=-1;
}
printf("\ti = %d \n", i);
i++;}
-
Hallo zusammen!
mir kommt vor, daß da ein grundsätzlicher Fehler drinnen ist:send() kann so viele Bytes senden, wie es will. Deshalb muß man abfragen, wie viele davon auch durchgegangen sind. Und den Rest wieder senden.
Ich stell mir das so vor (ungetestet):
int finished=0; char *data_to_send=... char *pos=data_to_send; int sent_bytes=0; int total_sent_bytes=0; while (!(finished)) { sent_bytes=send(sock,pos,strlen(pos),0); total_sent_bytes += sent_bytes; pos += sent_bytes; finished = (total_sent_bytes == strlen(data_to_send)); }
Man darf keine Annahmen über die Länge der übertragenen Pakete machen. Wenn man beispielsweise 8000 bytes und gleich darauf 9000 bytes sendet, kann durchaus 1 Paket mit 17000 bytes rauskommen, aber auch eines mit 1 byte und noch eines mit 16999.
HTH, Joe