Projekt Chat & Fragen



  • Hallo,

    Ich arbeite seit geraumer Zeit an einem Chatserver, bin gerade aktuell noch im Anfangsstadium.

    Wollte mal nachfragen, ob ich mit diesem aktuellen Code auf dem guten oder schlechten wege zum erfolg bin, oder ob vielleicht noch jemand ein Vorschlag hätte es besser oder anderst zu machen?

    Natürlich fehlt noch das bekannte fork() aber es soll mal ein Grundgerüst sein wo man drauf aufbauen kann.

    server.cpp

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <time.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <sys/wait.h>
    #include <sys/file.h>
    #include <sys/time.h>
    #include <signal.h>
    #include <fcntl.h>
    
    #include <sys/un.h>
    #include <sys/uio.h>
    
    #define SERVER_PORT 8080
    #define MAX_MSG 400
    #define MAXLINE 259
    #define MAX_USERS 500
    
    #include "server.h"
    #include "request_handler.h"
    
    FILE *log_file;
    char log_string[1024];
    
    struct user {
        int		sock;
        char* 	buf;
    
        char*	addr;
        char*	name;
        char*	session;
    
        int 	killed;
        struct user	*next;
    };
    
    struct list_type {
        struct user	*data;
        unsigned	count;
    };
    
    void init_list(struct list_type *list)
    {
      list->data = NULL;
      list->count = 0;
    }
    
    int add_client(struct list_type *list, int sock)
    {
        struct user *usr;
    
        usr->sock = sock;
        usr->next = list->data;
    
        list->data = usr;
        list->count++;
    
        return 0;
    }
    
    int remove_client(struct list_type *list, int sock)
    {
        struct user *usr, *lst = NULL;
    
        if(!list->count)
    	return 1;
    
        for(usr = list->data; usr; usr =  usr->next)
        {
    	if(usr->sock = sock)
    	    break;
    	lst = usr;
        }
    
        if(!lst)
    	return 1;
    
        if(lst)
    	lst->next = usr->next;
        else
    	list->data = usr->next;
    
        free(usr);
        list->count--;
    
        return 0;
    }
    
    int recv_fd (int sock)
    {
        int bufsize = 2000;
        char *buffer;
    
        recv(sock, buffer, bufsize, 0);
    
        if(buffer != NULL)
            int t1 = ::send(sock, header, strlen(header), 0);
            int t2 = ::send(sock, out_header, strlen(out_header), 0);
    }
    
    void my_log(char* message)
    {
        char log_time[24];
    
        if(log_file == NULL) return;
        time_t mtm;
        mtm = time(NULL);
        strftime(log_time, (size_t)23, "%d-%m-%Y> ", localtime(&mtm));
    
        fputs(log_time, log_file);
        fputs(message, log_file);
        fflush(log_file);
    }
    
    void sigchld_handler (int s)
    {
        exit(1);
    }
    
    int main (void)
    {
        int sockfd, new_fd, retval;
        int c, max, bytes;
        struct list_type list;
    
        fd_set chatList, readList, writeList, problemList;
        struct timeval listen_timeout;
        struct sockaddr_in my_addr;
        struct sockaddr_in their_addr;
        socklen_t sin_size;
        struct sigaction sa;
    
        int yes = 1;
        /*
    	Logfile erstellen und lesen
        */
        log_file = fopen("chat.log", "a");
        if(log_file == NULL) {perror ("Error opening log file"); exit(-1);}
    
        my_addr.sin_family = AF_INET;	/* Host byte Order */
        my_addr.sin_port = htons(SERVER_PORT);
        my_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
        bzero(&(my_addr.sin_zero), 8);
    
        if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    	my_log("ERROR: cannot create socket, Exiting. Other Copy of Chat is started?\n");
    	exit(1);
        }
    
        if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
    	my_log("ERROR: setsockopt(SO_REUSEADDR). Other Copy of Chat is started?  Exiting\n");
    	exit(1);
        }
    
        fcntl(sockfd, F_SETFL, O_NONBLOCK);
        if(bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
    	my_log("problem: Cannot bind to a given ip&port Exiting!\n");
    	exit(1);
        }
    
        if(listen(sockfd, MAX_USERS) == -1) {
    	my_log("problem: cannot listen. Exiting\n");
    	exit(1);
        }
    
        sa.sa_handler = sigchld_handler;
        sigemptyset(&sa.sa_mask);
        sa.sa_flags = SA_RESTART;
    
        if(sigaction(SIGCHLD, &sa, NULL) == -1) {
    	my_log("Sigaction failed ... Exiting\n");
    	exit(1);
        }
    
        init_list(&list);
    
        my_log("Server: Chat-Server laeuft....\n");
    
        while(1)
        {
    	sleep(1); /* sleeping for a second */
    
    	for(int i=0; i < 30; i++)
    	{
    	    listen_timeout.tv_sec = 0;
    	    listen_timeout.tv_usec = 0;
    	    FD_ZERO(&chatList);
    	    FD_SET(sockfd, &chatList);
    	    retval = select(sockfd +1, &chatList, NULL, NULL, &listen_timeout);
    
    	    if(retval > 0)
    	    {
    		if(FD_ISSET(sockfd, &chatList)) {
    		    sin_size = sizeof(struct sockaddr_in);
    
    		    if((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
    			snprintf(log_string, sizeof(log_string), "server: cannot accept connection! %s\n", strerror(errno));
    			my_log(log_string);
    			continue;
    		    }
    
    		    snprintf(log_string, sizeof(log_string), "server: got connection from %s\n", inet_ntoa(their_addr.sin_addr));
    		    my_log(log_string);
    
    		    fcntl(new_fd, F_SETFL, O_NONBLOCK);
    
                        add_client(&list, new_fd);
    
    		    int bla = handle_recv(&list, new_fd);
                        //recv_fd(new_fd);
    		    //close(new_fd);
    		}
    	    } else {break;}
    
              FD_ZERO(&readList);
              FD_ZERO(&writeList);
              FD_ZERO(&problemList);
    	}
    
        }
        close(sockfd);
        return 0;
    }
    

    server.h

    void init_list(struct list_type *list);
    int add_client(struct list_type *list, int sock);
    int remove_client(struct list_type *list, int sock);
    int recv_fd (int sock);
    int handle_recv(struct list_type *list, int sock);
    void my_log(char* message);
    void sigchld_handler (int s);
    int main (void);
    
    char* header = "HTTP/1.0 200 Ok Welcome\015\012Server: Chat\015\012Content-type: text/html\015\012\015\012";
    
    char* out_header = "<html>\n\n" \
                "<head>\n" \
                "<meta http-equiv=\"Content-Language\" content=\"de\">\n" \
                "<meta http-equiv=\"Content-Type\" content=\"text/html\">\n" \
                "<title>Chat</title>\n"\
                "</head>\n\n" \
                "Willkommen im Chat!</font>\n";
    

    request_handler.cpp

    #include <stdio.h>
    #include <sys/socket.h>
    #include <sys/un.h>
    
    #include "request_handler.h"
    
    int handle_recv(struct list_type *list, int sock)
    {
        char temp_buffer[16384];
    
        char *search_http, *search_start;
    
        int result = 0;
        int recv_result = 0;
    
        strcpy(temp_buffer, "");
        result = recv(sock, temp_buffer, sizeof(temp_buffer), 0);
    
        if(result == NULL) return (-1);
    
        int t1 = ::send(sock, header, strlen(header), 0);
        if(t1 == NULL) return (-1);
    
          if(temp_buffer) delete[] temp_buffer;
          return 0;
    }
    
    int handle_req(struct list_type *list, int sock, char *buffer)
    {
      char *search_http, *search_start;
    
            search_start = strstr(temp_buffer, "GET ");
    
            if(search_start == NULL) return result;
            search_http = strstr(search_start, "HTTP/1.");
            search_start = strstr(search_start, "/CHAT?");
    
            if(search_http != NULL && search_start != NULL)
            {
              printf("Chat-Login Versuch\n");
            }
            else
            {
              search_start = strstr(temp_buffer, "GET ");
              search_http = strstr(search_start, "HTTP/1.");
              search_start = strstr(search_start, "/INPUT?");
    
              printf("Chat-Input versuch\n");
            }
    
            return(-1)
    
    }
    


  • Niemand lust oder keine Zeit oder kein Bock? 🙄



  • die Funktion recv_fd ist falsch. Du hast für den buffer keinen Speicher geholt.



  • Ich denke nicht das es viele gibt deinen Code durchzugehen.
    Funktioniert er?

    JA. Dann ist es gut.
    NEIN: Debugge und frage dann.



  • ich hab das jetzt mal nur so ueberflogen,
    was mir aber direkt aufgefallen ist:
    - warum benutzt du keine container klasse aus der stl?
    - warum keine klassen (evtl die sockets schoen kapseln,
    das chat-protokol und das buffer handling)
    - warum FILE und puts statt streams?



  • Sany schrieb:

    result = recv(sock, temp_buffer, sizeof(temp_buffer), 0);
    
        if(result == NULL) return (-1);
    
        int t1 = ::send(sock, header, strlen(header), 0);
        if(t1 == NULL) return (-1);
    

    send/recv (und die meisten anderen socket-funktionen) geben -1 zurueck
    im fehlerfall. 0 sagt, dass keine daten mehr gelesen zum lesen
    vorhanden sind (z.b. gegenseite hat die verbindung abgebaut).
    der vergleich auf NULL ist da schlecht oder zumindest irrefuehrend
    (NULL wird bei vergleichen mit pointern eingesetzt).


Anmelden zum Antworten