#include #include #include #include // need this for unix domain sockets. #include // unlink #include #include using namespace std; const string GOOD{"ok"}; const string BAD{"error"}; void Success(bool status, int socket); const string PATH{"/tmp/CalcServer"}; const int BACKLOG{20}; void DoMath(char op, int & sum, int socket); void DoPrint(int sum, int socket); int main() { int theSocket; struct sockaddr_un address; theSocket = socket(AF_UNIX, SOCK_STREAM, 0); if(theSocket == -1) { perror("Socket failed: "); exit(1); } if (-1 == unlink(PATH.c_str()) and errno != ENOENT) { perror("Unlink existing socket: "); exit(1); } memset(&address, 0, sizeof(struct sockaddr_un)); address.sun_family = AF_UNIX; strncpy(address.sun_path, PATH.c_str(), sizeof(address.sun_path)-1); if( -1 == bind(theSocket,reinterpret_cast( &address), sizeof(struct sockaddr_un))) { perror("Bind failed: "); } if (listen(theSocket, BACKLOG) == -1) { perror("Listen failed: "); } bool done{false}; socklen_t len; while (not done) { int newSocket; char op; int value; int sum{0}; len = sizeof(struct sockaddr_un); // there is no client address, so use nullptr newSocket = accept(theSocket, nullptr, nullptr); if(newSocket == -1) { perror("Accept failed: "); break; } cout << "New connection." << endl; ssize_t numRead; while(numRead = read(newSocket, &op, sizeof(char)) > 0) { cout << "\tJust got: " << op << endl; switch (op) { case 'q': done = true; break; case '+': case '-': case '*': case '/': DoMath(op, sum, newSocket); break; case '=': DoPrint(sum, newSocket); break; case 'c': sum = 0; write(newSocket, GOOD.c_str(), GOOD.size()); break; default: write(newSocket, BAD.c_str(), BAD.size()); break; } cout << endl; } close(newSocket); cout << "End of connection." << endl; cout << endl; } close(theSocket); return 0; } void DoMath(char op, int & sum, int socket){ int value; int oldSum {sum}; bool good{true}; ssize_t bytes = read(socket, &value, sizeof(int)); if (bytes == sizeof(int) ) { switch(op) { case '+': sum += value; break; case '*': sum *= value; break; case '-': sum -= value; break; case '/': sum /= value; break; } cout << "\t"; cout << oldSum << " " << op << " " << value << " = " << sum << endl; } else { good = false; } Success(good, socket); return; } void DoPrint(int sum, int socket) { string msg{"The current value is " + to_string(sum)}; int size{static_cast(msg.size())}; write(socket, &size, sizeof(size)); write(socket, msg.c_str(), msg.size()); Success(true, socket); return; } void Success(bool status, int socket) { int size; string msg{GOOD}; if (not status) { msg = BAD; } size = msg.size(); write(socket, &size, sizeof(size)); write(socket, msg.c_str(), msg.size()); return; }