Server - Client RSA keypair exchange - c++

I'm new to programming and i've got this little project going for my diploma and i need help on this little code. This is a Server->Client C++ code where server generates and sends RSA Keypair to client. My problem is that both server and client codes compiled without any problem but when i start it the client side doesn't get any keypair just blank.
Here is my server code:
#include <iostream>
#include <cstdlib>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <stdio.h>
#include <string.h>
#define KEY_LENGTH 1024
#define PUB_EXP 3
#define PRINT_KEYS
#define WRITE_TO_FILE
using std::exit;
#define int_error(msg) handle_error(__FILE__, __LINE__, msg)
void handle_error(const char* file, int lineno, const char* msg)
{
std::cerr << "\n** " << file << ":" << lineno << " " << msg << "\n";
ERR_print_errors_fp(stderr);
exit(-1);
}
void init_OpenSSL()
{
std::cout << "Initializng OpenSSL library ... ";
if (!SSL_library_init())
int_error("OpenSSL initialization failed");
std::cout << "done\n";
SSL_load_error_strings();
}
DH* setup_dh()
{
DH* dh = DH_new();
if (!dh)
int_error("DH_new failed");
std::cout << "Generating DH parameters ... ";
if (!DH_generate_parameters_ex(dh, 2, DH_GENERATOR_2, 0))
int_error("DH_generate_parameters_ex failed");
std::cout << "done\n";
std::cout << "Checking DH parameters ... ";
int codes = 0;
if (!DH_check(dh, &codes))
int_error("DH_check failed");
std::cout << "done\n";
std::cout << "Generating DH keys ... ";
if (!DH_generate_key(dh))
int_error("DH_generate_key failed");
std::cout << "done\n";
return dh;
}
SSL_CTX* setup_ctx()
{
SSL_CTX* ctx;
std::cout << "Creating context ... ";
ctx = SSL_CTX_new(TLSv1_server_method());
if (!ctx)
int_error("SSL_CTX_new failed");
std::cout << "done\n";
DH* dh = setup_dh();
std::cout << "Setting DH parameters ... ";
SSL_CTX_set_tmp_dh(ctx, dh);
std::cout << "done\n";
std::cout << "Setting cipher list ... ";
if (SSL_CTX_set_cipher_list(ctx, "ADH-AES256-SHA") != 1)
int_error("Error setting cipher list (no valid ciphers)");
std::cout << "done\n";
return ctx;
}
int main()
{
init_OpenSSL();
BIO *acc, *client;
SSL* ssl;
SSL_CTX* ctx;
ctx = setup_ctx();
size_t pri_len;
size_t pub_len;
char *pri_key;
char *pub_key;
std::cout << "Generating RSA (%d bits) keypair...\n", 1024;
RSA *keypair = RSA_generate_key(1024, 3, NULL, NULL);
BIO *pri = BIO_new(BIO_s_mem());
BIO *pub = BIO_new(BIO_s_mem());
PEM_write_bio_RSAPrivateKey(pri, keypair, NULL, NULL, 0, NULL, NULL);
PEM_write_bio_RSAPublicKey(pub, keypair);
pri_len = BIO_pending(pri);
pub_len = BIO_pending(pub);
pri_key = (char*)malloc(pri_len + 1);
pub_key = (char*)malloc(pub_len + 1);
BIO_read(pri, pri_key, pri_len);
BIO_read(pub, pub_key, pub_len);
pri_key[pri_len] = '\0';
pub_key[pub_len] = '\0';
std::cout << "Creating server socket ... ";
acc = BIO_new_accept("*:5055");
if (!acc)
int_error("Error creating server socket");
std::cout << "done\n";
std::cout << "Binding server socket ... ";
if (BIO_do_accept(acc) <= 0)
int_error("Error binding server socket");
std::cout << "done\n";
while (true) {
std::cout << "Accepting connections ...\n";
if (BIO_do_accept(acc) <= 0)
int_error("Error accepting connection");
client = BIO_pop(acc);
std::cout << "Creating context ... ";
if (!(ssl = SSL_new(ctx)))
int_error("Error creating SSL context");
std::cout << "done\n";
SSL_set_bio(ssl, client, client);
if (SSL_accept(ssl) <= 0)
int_error("Error accepting SSL connection");
std::cout << "SSL connection opened: " << SSL_get_cipher(ssl) << " " <<
SSL_get_cipher_version(ssl) << " (" << SSL_get_cipher_bits(ssl, 0) << " bits)\n";
char buff[256] = {0};
int r = SSL_read(ssl, buff, sizeof buff);
if (r > 0) {
std::cout << buff;
SSL_write(ssl, keypair, 1024 );
}
SSL_shutdown(ssl);
SSL_free(ssl);
std::cout << "SSL connection finished\n";
}
SSL_CTX_free(ctx);
BIO_free(acc);
std::cout << "Server closed\n";
}
Here is my client code:
#include <iostream>
#include <cstdlib>
#include <string>
#include <fstream>
#include <openssl/ssl.h>
#include <openssl/err.h>
using namespace std;
using std::exit;
#define int_error(msg) handle_error(__FILE__, __LINE__, msg)
void handle_error(const char* file, int lineno, const char* msg)
{
std::cerr << "** " << file << ":" << lineno << " " << msg << "\n";
ERR_print_errors_fp(stderr);
exit(-1);
}
void init_OpenSSL()
{
std::cout << "Initializng OpenSSL library ... ";
if (!SSL_library_init())
int_error("OpenSSL initialization failed");
std::cout << "done\n";
SSL_load_error_strings();
}
SSL_CTX* setup_ctx()
{
SSL_CTX* ctx;
std::cout << "Creating context ... ";
ctx = SSL_CTX_new(TLSv1_client_method());
if (!ctx)
int_error("SSL_CTX_new failed");
std::cout << "done\n";
std::cout << "Setting cipher list ... ";
if (SSL_CTX_set_cipher_list(ctx, "ADH-AES256-SHA") != 1)
int_error("Error setting cipher list (no valid ciphers)");
std::cout << "done\n";
return ctx;
}
int main()
{
init_OpenSSL();
BIO* conn;
SSL* ssl;
SSL_CTX* ctx;
ofstream myfile;
ctx = setup_ctx();
std::cout << "Creating connection ... ";
conn = BIO_new_connect("192.168.1.10:5055");
if (!conn)
int_error("Error creating connection");
std::cout << "done\n";
std::cout << "Connecting to server ... ";
if (BIO_do_connect(conn) <= 0)
int_error("Error connecting to server");
std::cout << "done\n";
std::cout << "Creating context ... ";
if (!(ssl = SSL_new(ctx)))
int_error("Error creating an SSL context");
std::cout << "done\n";
SSL_set_bio(ssl, conn, conn);
std::cout << "Opening connection ... ";
if (SSL_connect(ssl) <= 0)
int_error("Error connecting SSL object");
std::cout << "done\n";
SSL_write(ssl, "The client is connected", 26);
char buff[64] = {0};
int bread = SSL_read(ssl, buff, sizeof buff);
if (bread > 0)
std::cout << "The key has been recieved\n";
myfile.open ("keypair.pem");
myfile << buff;
myfile.close();
SSL_shutdown(ssl);
SSL_free(ssl);
std::cout << "SSL connection finished\n";
SSL_CTX_free(ctx);
std::cout << "Client finished\n";
}
Can someone show me what i did wrong and it would be great if someone can tell me how i can get my private key and public keys(server generated) separately. Thanks a lot guys...really appreciate it

