Created
August 12, 2024 15:58
-
-
Save alimovlex/eeabaf5184581a17426e7b306d65eca9 to your computer and use it in GitHub Desktop.
A simple TCP C++ server that deserializes protobuf message and prints it out to the console.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * Copyright (C) 2024 Recompile.me. | |
| * All rights reserved. | |
| */ | |
| #include <iostream> | |
| #include <string> | |
| #include <stdio.h> | |
| #include <sys/types.h> | |
| #include <sys/socket.h> | |
| #include <netinet/in.h> | |
| #include <arpa/inet.h> | |
| #include <stdlib.h> | |
| #include <unistd.h> | |
| #include <string.h> | |
| #include <netdb.h> | |
| #include <sys/uio.h> | |
| #include <sys/time.h> | |
| #include <sys/wait.h> | |
| #include <fcntl.h> | |
| #include <fstream> | |
| #include <thread> | |
| #include "person.pb.h" | |
| using namespace std; | |
| //Server side | |
| int server () | |
| { | |
| //grab the port number | |
| int port = 8080; | |
| //buffer to send and receive messages with | |
| char msg[1500]; | |
| //setup a socket and connection tools | |
| sockaddr_in servAddr; | |
| bzero((char*)&servAddr, sizeof(servAddr)); | |
| servAddr.sin_family = AF_INET; | |
| servAddr.sin_addr.s_addr = htonl(INADDR_ANY); | |
| servAddr.sin_port = htons(port); | |
| //open stream oriented socket with internet address | |
| //also keep track of the socket descriptor | |
| int serverSd = socket(AF_INET, SOCK_STREAM, 0); | |
| if(serverSd < 0) | |
| { | |
| cerr << "Error establishing the server socket" << endl; | |
| return -1; | |
| } | |
| //bind the socket to its local address | |
| int bindStatus = bind(serverSd, (struct sockaddr*) &servAddr, | |
| sizeof(servAddr)); | |
| if(bindStatus < 0) | |
| { | |
| cerr << "Error binding socket to local address" << endl; | |
| return -1; | |
| } | |
| cout << "Waiting for a client to connect on a port: " << port << endl; | |
| //listen for up to 5 requests at a time | |
| listen(serverSd, 5); | |
| //receive a request from client using accept | |
| //we need a new address to connect with the client | |
| sockaddr_in newSockAddr; | |
| socklen_t newSockAddrSize = sizeof(newSockAddr); | |
| //accept, create a new socket descriptor to | |
| //handle the new connection with client | |
| int newSd = accept(serverSd, (sockaddr *)&newSockAddr, &newSockAddrSize); | |
| if(newSd < 0) | |
| { | |
| cerr << "Error accepting request from client!" << endl; | |
| return -1; | |
| } | |
| cout << "Connected with client!" << endl; | |
| //lets keep track of the sessionWaiting time | |
| struct timeval start1, end1; | |
| gettimeofday(&start1, NULL); | |
| //also keep track of the amount of data sent as well | |
| int bytesRead, bytesWritten = 0; | |
| while(1) | |
| { | |
| //receive a message from the client (listen) | |
| cout << "Awaiting client response..." << endl; | |
| memset(&msg, 0, sizeof(msg));//clear the buffer | |
| bytesRead += recv(newSd, (char*)&msg, sizeof(msg), 0); | |
| if(!strcmp(msg, "exit")) | |
| { | |
| cout << "Client has quit the session" << endl; | |
| break; | |
| } | |
| string binary = msg; | |
| PERSON::Person p2; | |
| p2.ParseFromString(binary); | |
| cout << "Client: " << binary << endl; | |
| cout << "-> "; | |
| cout << "["; | |
| cout << "Name: " << p2.name() << " id: " << p2.id() << " Email: " << p2.email(); | |
| cout << "]" << endl; | |
| string data; | |
| getline(cin, data); | |
| memset(&msg, 0, sizeof(msg)); //clear the buffer | |
| strcpy(msg, data.c_str()); | |
| if(data == "exit") | |
| { | |
| //send to the client that server has closed the connection | |
| send(newSd, (char*)&msg, strlen(msg), 0); | |
| break; | |
| } | |
| //send the message to client | |
| bytesWritten += send(newSd, (char*)&msg, strlen(msg), 0); | |
| } | |
| //we need to close the socket descriptors after we're all done | |
| gettimeofday(&end1, NULL); | |
| close(newSd); | |
| close(serverSd); | |
| cout << "********Session********" << endl; | |
| cout << "Bytes written: " << bytesWritten << " Bytes read: " << bytesRead << endl; | |
| cout << "Elapsed time: " << (end1.tv_sec - start1.tv_sec) | |
| << " secs" << endl; | |
| cout << "Connection closed..." << endl; | |
| return 0; | |
| } | |
| int main() { | |
| GOOGLE_PROTOBUF_VERIFY_VERSION; | |
| server(); | |
| google::protobuf::ShutdownProtobufLibrary(); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment