Thread: Need help with running multiple theads

  1. #16
    Registered User
    Join Date
    May 2016
    Posts
    31
    No it does work if I just call test_proxy.

  2. #17
    Registered User
    Join Date
    May 2016
    Posts
    31
    Could the threads be running simultaneously and thats why the printf statements are out of order? Also, besides that, the program quits early without any error.

  3. #18
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Quote Originally Posted by watchintv View Post
    I added the definition for POSIX_SOURCE
    That's incorrect. You're missing the initial underscore. And remember that it needs to be before the string.h include. Actually, maybe it needs to be before all the includes.

    What system are you on?

  4. #19
    Registered User
    Join Date
    May 2016
    Posts
    31
    Yeah its got the underscore. Im on linux.

  5. #20
    Registered User
    Join Date
    May 2016
    Posts
    31
    So, Im having luck with putting a mutex lock around everything in test_proxy. strtok_r works fine now. Great.

    Theres just one problem, whhen one of my send/rec functions fail, connect for example, execution stops completely. Why would this be? This would be in the middle of the mutex lock.

  6. #21
    Registered User
    Join Date
    May 2016
    Posts
    31
    Not sure mutexes are what want here since I want the thread functions to operate concurrently.

  7. #22
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Quote Originally Posted by watchintv View Post
    So, Im having luck with putting a mutex lock around everything in test_proxy. strtok_r works fine now. Great.

    Theres just one problem, whhen one of my send/rec functions fail, connect for example, execution stops completely. Why would this be? This would be in the middle of the mutex lock.
    There's no reason why a mutex would help with strtok_r. Do you mean strtok? With strtok_r each thread has it's own place to store the pointer that saves its place in the string.

    It's possible maybe that one of the socket functions will benefit from the mutex. I don't know enough about them to say. Try putting it just around socket, for example.

    Mutexing the entire function for all the threads means that they will simply execute sequentially, so there's no point in having threads.

    EDIT: I see you've considered that last point!

  8. #23
    Registered User
    Join Date
    May 2016
    Posts
    31
    Yes haha

    And heres the damn thing. I'm pretty sure the program is working now, without mutexes. And the reason its printing all over the place is because the threads are executing at different times.

  9. #24
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Interesting. Can you post your current code?

  10. #25
    Registered User
    Join Date
    May 2016
    Posts
    31
    Quote Originally Posted by algorism View Post
    Interesting. Can you post your current code?
    Code:
    #define _POSIX_SOURCE
    #include <stdio.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <stdlib.h>
    #include <arpa/inet.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <unistd.h>
    #include <pthread.h>
      
    #define IP_PORT_SIZE 22
     
    struct arg_struct {
        char * addr;
    };
      
    void * test_proxy (void * arguments)
    {
      
        struct arg_struct *args = arguments;
          
        char *ip;
        char *port;
        char *ptr;
        ip = strtok_r(args->addr, ":", &ptr);
        port = strtok_r(NULL, ":", &ptr);
    
        struct sockaddr_in server;
        int sockfd;
      
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
      
        server.sin_addr.s_addr = inet_addr(ip);
        server.sin_family = AF_INET;
        server.sin_port = htons(atoi(port));
        
        if(connect(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
        {
            return 0;
        }
    
        char request[] = "HEAD http://www.msn.com HTTP/1.0\r\n\r\n";
          
        if (send(sockfd, request, strlen(request), 0) < 0)
        {
            return 0;
        }
    
        char server_reply[500];
          
        if (recv(sockfd, server_reply, 500, 0) < 0)
        {
            return 0;
        }
      
        printf("%s \n \n",server_reply);
          
        close(sockfd);
          
        if (strstr(server_reply,"HTTP/1.1 200") || 
            strstr(server_reply,"HTTP/1.1 302") ||
            strstr(server_reply,"HTTP/1.0 200") || 
            strstr(server_reply,"HTTP/1.0 302"))
        {
            //FILE * fp;
            //char address[IP_PORT_SIZE];
            //fp = fopen(args->output_file,"a");
            //sprintf(address, "%s:%s", ip, port);
            //fputs(address,fp);
            //fclose(fp);
        }    
    
    }
      
    int amount_ips (char file[]) {
        FILE * fp;
        int ch, number_of_lines = 0;
      
        fp = fopen(file,"r");
      
        do
        {
            ch = fgetc(fp);
            if(ch == '\n')
                number_of_lines++;
        } while (ch != EOF);
      
        fclose(fp);
      
        return number_of_lines;
    }
      
    int main(int argc, char *argv[] ) {
              
        FILE * fp;
        int amount_of_ips;
        char line[IP_PORT_SIZE];    
        char file[100];
        strcpy(file,argv[1]);
        char output_file[100];
        strcpy(output_file,argv[2]);
    
        amount_of_ips = amount_ips(file);
          
        char ip_array[amount_of_ips][IP_PORT_SIZE];    
      
        fp = fopen(file,"r");
      
        int a;
        for (a = 0; a < amount_of_ips; a++)
        {
            fgets(line,IP_PORT_SIZE,fp);
            strcpy(ip_array[a], line);
        }
      
        fclose(fp);
      
        pthread_t proxy_thread[amount_of_ips];
        struct arg_struct args[amount_of_ips];
      
        int b;
        for (b = 0; b < amount_of_ips; b++)
        {
            args[b].addr = (char *) &ip_array[b];
            
            if(pthread_create(&proxy_thread[b], NULL, test_proxy, &args[b])) {
                printf("Error creating");
            }
        }
          
        int c;
        for (c = 0; c < amount_of_ips; c++)
        {
            if(pthread_join(proxy_thread[c], NULL)) {
      
                printf("Error joining thread\n");
            }
        }
    }

  11. #26
    Registered User
    Join Date
    May 2016
    Posts
    31
    It's incomplete. There's number of things I'd like to implement like better error checking. And an output file. But according to Wireshark all the requests are there and all the sockets that were delayed are now quiting together on time.

    Thanks everyone for there help. It was much appreciated.

  12. #27
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Some ideas. Basically untested, though.
    Note that recv is called in a loop (as Salem mentioned).
    Code:
    #define _POSIX_SOURCE
    #include <stdio.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <stdlib.h>
    #include <arpa/inet.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <unistd.h>
    #include <pthread.h>
    
    typedef struct Args {
        char *addr;
        char outfile[100];
    } Args;
    
    void *test_proxy(void *arguments) {
        Args *args = arguments;
    
        char *ptr = NULL;
        char *ip = strtok_r(args->addr, ":", &ptr);
        char *port = strtok_r(NULL, "\n", &ptr);
    
        int sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd == -1) {
            perror("socket");
            return NULL;
        }
    
        struct sockaddr_in server;
        memset(&server, 0, sizeof server);
        server.sin_addr.s_addr = inet_addr(ip);
        server.sin_family = AF_INET;
        server.sin_port = htons(atoi(port));
        
        if (connect(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) {
            close(sockfd);
            perror("connect");
            return NULL;
        }
    
        char request[] = "HEAD http://www.msn.com HTTP/1.0\r\n\r\n";
        ssize_t send_ret = send(sockfd, request, strlen(request), 0);
        if (send_ret == -1) {
            close(sockfd);
            perror("send");
            return NULL;
        }
    
        FILE *fout = fopen(args->outfile, "w");
    
        char server_reply[500];
        ssize_t n = 0;
        while ((n = recv(sockfd, server_reply, sizeof server_reply - 1, 0)) > 0) {
            server_reply[n] = '\0';
            fprintf(fout, "%s", server_reply);
        }
        fputc('\n', fout);
        if (n == -1)
            perror("recv");
    
        fclose(fout);
        close(sockfd);
        return NULL;
    }
      
    int count_ips(const char *file) {
        int ch, number_of_lines = 0;
        FILE *fp = fopen(file,"r");
        do {
            ch = fgetc(fp);
            if(ch == '\n')
                number_of_lines++;
        } while (ch != EOF);
        fclose(fp);
        return number_of_lines;
    }
      
    int main(int argc, char *argv[] ) {
        char line[100];
        const char *file = argv[1];
        const char *output_file = argv[2];
    
        int num_ips = count_ips(file);
        char ip_array[num_ips][sizeof line];
      
        FILE *fp = fopen(file,"r");
        int i;
        for (i = 0; i < num_ips; i++) {
            fgets(line, sizeof line, fp);
            strcpy(ip_array[i], line);
        }
        fclose(fp);
      
        pthread_t proxy_thread[num_ips];
        Args args[num_ips];
        for (i = 0; i < num_ips; i++) {
            args[i].addr = ip_array[i];
            sprintf(args[i].outfile, "%s_%d", output_file, i);
            if (pthread_create(&proxy_thread[i], NULL, test_proxy, &args[i]))
                perror("pthread_create");
        }
          
        for (i = 0; i < num_ips; i++)
            if (pthread_join(proxy_thread[i], NULL))
                perror("pthread_join");
    
        return 0;
    }

  13. #28
    Registered User
    Join Date
    May 2016
    Posts
    31
    Quote Originally Posted by algorism View Post
    Some ideas. Basically untested, though.
    Note that recv is called in a loop (as Salem mentioned).
    Code:
    #define _POSIX_SOURCE
    #include <stdio.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <stdlib.h>
    #include <arpa/inet.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <unistd.h>
    #include <pthread.h>
    
    typedef struct Args {
        char *addr;
        char outfile[100];
    } Args;
    
    void *test_proxy(void *arguments) {
        Args *args = arguments;
    
        char *ptr = NULL;
        char *ip = strtok_r(args->addr, ":", &ptr);
        char *port = strtok_r(NULL, "\n", &ptr);
    
        int sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd == -1) {
            perror("socket");
            return NULL;
        }
    
        struct sockaddr_in server;
        memset(&server, 0, sizeof server);
        server.sin_addr.s_addr = inet_addr(ip);
        server.sin_family = AF_INET;
        server.sin_port = htons(atoi(port));
        
        if (connect(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) {
            close(sockfd);
            perror("connect");
            return NULL;
        }
    
        char request[] = "HEAD http://www.msn.com HTTP/1.0\r\n\r\n";
        ssize_t send_ret = send(sockfd, request, strlen(request), 0);
        if (send_ret == -1) {
            close(sockfd);
            perror("send");
            return NULL;
        }
    
        FILE *fout = fopen(args->outfile, "w");
    
        char server_reply[500];
        ssize_t n = 0;
        while ((n = recv(sockfd, server_reply, sizeof server_reply - 1, 0)) > 0) {
            server_reply[n] = '\0';
            fprintf(fout, "%s", server_reply);
        }
        fputc('\n', fout);
        if (n == -1)
            perror("recv");
    
        fclose(fout);
        close(sockfd);
        return NULL;
    }
      
    int count_ips(const char *file) {
        int ch, number_of_lines = 0;
        FILE *fp = fopen(file,"r");
        do {
            ch = fgetc(fp);
            if(ch == '\n')
                number_of_lines++;
        } while (ch != EOF);
        fclose(fp);
        return number_of_lines;
    }
      
    int main(int argc, char *argv[] ) {
        char line[100];
        const char *file = argv[1];
        const char *output_file = argv[2];
    
        int num_ips = count_ips(file);
        char ip_array[num_ips][sizeof line];
      
        FILE *fp = fopen(file,"r");
        int i;
        for (i = 0; i < num_ips; i++) {
            fgets(line, sizeof line, fp);
            strcpy(ip_array[i], line);
        }
        fclose(fp);
      
        pthread_t proxy_thread[num_ips];
        Args args[num_ips];
        for (i = 0; i < num_ips; i++) {
            args[i].addr = ip_array[i];
            sprintf(args[i].outfile, "%s_%d", output_file, i);
            if (pthread_create(&proxy_thread[i], NULL, test_proxy, &args[i]))
                perror("pthread_create");
        }
          
        for (i = 0; i < num_ips; i++)
            if (pthread_join(proxy_thread[i], NULL))
                perror("pthread_join");
    
        return 0;
    }

    AWESOME. Thanks man. That looks great.

  14. #29
    Registered User
    Join Date
    May 2016
    Posts
    31
    Hey algorism, do you mind if I upload that code to my github account?

  15. #30
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Quote Originally Posted by watchintv View Post
    Hey algorism, do you mind if I upload that code to my github account?
    Not a problem. It's yours. No attribution necessary or desired. Kind of you to ask, though.

    Be forewarned, however, I'm not an expert on this kind of thing (neither threads nor networking) so there could easily be an error or two there.

    For instance, apparently pthread_create returns its error code (instead of setting errno directly), so the error handling should be something like:
    Code:
    #include <errno.h>  // might need this in your includes
    
    int status = pthread_create(&proxy_thread[i], NULL, test_proxy, &args[i]);
    if (status != 0) {
        errno = status;
        perror("pthread_create");
        // may want to exit here(?)
    }
    Ditto for pthread_join.

    Other functions may not be able to use perror at all (e.g., getaddrinfo returns its own error codes and uses the gai_strerror function to print human-readable error info), so to do it all properly you need to carefully read the manual for each function.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Multiple processes running concurrently in c
    By bungkai in forum C Programming
    Replies: 3
    Last Post: 02-07-2012, 04:15 PM
  2. Replies: 13
    Last Post: 12-09-2008, 11:09 AM
  3. Multiple theads to process video files
    By matth in forum C++ Programming
    Replies: 0
    Last Post: 07-15-2005, 02:55 PM
  4. Replies: 1
    Last Post: 05-01-2003, 02:52 PM
  5. Running multiple programs
    By Kespoosh in forum C++ Programming
    Replies: 2
    Last Post: 03-17-2003, 04:53 PM

Tags for this Thread