Related

(C++ multithread / socket) When two clients connect with server, first connection disconnected

I'm making simple chatting program with c++.
The structure of the server program like this,
■ MAIN
check client connection
if client connected -> make sub thread to connection with client
■ SUB THREAD
recv message from client
when client disconnected, delete User(custom class) Object from userList(std::vector)
The problem is, when I execute one client, sending message to server works well.
And execute second client(it means two clients have connection with server at the same time), second client send message is fine, but when send message to server with first client, first client disconnected from server.
I tried:
When I add dump User Object to userList(0), it works well. (why?) => I think something wrong with initialize vector, but i'm not sure.
I did't use mutex yet, but I think this problem is not cause by not using mutex.
this is my codes:
Server.cpp
#include "Server.h"
void communicateClient(std::vector<User*>* userList, User* user) {
bool clientConnected = true;
char recvMessage[Constants::NETWORK_MESSAGE_SIZE] = { 0, };
while (clientConnected) {
if (recv(user->getUserSocket(), recvMessage, sizeof(recvMessage), 0) == -1) {
std::cout
<< Constants::LOG_NETWORK
<< std::to_string(user->getUserSockAddrIn().sin_addr.S_un.S_un_b.s_b1) << "."
<< std::to_string(user->getUserSockAddrIn().sin_addr.S_un.S_un_b.s_b2) << "."
<< std::to_string(user->getUserSockAddrIn().sin_addr.S_un.S_un_b.s_b3) << "."
<< std::to_string(user->getUserSockAddrIn().sin_addr.S_un.S_un_b.s_b4) << ":"
<< std::to_string(user->getUserSockAddrIn().sin_port) << " client disconnected" << std::endl;
clientConnected = false;
}
else {
std::cout
<< Constants::LOG_NETWORK
<< std::to_string(user->getUserSockAddrIn().sin_addr.S_un.S_un_b.s_b1) << "."
<< std::to_string(user->getUserSockAddrIn().sin_addr.S_un.S_un_b.s_b2) << "."
<< std::to_string(user->getUserSockAddrIn().sin_addr.S_un.S_un_b.s_b3) << "."
<< std::to_string(user->getUserSockAddrIn().sin_addr.S_un.S_un_b.s_b4) << ":"
<< std::to_string(user->getUserSockAddrIn().sin_port) << " send message: "
<< recvMessage << std::endl;
}
}
closesocket(user->getUserSocket());
std::vector<User*>::iterator userIterator;
for (userIterator = userList->begin(); userIterator != userList->end(); userIterator++) {
if ((*userIterator)->getUserId() == user->getUserId()) {
delete(*userIterator);
userList->erase(userIterator);
break;
}
}
std::cout << "client count: " << userList->size() << std::endl;
}
int main() {
WSADATA wsaData;
SOCKET serverSocket;
SOCKADDR_IN serverAddr;
std::cout << Constants::LOG_START << "Chatting server started" << std::endl;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
std::cout << Constants::LOG_ERROR << "Error WSAStartup()" << std::endl;
return -1;
}
serverSocket = socket(AF_INET, SOCK_STREAM, Constants::PROTOCOL);
if (serverSocket == INVALID_SOCKET) {
std::cout << Constants::LOG_ERROR << "Error socket()" << std::endl;
}
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
inet_pton(AF_INET, Constants::SERVER_IP.c_str(), &serverAddr.sin_addr);
serverAddr.sin_port = htons(Constants::SERVER_PORT);
if (bind(serverSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
std::cout << Constants::LOG_ERROR << "Error bind()" << std::endl;
}
if (listen(serverSocket, Constants::CLIENT_CONNECT_LIMIT) == SOCKET_ERROR) {
std::cout << Constants::LOG_ERROR << "Error listen()" << std::endl;
}
std::vector<User*> userList;
std::vector<std::thread*> clientConnectionThread;
serverState = true;
while (serverState) {
std::cout << Constants::LOG_WAIT << "waiting client connection..." << std::endl;
SOCKADDR_IN clientSockAddrIn;
SOCKET clientSocket;
int clientSockAddrInSize = sizeof(clientSockAddrIn);
clientSocket = accept(serverSocket, (SOCKADDR*)&clientSockAddrIn, &clientSockAddrInSize);
if (clientSocket == SOCKET_ERROR) {
std::cout << Constants::LOG_ERROR << "Error accept()" << std::endl;
}
else {
std::cout
<< Constants::LOG_SUCCESS
<< std::to_string(clientSockAddrIn.sin_addr.S_un.S_un_b.s_b1) << "."
<< std::to_string(clientSockAddrIn.sin_addr.S_un.S_un_b.s_b2) << "."
<< std::to_string(clientSockAddrIn.sin_addr.S_un.S_un_b.s_b3) << "."
<< std::to_string(clientSockAddrIn.sin_addr.S_un.S_un_b.s_b4) << ":"
<< std::to_string(clientSockAddrIn.sin_port) << " client connected" << std::endl;
User* user = new User;
user->setUserSocket(clientSocket);
user->setUserSockAddrIn(clientSockAddrIn);
userList.push_back(user);
clientConnectionThread.push_back(new std::thread(communicateClient, &userList, std::ref(userList.back())));
std::cout << "client count: " << userList.size() << std::endl;
}
}
std::vector<std::thread>::iterator threadIterator;
for (threadIterator = clientConnectionThread.begin(); threadIterator != clientConnectionThread.end(); threadIterator++) {
(*threadIterator).join();
}
WSACleanup();
return 0;
}
Client.cpp
#include "Client.h"
int main() {
WSADATA wsaData;
SOCKET serverSocket;
SOCKADDR_IN serverAddr;
std::cout << "client start" << std::endl;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
std::cout << "Failed WSAStartup()" << std::endl;
}
serverSocket = socket(PROTOCOL_TYPE, SOCK_STREAM, IPPROTO_TCP);
if (serverSocket == INVALID_SOCKET) {
std::cout << "Failed socket()" << std::endl;
}
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = PROTOCOL_TYPE;
inet_pton(AF_INET, SERVER_IP.c_str(), &serverAddr.sin_addr);
serverAddr.sin_port = htons(SERVER_PORT);
std::cout << "connecting to server..." << std::endl;
while (true) {
if (connect(serverSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
std::cout << "Fail to connect server: retry in 2 seconds..." << std::endl;
Sleep(1000);
}
else {
break;
}
}
std::string sendMessage;
char recvMessage[256] = { 0, };
printf("send message to server...\n");
while (true) {
std::cout << "Write Message: ";
std::getline(std::cin, sendMessage);
send(serverSocket, sendMessage.c_str(), sendMessage.length() + 1, 0);
}
closesocket(serverSocket);
WSACleanup();
system("pause");
return 0;
}

