1 year ago

#291187

test-img

Will Amos

Does get_nprocs_conf() always return 1 when using a virtual machine?

I'm supposed to use get_nprocs_conf() to get the number of execution contexts on my machine. I'm doing this because I am coding a server and client to interact with each other, and the server may only host get_nprocs_conf()-1 clients. Before I add code to my server to wait for an opening, I want to figure out this issue.

I'm running this code on a virtual machine because I'm using Linux and my desktop is Windows, and when I use said code above, my maximum number of clients is 0, meaning that get_nprocs_conf() only returns 1. Is this because I'm using a virtual machine and for some reason it only can use one execution context, or am I misunderstanding and my computer only has one execution context?

Provided below are my server and client programs. Server Code:

#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <iostream>
#include <fstream>
#include <sys/sysinfo.h>
#include <vector>
#include <cstring>
#include <arpa/inet.h>
//#define BUFFER_SIZE 32

//May need to replace -1 with EXIT_FAILURE in all the exits
int main(int argc, char *argv[]) {
 if(argc != 2) {
  std::cout << "Need domain socket file name" << std::endl;
  exit(-1);
 }
 struct sockaddr_un server;

 char buffer[32];
 unlink(argv[1]);
 
 int serverSock = socket(AF_UNIX, SOCK_STREAM, 0);
 if(serverSock < 0) {
  perror("socket");
  exit(EXIT_FAILURE);
 }

 std::clog << "SERVER STARTED" << std::endl;
 size_t maxClients = get_nprocs_conf()-1;
 std::clog << "\t" << "MAX CLIENTS: " << maxClients << std::endl;

 memset(&server, 0, sizeof(server));
 server.sun_family = AF_UNIX;
 strncpy(server.sun_path, argv[1], sizeof(server.sun_path)-1);

 int success = bind(serverSock, (const struct sockaddr *) &server,
                 sizeof(struct sockaddr_un));
 if(success < 0) {
  perror("bind");
  exit(EXIT_FAILURE);
 }

 success = listen(serverSock, maxClients);
 if(success < 0) {
  perror("listen");
exit(EXIT_FAILURE);
 }

 while(true) {
  std::cout << "Waiting for clients" << std::endl;

  int clientSock = accept(serverSock, nullptr, nullptr);
  if(clientSock < 0) {
   perror("accept");
   exit(EXIT_FAILURE);
  }

  std::clog << "CLIENT CONNECTED" << std::endl;

  std::string path="";
  std::string searchStr="";
  char fileBuff[32];
  char searchBuff[32];

  memset(fileBuff, 0, 32);
  success = read(clientSock, fileBuff, 32);
  if(success < 0) {
   perror("read");
   exit(EXIT_FAILURE);
  }
  path = fileBuff;
  std::cout << path << std::endl;

  if(path.empty()) {
    std::cout << "No path to file given" << std::endl;
    exit(1);
  }

  memset(searchBuff, 0, 32);
  success = read(clientSock, searchBuff, 32);
  if(success < 0) {
   perror("read");
   exit(EXIT_FAILURE);
  }

  searchStr = searchBuff;
  std::cout << searchStr << std::endl;

  if(searchStr.empty()) {
   std::cout << "No search string given" << std::endl;
   exit(1);
  }

  std::ifstream inFile;
  inFile.open(path);
  std::string line = "";
  int bytesSent = 0;
  std::vector<std::string> allLines;
  if(inFile.is_open()) {
   while(std::getline(inFile, line)) {
    if(line.find(searchStr, 0)!=std::string::npos) {
     allLines.push_back(line);
     //std::cout << line << std::endl;
    }
   }
  }

  //Sending over entire length of vector containing all lines to be sent.
  long length = htonl(allLines.size());
  success = write(clientSock, &length, sizeof(length));
  if(success < 0) {
   perror("write");
   exit(EXIT_FAILURE);
  }

  for(int b=0; b<allLines.size(); b++) {
   length = htonl(allLines[b].length());
   success = write(clientSock, &length, sizeof(length));
   if(success < 0) {
perror("write");
    exit(EXIT_FAILURE);
   }
   success = write(clientSock, allLines[b].data(), allLines[b].length());
   if(success < 0) {
    perror("write");
    exit(EXIT_FAILURE);
   }
   bytesSent += allLines[b].length();
  }
  //char end[] = {'\n'};
  //write(clientSock, end, sizeof(char));
  std::cout << "BYTES SENT: " << bytesSent << std::endl;
  inFile.close();
  close(clientSock);
 }
 //return 0;
}

Client Code:

#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <sys/socket.h>
#include <unistd.h>
#include <iostream>
#include <fstream>   //Don't think I'll need this
#include <errno.h>
#include <sys/un.h>
#include <sstream>
#include <arpa/inet.h>
#include <vector>

int main(int argc, char *argv[]){
 if(argc != 4) {
  std::cout << "Need domain socket file name, file path and name, " <<
          "and search string" << std::endl;
  exit(-1);
 }

 struct sockaddr_un client;
 char buffer[64]; //Prof had 64 for client may need to change to 32 to match

 int clientSock = socket(AF_UNIX, SOCK_STREAM, 0);
 if(clientSock < 0) {
  perror("socket");
  exit(EXIT_FAILURE);
 }
 std::cout << "socket connected" << std::endl;

 memset(&client, 0, sizeof(struct sockaddr_un));
 client.sun_family = AF_UNIX;
 strncpy(client.sun_path, argv[1], sizeof(client.sun_path)-1);

 int connectClient = connect(clientSock, (const struct sockaddr *)&client,
                 sizeof(struct sockaddr_un));
 if(connectClient < 0) {
  fprintf(stderr, "The server is not working.\n");
  exit(EXIT_FAILURE);
 }
 std::cout << "client connected" << std::endl;

 //char arg2[] = {*argv[2],'\n'};
 std::string path = argv[2];
 std::cout << "Path: " << path << std::endl;
 connectClient = write(clientSock, argv[2], path.length());
 if(connectClient < 0) {
  perror("write");
  exit(EXIT_FAILURE);
 }
 std::string search = argv[3];
 std::cout << "Search String: " << search << std::endl;
 connectClient = write(clientSock, argv[3], search.length());
 if(connectClient < 0) {
  perror("write");
  exit(EXIT_FAILURE);
 }

 //int servRet;
 int lineCount=0;
 int bytes_received=0;
 //std::string line = "";
 char length[sizeof(int)];
 //std::string leng = "";
 int num=0;
 std::stringstream ss;
 std::vector<std::string> allLines;
 long size = 0;
 read(clientSock, &size, sizeof(size));
 size = ntohl(size);
 for(int a=0; a<size; ++a) {
  long length = 0;
  std::string line = "";
  connectClient = read(clientSock, &length, sizeof(length));
  length = ntohl(length);
  while(0 < length) {
   char buffer[1024];
   connectClient = read(clientSock, buffer, std::min<unsigned long>(sizeof(buffer),length));
   line.append(buffer, connectClient);
   length-=connectClient;
  }
  allLines.push_back(line);
  lineCount++;
  std::cout << lineCount << "\t" << line << std::endl;
  bytes_received += line.length();
 }
 std::cout << "BYTES RECEIVED: " << bytes_received << std::endl;
 close(clientSock);
 return 0;
}

Right now everything in the server and client work as they should. I'm just hesitating to add code that waits for an execution context to open for another client to be read because it seems like it would never accept any clients since the sole execution context is being used by the server. Any clarification on my issue or on if I'm just using get_nprocs_conf() incorrectly would be greatly appreciated.

c++

server

client

executioncontext

0 Answers

Your Answer

Accepted video resources