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);
}
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 ofsend
.A simple function might look like
And something similar for
recv
.