TCP-Server mit mehreren Clients



  • Hallo,

    ich möchte auf einem TCP-Server (unter Linux) parallel mehrere Clients versorgen können. Das heißt es können mehrere Clients parallel verbunden sein.

    Dazu eignet sich ja die Funktion select().

    Ich habe es leider nicht hinbekommen, dass der Server mithilfe von select Verbindungsaufbauwünsche entgegenehmen kann. Er gibt dann immer aus, dass keine neue Verbindung da ist und select() blockiert demnach. Wenn sich ein Client erfolgreich verbindet, ändert sich nichts davon.

    Ich habe den Code, da er sehr komplex ist, aufs nötigste vereinfacht um die Stelle die das Problem ist übersichtlicher zu machen.

    Hier der Code des Servers :

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <netinet/in.h>
    #include <fcntl.h>
    #include <errno.h>
    
    int main(){
    
    	int server = socket(AF_INET, SOCK_STREAM, 0);
    	if(server < 0){ 
    		printf("Fehler beim erstellen des Sockets\n");
    		return EXIT_FAILURE;
    	}
    
    	struct sockaddr_in myaddr;
    	memset(&myaddr, 0, sizeof(myaddr));
    	myaddr.sin_family = AF_INET;
    	myaddr.sin_port = htons(4711);			
    	myaddr.sin_addr.s_addr = htonl(INADDR_ANY);	
    
    	int q = sizeof(struct sockaddr_in);
    	if(bind(server, (struct sockaddr *) &myaddr, q) < 0){
    		printf("Fehler beim Binden\n");
    		return EXIT_FAILURE;
    	}
    
    	if(listen(server, 5) < 0){
    		printf("Fehler bei listen()\n");
    	}
    
    	fd_set listen_set;
    	int res1;
    	int i=0;
    	int newsock;
    	struct sockaddr_in newaddr;
    	memset(&newaddr, 0, sizeof(newaddr));
    	socklen_t q1 = sizeof(struct sockaddr_in);
    	char buffer[128];
    	int fd[10];
    
    	while(1) {
    		printf("Neuer Durchlauf while(1)\n");
    		FD_ZERO(&listen_set);
    		FD_SET(server, &listen_set);
    		res1 = select((i+1), &listen_set, NULL, NULL, NULL);
    		printf("%i Verbindungen bereit\n",res1);
    		if(FD_ISSET(server,&listen_set)) {
    			newsock = accept(server,(struct sockaddr *) &newaddr,&q1);
    			if(newsock < 0) {printf("accept erfolglos\n");}
    			else {
    				read(newsock,&buffer,128);
    				fd[i] = newsock;
    				i++;
    				}
    			}
    		printf("Ende while(1)\n");
    	}
    
    	return 0;
    }
    

    .. reagiert nicht auf neue Verbindungen.

    Und hier der Client :

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <netinet/in.h>
    #include <fcntl.h>
    #include <errno.h>
    
    int main()
    {
    
    	int client = socket(AF_INET, SOCK_STREAM, 0);
    	if(client < 0){ 
    		printf("Fehler beim erstellen des Sockets\n");
    		return EXIT_FAILURE;
    	}
    
    	struct sockaddr_in serveraddr;
    	memset(&serveraddr, 0, sizeof(serveraddr));
    	serveraddr.sin_family = AF_INET;
    
    	printf("Welche IP-Adresse hat der Server?\n"); 
    	char ipaddr[16];
    	scanf("%s",ipaddr);
    
    	serveraddr.sin_addr.s_addr = inet_addr(ipaddr);
    	serveraddr.sin_port = htons(4711);
    
    	int cn = connect(client,(struct sockaddr *) &serveraddr,sizeof(serveraddr));
    	if(cn == -1){
    		printf("Fehler beim Verbinden mit dem Server\n");
    		return EXIT_FAILURE;
    	}
    	printf("connect = %i\n",cn); // Ausgabe 0 (bei localhost) , also korrekt
    
    	printf("Verbunden mit %s\n",ipaddr);
    	char buffer[128];
    	while(1){
    	scanf("%s",buffer);
    	write(client,&buffer,128); }
    
    close(client);
    return 0;
    }
    

    Der Server kann die Daten bei dem Code natürlich nicht empfangen, aber es geht ja erstmal darum dass der Client korrekt akzeptiert wird und mehrere Clients parallel verbunden werden können.

    Ich hoffe, es kann mir jemand helfen.

    lg



  • So, habs jetzt selber herausgefunden. Es lag daran, dass das System dem FD für den Server nicht 1 sondern 3 zugeordnet hat. Ich hab es so gelöst, dass für select immer der maximale Wert der vorhandenen File-Deskriptoren verwendet wird (und nicht i+1).


Anmelden zum Antworten