Sending and Receiving From a Server Simultaneously

The way my code is currently written only allows a message from the server to be read directly after input is taken and a message is sent. However, this code is for a chat server and must allow a read to occur at any time a message is sent.
#include <iostream>
#include <string>
#include <cstring>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#define SERVER_ADDRESS "127.0.0.1"
constexpr int server_port = 15555;
#define SERVER_SUCCESS "1"
#define SERVER_FAILURE "-1"
constexpr int msg_buffer_size = 4096;
int main(int argc, char *argv[])
{
struct sockaddr_in serv_addr;
int sock;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
std::cerr << "Socket creation failed!" << std::endl;
return 1;
}
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(server_port);
if (inet_pton(AF_INET, SERVER_ADDRESS, &serv_addr.sin_addr) <= 0)
{
std::cerr << "Invalid server address!" << std::endl;
return 1;
}
if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
{
std::cerr << "Failed to connect to chat server!" << std::endl;
return 1;
}
int valread;
while (true)
{
std::cout << ">> ";
char msg[msg_buffer_size];
char return_msg[msg_buffer_size];
std::string input;
std::getline(std::cin, input);
if (input == "quit")
return 0;
if (input.length() > 4000)
{
std::cout << "Input length must be less than 4000 characters." << std::endl;
continue;
}
strcpy(msg, input.c_str());
if (send(sock, msg, strlen(msg), 0) < 0)
{
std::cout << "Error sending data." << std::endl;
continue;
}
if (recv(sock, return_msg, msg_buffer_size, 0) < 0)
{
std::cout << "Error receiving data." << std::endl;
continue;
}
std::string code(strtok(return_msg, " "));
if (code == SERVER_FAILURE)
std::cout << "Failure: " << strtok(NULL, "") << std::endl;
else
std::cout << strtok(NULL, "") << std::endl;
memset(msg, 0, msg_buffer_size);
memset(return_msg, 0, msg_buffer_size);
}
std::cout << "Exiting." << std::endl;
close(sock);
return 0;
}
What would be a correct way to allow the client to receive a message as soon as one is sent from the server? I was thinking about making a thread, but it seemed kind of redundant since I would be receiving in two places.

