Problem mit Client->Server und Socket()
-
Hi Zusammen,
wollte eine server-anwendung erstellen, welche auf port 1234 lauscht. Wenn der client zu ihm verbindet, schickt er an den server einen string. Dieser wird vom server empfangen und in einer funktion (parseInstr) geparsed, d.h. in token zerlegt und danach werden bestimtme interne variablen gesetzt.
Das problem ist, dass wenn ich mit dem clienten diesen string abschicke, der server diesen zwar korrekt empfängt und auch parsed, jedoch dies in einer endlos-schleife tut, obwohl ich mit dem clienten nur ein einziges mal diesen string an den server geschickt hab. Jegliche versuche meinerseits dies zu unterbinden, schlugen fehl. Ursache ist wohl, dass ich das server-seite empfangen mit einer for-schleife á la for(;;) realisiert habe. Ich dachte jedoch, dass er nur in dieser schleife reagiert, wenn auch wirklich eine anfrage vom client kommt. Aber anscheinend tut er das auch, nachdem die anfrage vom clienten längst gesendet wurde (wie gesagt unendlich oft).
Hier die funktion, welche auf anfragen vom clienten wartet.:
int waitForCon(void) { // Local variables & initialization long int sockfd = 0, fd = 0, bindfd = 0, listenfd = 0, rcv_msg = 0; unsigned int len; struct sockaddr_in server, client; char echo_buf[RCVBUFSIZE]; int i=1; memset(&server, 0, sizeof(server)); printf("[+] Entering daemon mode...\n"); // Requesting a socket sockfd = socket(AF_INET, SOCK_STREAM, 0); if(sockfd == -1) { perror("socket()"); return 1; }else{ printf("[+] Created socket for incoming connections...\n"); } // Set connection details and bind port to socket server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); //INADDR_ANY > Server reachable from everywhere server.sin_port = htons(PORT); bindfd = bind(sockfd, (struct sockaddr*)&server, sizeof(server)); if(bindfd == -1) { perror("bind() - If bind is in use already, check for malware/trojans!"); return 1; }else{ printf("[+] Binding socket to port %d...\n", ntohs(server.sin_port)); } // Listening on socket listenfd = listen(sockfd, 5); if(listenfd == -1) { perror("listen():"); return 1; }else{ printf("[+] Waiting for instructions...\n"); } for (;;) { len = sizeof(client); fd = accept(sockfd, (struct sockaddr*)&client, &len); if(fd == -1) { perror("[-] accept():"); return 1; } rcv_msg = recv(fd, echo_buf, RCVBUFSIZE, 0); if(rcv_msg == -1) { perror("[-] recv()"); return 1; } echo_buf[rcv_msg] = '\0'; printf("[+] Incoming instruction from %s\n", inet_ntoa(client.sin_addr)); printf("[+] Instruction: %s\n", echo_buf); printf("parsing...\n"); if(parseInstr(echo_buf) == -1) { return 1; } } //Socket schliessen printf("closing socket\n"); close(sockfd); return 0; }
parseInstr(echo_buf) ist jedenfalls die funktion, welche den empfangen string in token zerlegt und danach unterfunktionen aufruft.
Habe bereits veruscht mit close(sockfd) oder einem shutdown(sockfd, SHUT_RDWR) das problem zu lösen.
Ich versteh einfach die funktionsweise nicht bzw. die hintergründe, warum er etwas empfängt, wenn nichts gesendet wird.
Kann mich bitte einer aufklären?
Danke
dipset
-
So ich hoffe ich kann dir helfen
Wenn der Client nur einmal was zu schicken soll und dann nichts mehr. Also sprich du verwaltest nur einen Clienten dann würde ich folgenden Code vorschlagen
[cpp]
int waitForCon(void)
{
// Local variables & initializationlong int sockfd = 0, fd = 0, bindfd = 0, listenfd = 0, rcv_msg = 0;
unsigned int len;
struct sockaddr_in server, client;
char echo_buf[RCVBUFSIZE];
int i=1;
memset(&server, 0, sizeof(server));printf("[+] Entering daemon mode...\n");
// Requesting a socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1)
{
perror("socket()");
return 1;
}else{
printf("[+] Created socket for incoming connections...\n");
}// Set connection details and bind port to socket
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY); //INADDR_ANY > Server reachable from everywhere
server.sin_port = htons(PORT);
bindfd = bind(sockfd, (struct sockaddr*)&server, sizeof(server));
if(bindfd == -1)
{
perror("bind() - If bind is in use already, check for malware/trojans!");
return 1;
}else{
printf("[+] Binding socket to port %d...\n", ntohs(server.sin_port));
}// Listening on socket
listenfd = listen(sockfd, 5);
if(listenfd == -1)
{
perror("listen():");
return 1;
}else{
printf("[+] Waiting for instructions...\n");
}len = sizeof(client);
if(fd = accept(sockfd, (struct sockaddr*)&client, &len)>0)
{
if(fd == -1)
{
return 1;
}
rcv_msg = recv(fd, echo_buf, RCVBUFSIZE, 0);
if(rcv_msg == -1)
{
return 1;
}
echo_buf[rcv_msg] = '\0';
printf("[+] Incoming instruction from %s\n", inet_ntoa(client.sin_addr));
printf("[+] Instruction: %s\n", echo_buf);
printf("parsing...\n");
if(parseInstr(echo_buf) == -1)
{
return 1;
}}
//Socket schliessen
printf("closing socket\n");
close(sockfd);return 0;
}[code]Falls du mehere Clients versorgen musst kommst du nicht um Threads oder Prozesse drum herum
-
Hey Cefour,
danke für deine antwort. Momentan steh ich aber noch immer vor einem problem:
Wenn ich, wie du vorgeschlagen hast, die for-schleife weglassen, dann passiert folgendes: Ich starte den server, schicke mit dem client eine nachricht, der server verarbeitet sie korrekt und das server-programm wird beendet. Ist ja auch klar.
Darum hab ich in der waitForCon-aufrufenden main()-funktion, um den funktions aufruf von waitForCon eine for-schleife á la for(;;) erstellt. Nun funktioniert es FAST: Nachdem der client die nachricht verschickt hat und der server sie ordentlich verarbeitet hat, verlässt er die waitForCon-Funktion und springt gleich wieder rein. D.h. er erstellt nen neune socket, bindet ihn an den port etc. Und das ist das Problem: es kommt immer:
bind(): Address already in use!
Ich hab kurz vor ende der waitForCon funktion ein sleep(10); eingebaut, um abzuwarten, bis der port wieder freigegeben wird, aber egal wie lang ich warte, es kommt immer die bind-fehlermeldung. Gibt es eine funktion, um den port wieder friezugbeen, damit ich erneut binden kann?
Danke nochmal,
dipset
-
Kann mir hier evtl. noch jemand beistehen? BHabe die vermutung, dass die lösung simpler ist, als ich annehme.
DipSet
-
int waitForCon(void) { // Local variables & initialization long int sockfd = 0, fd = 0, bindfd = 0, listenfd = 0, rcv_msg = 0; unsigned int len; struct sockaddr_in server, client; char echo_buf[RCVBUFSIZE]; int i=1; memset(&server, 0, sizeof(server)); printf("[+] Entering daemon mode...\n"); // Requesting a socket sockfd = socket(AF_INET, SOCK_STREAM, 0); if(sockfd == -1) { perror("socket()"); return 1; }else{ printf("[+] Created socket for incoming connections...\n"); } // Set connection details and bind port to socket server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); //INADDR_ANY > Server reachable from everywhere server.sin_port = htons(PORT); bindfd = bind(sockfd, (struct sockaddr*)&server, sizeof(server)); if(bindfd == -1) { perror("bind() - If bind is in use already, check for malware/trojans!"); return 1; }else{ printf("[+] Binding socket to port %d...\n", ntohs(server.sin_port)); } // Listening on socket listenfd = listen(sockfd, 5); if(listenfd == -1) { perror("listen():"); return 1; }else{ printf("[+] Waiting for instructions...\n"); } [b]do[/b] { len = sizeof(client); fd = accept(sockfd, (struct sockaddr*)&client, &len); if(fd == -1) { perror("[-] accept():"); return 1; } rcv_msg = recv(fd, echo_buf, RCVBUFSIZE, 0); if(rcv_msg == -1) { perror("[-] recv()"); return 1; } echo_buf[rcv_msg] = '\0'; printf("[+] Incoming instruction from %s\n", inet_ntoa(client.sin_addr)); printf("[+] Instruction: %s\n", echo_buf); printf("parsing...\n"); }[b] while (parseInstr(echo_buf) == -1);[/b] //Socket schliessen printf("closing socket\n"); close(sockfd); return 0; }
So würde ich es machen. Ist jetzt schnell gepostet aber ich denke dass er jetzt so lange Daten empfängt, bis er etwas mit ihnen anfangen kann. Hoffe ich konnte dir helfen!
mfg Clemens
-
Danke, werd das mal ausprobieren