Question

I have poured over my code for the past 5 hours and have gotten nowhere. Whenever I run my code, I get a Segmentation Fault. Sometimes it happens on the client side, sometimes on the server side, so I'm just not sure what's happening. The code works when I try to look for prime numbers up to 100, but nothing after. When I last posted here, I was told to post my complete code, so here it is:

Server:

void sieve(int *isComposite, int maximum, int maxSqrt) {

    int m = isComposite[0];
    int currentPrime = m-1;

    //Loop through "maxSqrt" times through the array
    if(m <= maxSqrt){
        //Loop through the multiples of the number we're
        //looking at (m) and mark them as composite (1)
        for (int k = currentPrime * currentPrime; k <= maximum; k += currentPrime){
            if(isComposite[k+1] == 0){
                //cout << "Removing: " << k << endl;
                isComposite[k+1] = 1;
            }
        }
    }
}

int main(int argc, char *argv[]){
    int sockfd, newsockfd, portno; // listen on sock_fd, new connection on new_fd, port number
    socklen_t clilen;

    struct sockaddr_in serv_addr, cli_addr;  // my address information, connector's address information
    int n;
    int open = 1; //true


    if (argc < 2) {
        fprintf(stderr,"ERROR, no port provided\n");
        exit(1);
    }

    //Socket setup
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        error("ERROR opening socket");
    } 
    bzero((char *) &serv_addr, sizeof(serv_addr));
    portno = atoi(argv[1]);             //port number (ex. 10.12.110.57 or thing-1.uwec.edu)
    serv_addr.sin_family = AF_INET;     // host byte order
    serv_addr.sin_port = htons(portno); // short, network byte order
    serv_addr.sin_addr.s_addr = INADDR_ANY;  // use my IP address

    //Bind socket
    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
        error("ERROR on binding");
    }
    //Listen for connection
    listen(sockfd,5);

    //Accept the connection
    clilen = sizeof(cli_addr);
    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
    if (newsockfd < 0){
        error("ERROR on accept");
    }
    printf("Connection accepted!\n");

    // Variable to college the largest number in the range
    int maximum;

    // Collect the maximum
    cout << "\nEnter a Maximum:";
    cin >> maximum;
    cout << "\n";

    int *maxToSend = new int[1];
    maxToSend[0] = maximum;

    if(send(newsockfd, maxToSend, 10, 0) < 0){
        perror("ERROR sending to socket");
    }


    int maxSqrt = (int)sqrt((double)maximum);

    // Declare the array to hold important 
    // information and the numbers to sieve
    int *isComposite= new int[maximum+1]();

    // Insert the variable that keeps track of where we
    // are in the array, starting with 2 (the first prime)
    // which is held in isComposite[3]
    isComposite[0] = 3;

    // Run the sieve for each prime we come accross
    // until we reach the prime that is the square
    // root of the maximum (isComposite[2])
    while(isComposite[0] <= maxSqrt){

        // Unless it is the first time through
        // Receive from the client
        if(isComposite[0] > 3){
            if(recv(newsockfd, isComposite, (maximum+1)* sizeof(int), 0) < 0){
                perror("ERROR receiving from socket");
            }
        }

        // If we're not done:
        if(isComposite[0] <= maxSqrt){
            // Sieve the range
            sieve(isComposite, maximum, maxSqrt);
            isComposite[0]++;

            // Find the next prime
            while(isComposite[isComposite[0]] == 1){
                isComposite[0]++;
            }
            cout << "Doing next Sieve on: " << isComposite[0]-1 << endl;

        }

        // If we're still not done:
        if(send(newsockfd, isComposite, (maximum+1)* sizeof(int), 0) < 0){
            if(send(newsockfd, isComposite, maximum+1500, 0) < 0){
                perror("ERROR sending to socket");
            }
        }
    }
    return 0;
}

Client:

void sieve(int *isComposite, int maximum, int maxSqrt) {

    int m = isComposite[0];
    int currentPrime = m-1;

    //Loop through "maxSqrt" times through the array
    if(m <= maxSqrt){
        //Loop through the multiples of the number we're
        //looking at (m) and mark them as composite (1)
        for (int k = currentPrime * currentPrime; k <= maximum; k += currentPrime){
            if(isComposite[k+1] == 0){
                //cout << "Removing: " << k << endl;
                isComposite[k+1] = 1;
            }
        }
    }
}

int main(int argc, char *argv[]){

    int sockfd, portno, n;
    struct sockaddr_in serv_addr;
    struct hostent *server;
    int open = 1; //true
    char c = 'a';

    if (argc < 3) {
       fprintf(stderr,"usage %s hostname port\n", argv[0]);
       exit(0);
    }

    portno = atoi(argv[2]);  //parse port number

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        error("ERROR opening socket");
    }

    server = gethostbyname(argv[1]);
    if (server == NULL) {
        fprintf(stderr,"ERROR, no such host\n");
        exit(0);
    }

    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;   // host byte order
    bcopy((char *)server->h_addr,(char *)&serv_addr.sin_addr.s_addr, server->h_length);
    serv_addr.sin_port = htons(portno);  // short, network byte order


    if (connect(sockfd,(struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
        error("ERROR connecting");
    }

    int *maxToSend = new int[1];

    if(recv(sockfd, maxToSend, 10, 0) < 0){
        perror("ERROR receiving from socket");
    }

    int maximum = maxToSend[0];
    int maxSqrt = (int)sqrt((double)maximum);

    int *isComposite= new int[maximum+1]();

    while(isComposite[0] <= maxSqrt){

        if(recv(sockfd, isComposite, (maximum+1)* sizeof(int), 0) < 0){
            perror("ERROR receiving from socket");
        }

        // Sieve the range
        sieve(isComposite, maximum, maxSqrt);
        isComposite[0]++;

        // Find the next prime
        while(isComposite[isComposite[0]] == 1){
            isComposite[0]++;
        }
        cout << "Doing next Sieve on: " << isComposite[0]-1 << endl;

        if(send(sockfd, isComposite, (maximum+1)* sizeof(int), 0) < 0){
            perror("ERROR sending to socket");
        }

    }

    close(sockfd);
    return(0);
}
Was it helpful?

Solution

The reason is that the size of your sieve is getting larger than a single packet can hold. You can only store about 1400 bytes in a single packet, and your send and receive functions don't account for this. You have to loop until you have sent all of the data that you are trying to send or read in all of the data that you are trying to read. It looks like you tried to do this with send(newsockfd, isComposite, maximum+1500, 0), but you need to do this with a loop, and keep track of how much data you have sent from the return value of send.

A simple function might look like

bool sendAll(int socket, const void *data, ssize_t size) {
    ssize_t sent = 0;
    ssize_t just_sent;
    while (sent < size) {
        just_sent = send(socket, data + sent, size - sent, 0);
        if (just_set < 0) {
            return false;
        }
        sent += just_sent;
    }
    return true;
}

And something similar for recv.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top