rendered paste body#include <stdio.h> /* for printf() and fprintf() */#include <sys/socket.h> /* for socket(), bind(), and connect() */#include <arpa/inet.h> /* for sockaddr_in and inet_ntoa() */#include <stdlib.h> /* for atoi() and exit() */#include <string.h> /* for memset() */#include <unistd.h> /* for close() */#include <pthread.h>#include <sys/select.h>#include <sys/time.h>#include <sys/types.h>#include <signal.h>#include "server.h"#define MAXPENDING 5 /* Maximum outstanding connection requests */#define MAX_THREADS 2 /*anzahl maximaler Nutzer */int servSock; /* Socket descriptor fur server */char join_thread[MAX_THREADS]; //feld aktiver threadspthread_t threads[MAX_THREADS]; //fehlt abgearbetieter threadspthread_mutex_t mx_join; //semeaphore für exkl. zugriff/*fangt das Signal Strg+C ab und beendet alles Verbindugen korrekt*/void sighandler(int sig){ if(sig == SIGINT) { printf("caught SIGINT!\n"); close(servSock); exit(1); }}int main(int argc, char *argv[]){ int clntSock; /* Socket descriptor for server */ struct sockaddr_in smtpServAddr; /* Local address */ struct sockaddr_in smtpClntAddr; /* Client address */ unsigned short smtpServPort; /* Server port */ fd_set fds; struct timeval tv; int ret, i; unsigned int clntLen; void *value; signal(SIGINT, sighandler); //sighandler initialisierung pthread_mutex_init( &mx_join, NULL ); //semaphore initialisierung memset(join_thread, 0, sizeof(join_thread)); //initialisierung der thread tabelle if (argc != 2) /* test ob anzahl der argumente korrekt ist */ { fprintf(stderr, "Usage: %s <Server Port>\n", argv[0]); return -1; } smtpServPort = atoi(argv[1]); /* erstes argument: server port */ /* Socket fur eingehende Verbindungen starten */ if ((servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { perror("socket"); return -1; } /* Construct local address structure */ memset(&smtpServAddr, 0, sizeof(smtpServAddr)); /* Zero out structure */ smtpServAddr.sin_family = AF_INET; /* Internet address family */ smtpServAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */ smtpServAddr.sin_port = htons(smtpServPort); /* Local port */ /* Bind an lokale adresse */ if (bind(servSock, (struct sockaddr *) &smtpServAddr, sizeof(smtpServAddr)) < 0) { perror("bind() failed"); return -1; } /* socket wird zyklisch abgehort */ if (listen(servSock, MAXPENDING) < 0) { perror("listen() failed"); return -1; } for (;;) /* endloses warten auf Clienten */ { /* locked */ pthread_mutex_lock( &mx_join ); for(i=0; i<MAX_THREADS; i++) //maximal MAX_THREADS clienten können sich verbinden, danach warten die weiteren in einer warteschlange { if(join_thread[i] == 1) { pthread_join(threads[i], &value); threads[i] = 0; join_thread[i] = 0; } } pthread_mutex_unlock( &mx_join ); /* unlocked */ FD_ZERO(&fds); FD_SET(servSock, &fds); tv.tv_sec = 0; //zeit zyklus in sek tv.tv_usec = 50000; //in mikrosekunden //hier kommt select und createthread hin ret = select(servSock + 1, &fds, NULL, NULL, &tv); //wenn etwas auf den Serversocket ankommt if(ret == 0) continue; // bei 0 mach weiter (beendeter Thread) if(ret < 0) perror("select"); // bei negativen Werten ist ein Fehler aufgetreten for(i=0; i<MAX_THREADS; i++) // ist noch Platz für einen neuen Client ? if(threads[i] == 0 ) break; if(i == MAX_THREADS) // wenn nicht kurz warten { usleep(10000); continue; } // erzeugen des ClientSockets zur direkten Verbindung clntSock = accept(servSock, (struct sockaddr *) &smtpClntAddr, &clntLen); if (clntSock < 0) perror("accept() failed"); /* clntSock is connected to a client! */ printf("Handling client %s\n", inet_ntoa(smtpClntAddr.sin_addr)); ret = pthread_create(&threads[i], 0, (void*)handleClient, (void*) &clntSock); // jeder client bekommt einen Thread if( ret != 0) perror("pthread_create"); } close(servSock); /* wird nie erreicht */}/* jeder Thread bekommt diese Funktion übergeben */void handleClient(void* arg){ struct timeval tv; int sock = *((int*) arg); fd_set fds; char buffer[1024]; int len=0, ret; int id = pthread_self(); int i=0; for (;;) /* endlos */ { FD_ZERO(&fds); FD_SET(sock, &fds); tv.tv_sec = 10; tv.tv_usec = 0; //hier kommt select und createthread hin ret = select(sock + 1, &fds, NULL, NULL, &tv); if(ret == 0) continue; if(ret < 0) perror("select"); memset(buffer, 0, sizeof(buffer)); //bufffer wird mit 0 initialisiert len = read(sock, buffer, 1024); if(len <=0)continue; buffer[1023]='\0'; if(strncmp(buffer, "quit", 4) == 0) //beendung bei eingabe von quit { ret = 0; close(sock); printf("beenden!\n"); /* locked */ pthread_mutex_lock( &mx_join ); for(i=0; i<MAX_THREADS; i++) { if(threads[i] == id) break; } if(i == MAX_THREADS) { printf("ganz schlecht!\n"); exit(1); } join_thread[i] = 1; pthread_mutex_unlock( &mx_join ); /* unlocked */ pthread_exit(&ret); } printf("erhalten: %s", buffer); }}