Winsock Connection C++ not connecting to either IPv4 or External Ip Address

So I have been developing something for multi-computer use (I'm working on a botnet in order to prove for a school project that computers can be easily hacked as a project for GITA) and I can't seem to make a connection with the server and client. The client can connect via 127.0.0.1, however, when attempted to connect via IPv4 or the external ip (can be found www.whatsmyip.org) it doesn't seem to work. So I have tried everything, even disabling my firewall but nothing.
I'm wondering if I happened to make a mistake in my code?
Client:
#include "client.h"
Client* Client::clientptr;
int Client::Initalize(const char* add)
{
char ownPth[MAX_PATH];
// When NULL is passed to GetModuleHandle, the handle of the exe itself is returned
HMODULE hModule = GetModuleHandle(NULL);
if (hModule != NULL)
{
// Use GetModuleFileName() with module handle to get the path
GetModuleFileName(hModule, ownPth, (sizeof(ownPth)));
std::cout << ownPth << std::endl;
}
else
{
std::cout << "Module handle is NULL" << std::endl;
}
WSAData wsaData;
WORD DllVersion = MAKEWORD(2, 1);
if (WSAStartup(DllVersion, &wsaData) != 0)
{
std::cout << "ERROR: WINSOCK INVALID!" << std::endl;
exit(0);
}
std::cout << "Setting SOCKADDR_IN addr..." << std::endl;
addrlen = sizeof(addr);
addr.sin_addr.s_addr = inet_addr(add);
addr.sin_port = htons(4403);
addr.sin_family = AF_INET;
connection = socket(AF_INET, SOCK_STREAM, NULL);
while (true)
{
std::cout << "Attempting connection..." << std::endl;
if (connect(connection, (SOCKADDR*)&addr, addrlen) > 0 || connect == 0)
{
std::cout << "Connection established!" << std::endl;
break;
}
std::cout << "Error: Failed to connect! Retrying... " << std::endl;
Sleep(1000);
}
clientptr = this;
return 0;
}
int Client::Run()
{
std::cout << std::endl << "Running..." << std::endl;
while (true)
{
Sleep(10);
}
return 0;
}
Server:
#include "server.h"
Server* Server::serverptr; //Serverptr is necessary so the static ClientHandler method can access the server instance/functions.
int Server::Initalize()
{
std::cout << "Setting crash handler..." << std::endl;
std::cout << "Looking at winsock dll version..." << std::endl;
WSADATA wsaData;
WORD DllVersion = MAKEWORD(2, 1);
if (WSAStartup(DllVersion, &wsaData) != 0)
{
MessageBoxA(NULL, "Winsock startup failed", "Error", MB_OK | MB_ICONERROR);
exit(1);
}
std::cout << "Creating listening socket..." << std::endl;
addrlen = sizeof(addr);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(4403);
addr.sin_family = AF_INET;
std::cout << "The socket data addr "
<< "{"
<< "addr.sin_addr.s_addr = " << addr.sin_addr.s_addr
<< ", addr.sin_port = " << addr.sin_port
<< ", addr.sin_family = " << addr.sin_family
<< "}" << std::endl;
sListen = socket(AF_INET, SOCK_STREAM, NULL); //Create socket to listen for new connections
if (bind(sListen, (SOCKADDR*)&addr, sizeof(addr)) == SOCKET_ERROR) //Bind the address to the socket, if we fail to bind the address..
{
std::string ErrorMsg = "Failed to bind the address to our listening socket. Winsock Error:" + std::to_string(WSAGetLastError());
MessageBoxA(NULL, ErrorMsg.c_str(), "Error", MB_OK | MB_ICONERROR);
exit(1);
}
if (listen(sListen, SOMAXCONN) == SOCKET_ERROR) //Places sListen socket in a state in which it is listening for an incoming connection. Note:SOMAXCONN = Socket Oustanding Max connections, if we fail to listen on listening socket...
{
std::string ErrorMsg = "Failed to listen on listening socket. Winsock Error:" + std::to_string(WSAGetLastError());
MessageBoxA(NULL, ErrorMsg.c_str(), "Error", MB_OK | MB_ICONERROR);
exit(1);
}
std::cout << "Finalizing..." << std::endl;
output = false;
currClient = 0;
std::cout << "Setting serverptr..." << std::endl;
serverptr = this;
std::cout << "Creating Threads..." << std::endl;
serverptr->Listening = false;
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)Listen, NULL, NULL, NULL); //Create thread that will manage all outgoing packets
while (serverptr->Listening == false);
std::cout << "Done Initalizing!" << std::endl << std::endl;
return 0;
}
int Server::Run()
{
std::cout << "Running server...";
serverptr->Listening = true;
while (true)
{
std::string userinput;
int inputInt;
HANDLE hConsoe = GetStdHandle(STD_OUTPUT_HANDLE);
while (true)
{
std::cout << std::endl << "] ";
std::getline(std::cin, userinput);
serverptr->HandleInput(userinput);
}
}
return 0;
}
void Server::Listen()
{
if (serverptr->output)
std::cout << "Listener socket running..." << std::endl;
serverptr->Listening = true;
while (true)
{
if (serverptr->Listening == true)
{
SOCKET newConnection //the connection for the socket
= accept(serverptr->sListen, (SOCKADDR*)&serverptr->addr, &serverptr->addrlen); //Accept a new connection
if (newConnection == 0)
{
if (serverptr->output)
std::cout << "FAILED TO ACCEPT THE CLIENTS CONNECTION!" << std::endl;
}
else
{
if (serverptr->output)
{
std::cout << "A connection has been made [" << inet_ntoa(serverptr->addr.sin_addr) << "]!" << std::endl;
std::cout << "Creating Client(" << newConnection << ")..." << std::endl;
}
Client newClient(newConnection, serverptr->addr);
int connectionId = serverptr->clients.size();
serverptr->clients.push_back(newClient);
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)RecvClient, NULL, NULL, NULL); //Create thread that will manage all incomming packets
int index = serverptr->clients.size() - 1;
while (!serverptr->clients[index].Listening);
if (serverptr->output)
std::cout << "Client success [" << (index + 1) << "]!" << std::endl;
}
}
}
return;
}
void Server::RecvClient()
{
int index = serverptr->clients.size() - 1;
char data[1600];
if (serverptr->output)
std::cout << "Listening for client[" << (index + 1) << "]..." << std::endl;
serverptr->clients[index].Listening = true;
while (true)
{
recv(serverptr->clients[index]._socket, data, sizeof(data), 0);
if (serverptr->output)
std::cout << "Data Recieved from client[" << (index + 1) << "]!" << std::endl;
if ((int)data[0] < 0)
{
if (serverptr->output)
std::cout << "Client [" << (index + 1) << "] is disconnecting with the current code {" << (int)data[0] << "}..." << std::endl;
serverptr->DisconnectClient(index);
break;
}
}
if (serverptr->output)
std::cout << "No longer listening for client[" << (index + 1) << "]!" << std::endl;
}
void Server::HandleInput(std::string string)
{
std::string sHandle = string;
std::istringstream iss(string);
std::vector<std::string> sTokens((std::istream_iterator<std::string>(iss)),
std::istream_iterator<std::string>());
if (sHandle == "cls")
{
system("cls");
return;
}
if (sHandle == "list")
{
int index = serverptr->clients.size() - 1;
std::cout << "Total Clients: " << serverptr->clients.size() << std::endl;
for (int i = 0; i < serverptr->clients.size(); i++)
{
std::cout << (char)195 << (char)196 << " Client [" << i + 1 << "] {" << serverptr->clients[i]._socket << ", " << inet_ntoa(serverptr->clients[i]._address.sin_addr) << "}" << std::endl;
}
return;
}
if (sHandle == "data")
{
std::cout << "Toggling data output..." << std::endl;
serverptr->output = true;
return;
}
if (sTokens[0] == "broadcast")
{
int change = 0;
std::cout << "Toggling client: ";
if (sTokens.size() > 1)
{
std::stringstream strings(sTokens[1]);
strings >> change;
if (change > serverptr->clients.size())
{
change = serverptr->clients.size();
}
}
if (change > 0) std::cout << change << std::endl;
else std::cout << "All" << std::endl;
serverptr->currClient = change;
return;
}
std::cout << "Error: Unknown command!" << std::endl;
return;
}
void Server::DisconnectClient(int id)
{
if (serverptr->output)
std::cout << "void Server::DisconnectClient(" << id << ")..." << std::endl;
closesocket(serverptr->clients[id]._socket);
serverptr->clients.erase(serverptr->clients.begin() + (id));
return;
}
Client::Client(SOCKET socket, SOCKADDR_IN address)
{
this->_address = address;
this->_socket = socket;
this->Listening = false;
}

