Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

2 threada kroz jedan socket, sleep() pravi problem

[es] :: C/C++ programiranje :: 2 threada kroz jedan socket, sleep() pravi problem

[ Pregleda: 1156 | Odgovora: 1 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

VerbatimBOT
Aleksandar Dragosavac
Senior .NET Developer

Član broj: 84129
Poruke: 228
*.adsl-a-2.sezampro.rs.



Profil

icon 2 threada kroz jedan socket, sleep() pravi problem06.06.2011. u 16:23 - pre 155 meseci
Pozdrav,
Kreiram 2 thread-a koja pozivaju funkciju sendMessage i dobijaju odgovor sa servera. Problem nastaje kada pokrenem oba thread-a (funkcije feedCommunicationThread i loginCommunicationThread) i u FOR petlju ubacim sleep(N) ili usleep(N), dobijam grešku "ERROR reading from socket" (195. linija) sa error kodom -1.
Moja prva pretpostavka je da sleep utiče i na glavni thread a ne samo na running, ali nisam siguran jer nemam puno iskustva sa thread-ovima u C-u. Kada sklonim sleep(), prodje lepo kroz FOR petlju do kraja.

Drugo što bih hteo da pitam je - hoću da imam jedan otvoren socket sve vreme (a ne da ga otvaram i zatvaram pri svakom pozivu unutar sendMessage funkcije). Medjutim, kada taj deo koda izmestim u main() funkciju dobijam grešku pri drugom pokušaju da pošalje poruku (prvi prodje ok). Jel zna neko šta je ovde problem? Mogu da pošaljem i taj kod ako nekoga interesuje..

Bio bih zahvalan ako bi neko mogao da mi pomogne s ovim, jer sam se poprilično zaglavio.

Code:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h> 
#include <pthread.h>

typedef struct config
{
    char srv1_ip[100];
    int srv1_port;
    char auth[256];
    char srv2_ip[100];
    int srv2_port;
    char feed[256];
} CONFIG;

char bfr[256];

void error(const char *msg);
void removeNewLine(char *buffer);
char *sendMessage(char* message, CONFIG config);
void *feedCommunicationThread(void *threadid);
void *loginCommunicationThread(void *threadid);

int main(int argc, char *argv[])
{
    FILE *fp;
    char buffer[100], buffer2[100];
    char *cptr;
    CONFIG config;
    char *response;
    int counter = 0, threadCreateCode, i;
    
    fp = fopen("client.cfg", "r");
    if (fp == NULL)
    {
        printf("Unable to read client.cfg");
        exit(1);
    }
    // read config settings
    printf("Reading settings:\n");
    i = 0;
    while (fgets(buffer, 100, fp))
    {
        cptr = strstr(buffer, "srv1_ip=");
        if (cptr != NULL)
        {
            cptr = strstr(buffer, "=") - 1;
            cptr += 2;
            removeNewLine(cptr);
            strcpy(config.srv1_ip, cptr);
        }        
        cptr = strstr(buffer, "srv1_port=");
        if (cptr != NULL)
        {
            cptr = strstr(buffer, "=") - 1;
            cptr+=2;
            config.srv1_port = atoi(cptr);
        }
        cptr = strstr(buffer, "auth=");
        if (cptr != NULL)
        {
            cptr = strstr(buffer, "=") - 1;
            cptr += 2;
            removeNewLine(cptr);
            strcpy(config.auth, cptr);
        }
        cptr = strstr(buffer, "srv2_ip=");
        if (cptr != NULL)
        {
            cptr = strstr(buffer, "=") - 1;
            cptr += 2;
            removeNewLine(cptr);
            strcpy(config.srv2_ip, cptr);
        }
        cptr = strstr(buffer, "srv2_port=");
        if (cptr != NULL)
        {
            cptr = strstr(buffer, "=") - 1;
            cptr += 2;
            config.srv2_port = atoi(cptr);
        }
        cptr = strstr(buffer, "feed=");
        if (cptr != NULL)
        {
            cptr = strstr(buffer, "=") - 1;
            cptr += 2;
            removeNewLine(cptr);
            strcpy(config.feed, cptr);
        }
    }
    fclose(fp);
    printf("======================\n");
    printf("PARAMS: %s %d %s %s %d %s\n", config.srv1_ip, config.srv1_port, config.auth, config.srv2_ip, config.srv2_port, config.feed);
    printf("======================\n\n");
    
    // create threads
    pthread_t threads[2];
    
    threadCreateCode = pthread_create(&threads[0], NULL, feedCommunicationThread, (void *)&config);
    if (threadCreateCode)
        printf("ERROR: Unable to create FEED thread. Return code: %d", threadCreateCode);
        
    threadCreateCode = pthread_create(&threads[1], NULL, loginCommunicationThread, (void *)&config);
    if (threadCreateCode)
        printf("ERROR: Unable to create LOGIN communication thread. Return code: %d", threadCreateCode);
        
    pthread_exit(NULL);
    
    
    
    /*for (i=0; i<300; i++)
    {
        printf("\nSending generated message.\n");
        response = sendMessage("Generated message.", config);
        printf("Response: %s\n\n", response);
        if (strcmp(response, "OK") != 0)
            counter++;
        //sleep(1);
    }*/
    printf("Successfully executed.");
    if (counter > 0)
        printf("\nUnsuccessfully sent: %d/300", counter);
    return 0;
}

void error(const char *msg)
{
    perror(msg);
    exit(0);
}

void removeNewLine(char *buffer)
{
    int length = strlen(buffer)-1;
    int i;
    for (i=0; i<length; i++)
    {        
        if ((int)buffer[i] == 10 || (int)buffer[i] == 13)
        {
            buffer[i] = '\0';
            break;
        }
    }
}

char *sendMessage(char* message, CONFIG config)
{
    int sockfd, n;
    struct sockaddr_in serv_addr;
    struct hostent *server;
    
    //printf("Send message called for server %s", config.srv2_ip);
    
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
        
    if (sockfd < 0) 
        printf("ERROR opening socket");
        
    server = gethostbyname(config.srv1_ip);
    
    if (server == NULL) {
        printf("ERROR, no such host\n");
        exit(0);
    }
    
    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    
    bcopy((char *)server->h_addr, 
         (char *)&serv_addr.sin_addr.s_addr,
         server->h_length);
         
    serv_addr.sin_port = htons(config.srv1_port);
    
    if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) 
        printf("ERROR connecting");
        
    bzero(bfr,256);
    
    n = write(sockfd, message, strlen(message));
    
    
    if (n < 0) 
         error("ERROR writing to socket");
         
    bzero(bfr,256);
    n = read(sockfd,bfr,255);
    
    if (n < 0) 
         printf("ERROR reading from socket: Error code %d", n);
         
    close(sockfd);
    
    return &bfr[0];
}

void *feedCommunicationThread(void *cnfg)
{
    //pthread_exit(NULL);
   CONFIG *cfg;
   cfg = (CONFIG *)cnfg;
   int i;
   char *r;
   
   r = sendMessage(cfg->feed, *cfg);
    if (strcmp(r, "OK") == 0)
    {
        // ok, go to next step
        printf("FEED message successfully sent.\n");
        for (i=0; i<15; i++)
        {
            printf("Sending ping... ");
            r = sendMessage("PING...", *cfg);
            if (strcmp(r, "OK") == 0)
                printf("OK\n");
            else
                printf("NOT OK\n");
            //usleep(2000);
        }
    }
    else
    {
        printf("ERROR: FEED message could not be sent successfully to the server. Server responded with: %s\n", r);
    }
    
   pthread_exit(NULL);
}

void *loginCommunicationThread(void *cnfg)
{
    
    //pthread_exit(NULL);
   CONFIG *cfg;
   cfg = (CONFIG *)cnfg;
   char *r;
   int i;
  
    printf("AUTH: %s\n", cfg->auth);    
    r = sendMessage(cfg->auth, *cfg);
    if (strcmp(r, "OK") == 0)
    {
        printf("Client successfully authenticated.\n");
        for (i=0; i<10; i++)
        {
            sendMessage("Sending message from LOGIN function.", *cfg);
            //sleep(1);
        }
    }
    else
    {
        printf("AUTHENTICATION RESPONSE NOT OK: %s\n", r);
        printf("Client exited with error.\n");
    }
  
   pthread_exit(NULL);
}


Winners never quit, quitters never win.
 
Odgovor na temu

Mihajlo Cvetanović
Beograd

Moderator
Član broj: 37636
Poruke: 1249



+96 Profil

icon Re: 2 threada kroz jedan socket, sleep() pravi problem08.06.2011. u 14:50 - pre 155 meseci
U main-u se poziva pthread_exit, a sudeći po dokumentaciji tad se terminira nit. Mogu da zamislim da to izaziva probleme ako izvršavanje kreiranih pod-niti dugo traje, ali da problema nema ako niti kratko traju. Umesto pthread_exit verujem da tu treba da stoji dva puta pthread_join (po jedan za svaku nit).

Postoji drugi problem sa ovim kodom. Slanje svake poruke preko soketa podrazumeva da se napravi novi soket. To nema mnogo logike u TCP/IP svetu. Konekcija treba da traje što duže, i ne treba da se gasi dokle god radi svoj posao. Ispravljeni kod treba da radi konektovanje, pa slanje poruka već po redu kako treba, pa diskonektovanje. Ako je logika takva da jedna konekcija treba da ima samo jednu poruku, onda je logika loša.
 
Odgovor na temu

[es] :: C/C++ programiranje :: 2 threada kroz jedan socket, sleep() pravi problem

[ Pregleda: 1156 | Odgovora: 1 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.