All pastes #502342 Raw Edit

Untitled

public c v1 · immutable
·published 2007-05-22 14:06 UTC
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);    }}