Connecting to an IRC server, getting Ping timeout without receiving PING message

I'm trying my hands at network programming for the first time, implementing a small IRC bot using the SFML network functionality.
The connection gets established, but from there on I can't do much else. Trying to receive any data from the server yields nothing, until I get the "Ping timeout" message after a few seconds.
Removing all or some of the receive() calls in the loginOnIRC function doesn't do any good.
Trying to connect via telnet with the exact same messages works. Here I get a PING message right after sending my NICK message.
Am I missing something?
My code is as follows
#include <iostream>
#include <string>
#include <SFML/Network.hpp>
#define ARRAY_LEN(x) (sizeof(x)/sizeof(*x))
void receive(sf::TcpSocket* sck)
{
char rcvData[100];
memset(rcvData, 0, ARRAY_LEN(rcvData));
std::size_t received;
if (sck->receive(rcvData, ARRAY_LEN(rcvData), received) != sf::Socket::Done)
{
std::cout << "oops" << std::endl;
}
std::cout << "Received " << received << " bytes" << std::endl;
std::cout << rcvData << std::endl;
}
int establishConnection(sf::TcpSocket* sck)
{
sf::Socket::Status status = sck->connect("irc.euirc.net", 6667, sf::seconds(5.0f));
if (status != sf::Socket::Done)
{
std::cout << "Error on connect!" << std::endl;
return 1;
}
std::cout << "Connect was successful!" << std::endl;
return 0;
}
int loginOnIRC(sf::TcpSocket* sck)
{
receive(sck); // We get a Ping timeout here
std::string data{ "NICK NimBot" };
if(sck->send(data.c_str(), data.length()) != sf::Socket::Done)
{
std::cout << "Error on sending " << data << std::endl;
return 1;
}
receive(sck);
data = "USER NimBot * * :Nimelrians Bot";
if (sck->send(data.c_str(), data.length()) != sf::Socket::Done)
{
std::cout << "Error on sending " << data << std::endl;
return 1;
}
receive(sck);
data = "JOIN #nimbottest";
if (sck->send(data.c_str(), data.length()) != sf::Socket::Done)
{
std::cout << "Error on sending " << data << std::endl;
return 1;
}
return 0;
}
int main()
{
sf::TcpSocket sck{};
establishConnection(&sck); // works
loginOnIRC(&sck);
while(true)
{
char data[100];
memset(data, 0, ARRAY_LEN(data));
std::size_t received;
sf::Socket::Status rcvStatus = sck.receive(data, ARRAY_LEN(data), received);
if (rcvStatus != sf::Socket::Done)
{
std::cout << "oops" << std::endl;
if (rcvStatus == sf::Socket::Disconnected)
{
break;
}
}
std::cout << "Received " << received << " bytes" << std::endl;
std::cout << data << std::endl;
}
return 0;
}

Passing Object over Server to client

I am trying to create a client server application in linux. Server is supposed to send one object to all connected clients.
Here is the code for it.
In this When server send object, everything remains ok at server side but Segmentation fault occurs on client server immediately it receive it.
Server:
#include "Question.h"
#include <iostream>
#include <string.h>
using namespace std;
#include<sys/socket.h>
#include<sys/types.h>
#include<stdio.h>
#include<arpa/inet.h>
#include<time.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>
int main() {
Question q1("Capital Of Pakistan?", "Lahore", "Karachi", "Quetaa", "Islamabad");
int socketID = 0, clientID[10] = {0}, totalClients = 3;
char sendBuffer[1024];
memset(sendBuffer, '0', sizeof(sendBuffer));
time_t time;
struct sockaddr_in servAddr;
cout << "Question is: \n" << q1.getQuestion()<<endl;
cout << q1.getOpt1() << endl << q1.getOpt2() << endl << q1.getOpt3() << endl << q1.getCorrect()<<endl;
cout << "\n\n --- Server starting up --- \n\n";
/*
* Creating Socket
*/
socketID = socket(AF_INET, SOCK_STREAM, 0);
if (socketID == -1) {
cerr << " Can't create Socket";
}
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(5000);
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
/*
* Binding IP
*/
int bindID;
bindID = bind(socketID, (struct sockaddr *) &servAddr, sizeof(servAddr)); // Casting sockaddr_in on sockaddr and binding it with socket id
if (bindID != -1) {
cout << " Bind SucessFull";
listen(socketID, 5);
cout << " Server Waiting for connections" << endl;
int i = 0;
while (1) {
clientID[i] = accept(socketID, (struct sockaddr *) NULL, NULL);
cout << "Got Client: " << i+1 << ","<<totalClients-(i+1)<<" to go" << endl;
cout << "ID: " << clientID[i]<<endl;
cout.flush();
snprintf(sendBuffer, sizeof(sendBuffer), "%.24s\n", ctime(&time));
write(clientID[i], sendBuffer, strlen(sendBuffer));
i++;
if (i >= totalClients)
break;
sleep(1);
}
cout << "Sending Question to All Clients...." << endl;
for(int j=0; j<totalClients; j++) {
cout << "Sending to ID " << clientID[j]<<endl;
write(clientID[j], &q1 , sizeof(q1));
cout << "Sent " << j << "...." << endl;
}
/*
* Closing all clients
*/
for (int k = 0; k < totalClients; k++) {
close(clientID[k]);
}
} else {
cerr << " Unable to Bind";
}
return 0;
}
Client:
#include "Question.h"
#include <iostream>
#include <string.h>
using namespace std;
#include<sys/socket.h>
#include<sys/types.h>
#include<stdio.h>
#include<arpa/inet.h>
#include<time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int main(int argc, char *argv[])
{
int socketID = 0 /*Socket Descriptor*/, n = 0;
char recvBuffer[1024];
memset(recvBuffer, '0',sizeof(recvBuffer));
struct sockaddr_in servAddr;
if(argc!=2){
cout << "\n Usage: %s <ip of server> \n",argv[0];
return 1;
}
socketID = socket(AF_INET, SOCK_STREAM, 0);
if(socketID == -1){
cerr << "\n Can't create socket \n";
return 1;
}
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(5000);
if(inet_pton(AF_INET, argv[1], &servAddr.sin_addr)==-1){
cerr << "\n Unable to convert given IP to Network Form \n inet_pton Error";
return 1;
}
int connectFlag;
connectFlag = connect(socketID, (struct sockaddr *)&servAddr, sizeof(servAddr));
if(connectFlag == -1){
cout << " Connection Failed" << endl;
return 1;
}
n = read(socketID, recvBuffer, sizeof(recvBuffer)-1);
recvBuffer[n] = 0;
cout << recvBuffer << endl;
if(n < 0){
cerr << "Buffer Read error\n";
}
Question q1;
cout << "Gonna Receive Connections"<<endl;
q1.setAll("0","0","0","0","0");
cout.flush();
n = read(socketID, &q1, sizeof(q1));
cout << n << endl;
cout << "Received Question " << endl;
cout << "Question is: \n" << q1.getQuestion()<<endl;
cout << q1.getOpt1() << endl << q1.getOpt2() << endl << q1.getOpt3() << endl << q1.getCorrect()<<endl;
cout.flush();
return 0;
}
Question.h
#ifndef QUESTION_H_
#define QUESTION_H_
#include <iostream>
using namespace std;
class Question {
private:
string question;
string opt1;
string opt2;
string opt3;
string correct;
public:
/*
* Constructors
*/
Question();
Question(string, string, string, string, string);
void setAll(string, string, string, string, string);
string getCorrect() const;
void setCorrect(string correct);
string getOpt1() const;
void setOpt1(string opt1);
string getOpt2() const;
void setOpt2(string opt2);
string getOpt3() const;
void setOpt3(string opt3);
void setQuestion(string question);
string getQuestion() const;
};
#endif /* QUESTION_H_ */
You will need to "serialize" your object. This usually involves making it into a string that can be read at the other "side" of whatever thing you are sending the object through.
It is exactly the same issue as if you were to write the data to a file, you don't want to store the OBJECT, you want to store the "payload" or "content" of that is inside the class.
You can use stringstream to form a long string of your data, and pass the string formed from that.
Something like:
class A
{
int x;
string s;
};
...
class A a;
stringstream ss;
ss << a.x << ", " << a.s << endl;
....
write(clientID[j], ss.str.c_str(), ss.str.length());
You will obviously need to parse the resulting string at the other end - and , may not be the ideal separator. Feel free to use something else...