Sign in to follow this  
alextoti99

Client - Server

Recommended Posts

Guys im creating a client - server communication with a simple chat server with local host now.

But when im loging in with the client the server stops working

also the client is like writing black lines all the time.

the code:

Client:

#include <iostream>
#include <Windows.h>
#include <WinSock.h>

#pragma comment (lib, "ws2_32")

using namespace std;

SOCKET sConnect;
SOCKADDR_IN addr;

int Startup_WinSock()
{
    WSADATA wsaData;
        WORD DllVersion = MAKEWORD(2, 1);
        int Val = WSAStartup(DllVersion, &wsaData);
    return Val;
}

int ClientThread()
{
    char *Buffer = new char[256];
    int size = 0;
    while (true)
    {
        ZeroMemory(Buffer, 256);
        if ((size = recv(sConnect, Buffer, 256, NULL)) > 0);
        {
            cout << Buffer << endl;
        }
        Sleep(50);
    }
}
    int main()
    {
        system("color 0a");

        int Val = Startup_WinSock();

        if (Val != 0)
        {
            cout << "Cant start WinSock" << endl;
            exit(1);
        }
        sConnect = socket(AF_INET, SOCK_STREAM, NULL);
        addr.sin_addr.s_addr = inet_addr("127.0.0.1");
        addr.sin_port = htons(2222);
        addr.sin_family = AF_INET;
        cout << "Please press [ENTER]" << endl;
        cin.get();
        Val = connect(sConnect, (SOCKADDR*)&addr, sizeof(addr));

        if (Val != 0)
        {
            cout << "Cant login to the server" << endl;
            main();
        }
        else
        {
            system("cls");
            int ID;
            char *nID = new char[64];
            char *hello = new char[256];
            ZeroMemory(hello, 256);
            ZeroMemory(nID, 64);
            recv(sConnect, nID, 64, NULL);
            recv(sConnect, hello, 64, NULL);
            ID = atoi(nID);
            cout << hello << endl;
            cout << "Your ID:" << " " << ID << endl;
            cout << " If you are ready press [ENTER]" << endl;
            cin.get();

            system("cls");
            CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ClientThread, NULL, NULL, NULL);

            while (true)
            {
                char *MSG = new char[256];
                ZeroMemory(MSG, 256);
                cin.getline(MSG, 256);
                send(sConnect, MSG, 256, NULL);
                Sleep(50);
            }
        }
        return 0;
    }

Server:

#include <iostream>
#include <Windows.h>
#include <WinSock.h>

using namespace std;

#pragma comment (lib, "ws2_32")

SOCKADDR_IN addr; // this  saves the ip and port of the server
int addrlen = sizeof(addr);

int Counter; // this counts how many clients are connected in the server

SOCKET sConnect; // 1 socket for incoming connections
SOCKET sListen; // 1 socket for listening
SOCKET *Connections; // 1 which saves the connections

int InitWinSock()
{
	int Val = 0; 
	WSAData wsaData;
	WORD DllVersion = MAKEWORD(2, 1);

	Val = WSAStartup(DllVersion, &wsaData);



	return Val;
}

int ServerThread(int ID)
{
	char *Buffer = new char[256];
	int size = 0;
	while (true)
	{
		ZeroMemory(Buffer, 256);
		for (int a = 0; a < Counter; a++)
		{
		if ((size = recv(Connections[ID], Buffer, 256, NULL)) > 0)
			
				{if (Connections[a] == Connections[ID])
					ZeroMemory(Buffer, 256);
				printf(Buffer, "Client[%i]: %s", ID, Buffer);
				cout << "New Message: " << Buffer << endl;
				}
		else {
			ZeroMemory(Buffer, 256);
			printf(Buffer,  "Client[%i]: %s", ID, Buffer);
			send(Connections[a], Buffer, 256, NULL);
		}
			}
	}
}

int main ()
{
	system("color 0a");

	cout << "Server Started Successfully" << endl;

	int Val = InitWinSock();

	if (Val != 0)
	{
		MessageBoxA(NULL, "Error while attempting to load WinSock", "Error", MB_OK | MB_ICONERROR);
		exit(1);
	}

	Connections = (SOCKET*)calloc(64, sizeof(SOCKET));

	sListen = socket(AF_INET, SOCK_STREAM, NULL);
	sConnect = socket(AF_INET, SOCK_STREAM, NULL);

	addr.sin_addr.s_addr = inet_addr("127.0.0.1");
	addr.sin_port = htons(2222);
	addr.sin_family = AF_INET;

	bind(sListen, (SOCKADDR*)&addr, sizeof(addr));
	listen(sListen, 64);

	while (true)
	{
		if (sConnect = accept(sListen, (SOCKADDR*)&addr, &addrlen))
		{
			Connections[Counter] = sConnect;
			char *Name = new char[64];
			ZeroMemory(Name, 64);
			printf(Name, "%i", Counter);
			send(Connections[Counter], Name, 64, NULL);
			send(Connections[Counter], "Welcome To The Mysteries Of Genesys", 64, NULL);
			cout << "New Connection" << endl;
			Counter++;
			CreateThread(NULL, NULL, NULL,(LPTHREAD_START_ROUTINE)ServerThread, NULL, NULL);
		}
		Sleep(50);
	}
}

Could u help me? :3

Thx in advance

 

But if i use the one created some hours before:

#include <WinSock.h>
#include <iostream>
#include <Windows.h>

using namespace std;

#pragma comment (lib, "ws2_32.lib") //<-- we need this lib

SOCKADDR_IN addr; // this  saves the ip and port of the server
int addrlen = sizeof(addr);

int Counter; // this counts how many clients are connected in the server

SOCKET sConnect; // 1 socket for incoming connections
SOCKET sListen; // 1 socket for listening
SOCKET *Connections; // 1 which saves the connections

int InitWinSock()
{
	int Val = 0; // this will say to us when the action will fail
	WSAData wsaData;
	WORD DllVersion = MAKEWORD(2, 1);

	Val = WSAStartup(DllVersion, &wsaData); //here the winsock will be initialized



	return Val;
}

int ServerThread(int ID)
{
	char *Buffer = new char[256];
	int size = 0;

	while (true)
	{
		ZeroMemory(Buffer, 256);

		if ((size = recv(Connections[ID], Buffer, 256, NULL)) > 0);  // the following steps will be followed only if the msg isnt empty
		{
			for (int a = 0; a < Counter; a++)
			{
				if (Connections[a] == Connections[ID])
				{
					ZeroMemory(Buffer, 256);
					printf(Buffer, " Client[%i]: %s", ID, Buffer);
					cout << Buffer << endl;
				}
				else
				{
					ZeroMemory(Buffer, 256);
					printf(Buffer, " Client[%i]: %s", ID, Buffer);
					send(Connections[a], Buffer, 256, NULL);
				}
			}
		}
	}
}
	int main()
	{
		cout << "Server started" << endl;
		system("Color  0a");

		int  Val = InitWinSock();

		if (Val != 0)
		{
			MessageBoxA(NULL, " Error while attempting to Startup Winsock!", "Error", MB_OK | MB_ICONERROR);
			exit(1);
		}

		Connections = (SOCKET*)calloc(64, sizeof(SOCKET));
		sListen = socket(AF_INET, SOCK_STREAM, NULL);
		sConnect = socket(AF_INET, SOCK_STREAM, NULL);

		addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // server ip
		addr.sin_port = htons(2222); // server port
		addr.sin_family = AF_INET; // this is the kind of connection

		bind(sListen, (SOCKADDR*)&addr, sizeof(addr)); // first we bind the server to the ip and port

		listen(sListen, 64);

		while (true) // in this endless loop we search for connections
		{
			if (sConnect = accept(sListen, (SOCKADDR*)&addr, &addrlen)) // here the connection is accepted
			{
				Connections[Counter] = sConnect;

				char *Name = new char[64]; // the name of the client

				ZeroMemory(Name, 64); // we make  the char empty

				printf(Name, "%i", Counter);

				send(Connections[Counter], Name, 64, NULL);
				send(Connections[Counter], "Welcome", 64, NULL); // welcome msg

				cout << "New Connection" << Counter << endl;

				Counter++; // +1 client :D		

				CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ServerThread, (LPVOID)(Counter - 1), NULL, NULL);

			}
			Sleep(50); // the server waits for 50 miliseconds
		}
	}

is responding well, but the messages from the clients arent sent to the others also the client is like writing black lines all the time again

Edited by alextoti99

Share this post


Link to post
Share on other sites

also i always get the same id (0) from every client

 

edit:

 

changed the client code to:

#include <iostream>
#include <Windows.h>
#include <WinSock.h>

#pragma comment (lib, "ws2_32")

using namespace std;

SOCKET sConnect;
SOCKADDR_IN addr;

int Startup_WinSock()
{
	WSADATA wsaData;
		WORD DllVersion = MAKEWORD(2, 1);
		int Val = WSAStartup(DllVersion, &wsaData);
	return Val;
}

int ClientThread()
{
	char *Buffer = new char[256];
	int size = 0;

	while (true)
	{
		ZeroMemory(Buffer, 256);

		if ((size = recv(sConnect, Buffer, 256, NULL)) > 0);
		{
			cout << Buffer << endl;
		}
		Sleep(50);
	}

}

	int main()
	{
		system("color 0a");

		int Val = Startup_WinSock();

		if (Val != 0)
		{
			cout << "Cant start WinSock" << endl;
			exit(1);
		}
		sConnect = socket(AF_INET, SOCK_STREAM, NULL);
		addr.sin_addr.s_addr = inet_addr("127.0.0.1");
		addr.sin_port = htons(2222);
		addr.sin_family = AF_INET;
		cout << "Please press [ENTER]" << endl;
		cin.get();
		Val = connect(sConnect, (SOCKADDR*)&addr, sizeof(addr));

		if (Val != 0)
		{
			cout << "Cant login to the server" << endl;
			main();
		}
		else
		{
			system("cls");
			int ID;
			char *nID = new char[64];
			char *hello = new char[256];
			ZeroMemory(hello, 256);
			ZeroMemory(nID, 64);
			recv(sConnect, nID, 64, NULL);
			recv(sConnect, hello, 64, NULL);
			ID = atoi(nID);
			cout << hello << endl;
			cout << "Your ID:" << " " << ID << endl;
			cout << " If you are ready press [ENTER]" << endl;
			cin.get();

			system("cls");
			CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ClientThread, NULL, NULL, NULL);

			while (true)
			{
				char *MSG = new char[256];

				ZeroMemory(MSG, 256);

				cin.getline(MSG, 256);

				send(sConnect, MSG, 256, NULL);

				Sleep(50);
			}
		}
		return 0;
	}

and when im sending a msg from the other client its like a get a msg but writing nth its a blank like to the other client

Edited by alextoti99

Share this post


Link to post
Share on other sites

Some bad smells I found looking at your code (I am a linux programer, so take what I say with a grain of salt).

 

First, why are you creating one thread for each socket? You can use select or poll to watch for multiple sockets, it will lead to a much simpler code.

 

Second, on the server code, are those printfs correct? Is there any redefinition of it for windows that I am not aware about? Because I am pretty sure you should be using sprintf  there instead (or even better, snprintf).

 

Finally, some of your "send" commands are with constant 64 size, when the buffers are not 64 bytes long, you should definitely fix this.

Share this post


Link to post
Share on other sites

Not pimping this, really, because it's not completed yet and some of it is still very messy, but please take a look at the TCPServer and TCPSocket classes and make note of some of the differences:
 
https://github.com/khatharr/SimpleSocks
 
You may also want to look at the implementation of the SSocks::select() function to see how ::select() is used, since - as KnolanCross mentioned - a unique thread of each connection is often overkill.
 
Actually, to simplify some of it a bit...

Using recv()
std::vector<char> SSocks::TCPSocket::coreRecv(size_t len) {
  if(!isOpen()) { throw std::runtime_error("Attempted recv on closed TCPSocket."); }

  std::vector<char> data(len);
  
  int got = ::recv(sock, data.data(), data.size(), 0);
  if(got == SOCKET_ERROR) { 
    close();
    throw std::runtime_error("Error reading from socket!");
  }

  //recv() returns zero if the socket was closed by the remote host
  if(got == 0) { close(); }

  data.resize(got);

  return data;
}

.

Using send()
size_t SSocks::TCPSocket::send(const char* data, size_t len) {
  if(!isOpen()) { throw std::runtime_error("Attempted send on closed TCPSocket."); }

  int sent = ::send(sock, data, len, 0);
  if(sent == SOCKET_ERROR) {
    close(); //if a socket operation fails you should usually assume that the socket is now bad
    throw std::runtime_error("Failure during send.");
  }

  return sent;
}

.

Setting up a listener
//localHostAddr should be the IP address of a local interface, not a host name. the default is "0.0.0.0" to listen on all interfaces
void SSocks::TCPServer::start(uint16_t port, const std::string& localHostAddr) {

  //We need a sockaddr_in to bind the server to a port and interface.
  sockaddr_in sain = {0};
  sain.sin_family = AF_INET;
  sain.sin_port = htons(port);

  //This shouldn't fail unless you type in gibberish, but let's be safe.
  int result = inet_pton(AF_INET, localHostAddr.c_str(), &sain.sin_addr);
  switch(result) {
  case 0: throw std::runtime_error("Attempted to start server on interface with invalid address string.");
  case -1: throw std::runtime_error("Failed to generate address from string while creating server.");
  }

  //assume a member variable named 'servSock' that holds the socket handle for the listener
  servSock = ::socket(AF_INET, SOCK_STREAM, 0);
  //~~check for errors here
  
  //bind the socket
  result = bind(servSock, reinterpret_cast<sockaddr*>(&sain), sizeof(sain));
  if(result) { throw std::runtime_error("Failed to bind listener."); }

  result = listen(servSock, SOMAXCONN);
  if(result) { throw std::runtime_error("Failed to listen on bound socket."); }
}

.

Accepting an incoming connection
int SSocks::TCPServer::accept() {
  if(!isOpen()) { throw std::runtime_error("Attemtped to wait for connections on closed TCPServer."); }

  int nuSock = ::accept(servSock, nullptr, nullptr);
  if(nuSock == SOCKET_ERROR) { throw std::runtime_error("Failure while accepting incoming connection."); }

  return nuSock;
}

.

Connecting to a remote host
void SSocks::TCPSocket::connect(const HostAddress& host) {
  if(isOpen()) { close(); }

  //assume this is a member variable
  sock = ::socket(SOCK_STREAM, IPPROTO_TCP, 0);
  //~~ check for errors

  //try to connect to address
  int err = ::connect(sock, host, sizeof(sockaddr_in));
  if(err) {
    closesocket(sock);
    throw std::runtime_error("Failed to connect to remote host.");
  }
}

.

Keep in mind that if you want to print strings that you got over the wire you may need to manually place a null terminator at the end of the string to indicate its end.

Share this post


Link to post
Share on other sites

if i use sprintfs i get errors , that says that they are not safe

 

Your entire code is unsafe given that you're firing off threads that share sockets and data with no attempt at synchronisation or locks. You really need to reconsider your entire approach.

Share this post


Link to post
Share on other sites
if i use sprintfs i get errors , that says that they are not safe

 

The short answer is: use snprintf (notice the 'n' threre).

 

Where you have:

printf(Name, "%i", Counter);

Change to:

snprintf(Name, 64, "%i", Counter);

The long answer is:

printf is used to write on the stdout, and on stdout only. The reason you are not having any error messages is because it will receive a formated string and any number of arguments. When you use:

printf(Name, "%i", Counter);

The compiler will assume that Name is a formatted string such as "Hello %i", and the following arguments will be used to format the percent marked points in your string, since the compiler doesn't know the contents of the variable Name it will assume that you know what you are doing and leave no warnings or errors. When your code is executed, Name is empty and it will print an empty string and ignore the "%i" and Counter variables.

 

The compiler is complaining about sprintf because it is indeed unsafe. If you try to write 80 bytes on the Name variable, it will not check the actual size and it will write outside it bounds, which will likely end up crashing your program sooner or later (in my experience, later, on another malloc).

 

On the other hand, snprintf will use the second argument as the size of the buffer and will not write more than n bytes (or n -1, depends on the implementation) on it, hence it is considered safe.

 

Here is the documentation for snprintf: https://msdn.microsoft.com/en-us/library/2ts7cx93.aspx

 

PS: you should free the Name variable after you send it, or use char Name[64] instead.

Edited by KnolanCross

Share this post


Link to post
Share on other sites

well i changed the code but now im taking this error:

Severity    Code    Description    Project    File    Line    Suppression State
Error    C4996    'inet_addr': Use inet_pton() or InetPton() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings    client    c:\users\alex_\documents\visual studio 2015\projects\client\client\main.cpp    20    
 

the code:

#pragma comment(lib,"ws2_32.lib")
#include <WinSock2.h>
#include <iostream>
#include <Windows.h>

int main()
{
    system("color 0a");
    //Winsock Startup
    WSAData wsaData;
    WORD DllVersion = MAKEWORD(2, 1);
    if (WSAStartup(DllVersion, &wsaData) != 0) //If WSAStartup returns anything other than 0, then that means an error has occured in the WinSock Startup.
    {
        MessageBoxA(NULL, "Winsock startup failed", "Error", MB_OK | MB_ICONERROR);
        exit(1);
    }

    SOCKADDR_IN addr; //Address to be binded to our Connection socket
    int sizeofaddr = sizeof(addr); //Need sizeofaddr for the connect function
    addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // The ip that the client will be logged in
    addr.sin_port = htons(555); // The port that will use
    addr.sin_family = AF_INET; //IPv4 Socket

    SOCKET Connection = socket(AF_INET, SOCK_STREAM, NULL); //Set Connection socket
    if (connect(Connection, (SOCKADDR*)&addr, sizeofaddr) != 0) //If we are unable to connect...
    {
        MessageBoxA(NULL, "Failed to Connect", "Error", MB_OK | MB_ICONERROR);
        return 0; //Failed to Connect
    }
    std::cout << "Connected!" << std::endl;

    char MOTD[256];
    recv(Connection, MOTD, sizeof(MOTD), NULL); // The msg that the client will get on login
    std::cout << "MOTD:" << MOTD << std::endl;
    while (true)
    {
        Sleep(10);
    }
}

 

Share this post


Link to post
Share on other sites

if i use inet_pton i get this error:

Severity    Code    Description    Project    File    Line    Suppression State
Error (active)        identifier "inet_pton" is undefined    server    c:\Users\alex_\Documents\Visual Studio 2015\Projects\server\server\main.cpp    37    
Severity    Code    Description    Project    File    Line    Suppression State
Error (active)        identifier "InetPton" is undefined    server    c:\Users\alex_\Documents\Visual Studio 2015\Projects\server\server\main.cpp    37    

 


but if i add this
#include <ws2tcpip.h>

    addr.sin_addr.s_addr = inet_pton("127.0.0.1"); //Broadcast locally

 

but im getting this error

Severity    Code    Description    Project    File    Line    Suppression State
Error (active)        argument of type "const char *" is incompatible with parameter of type "INT"    server    c:\Users\alex_\Documents\Visual Studio 2015\Projects\server\server\main.cpp    38    
 

Share this post


Link to post
Share on other sites

hi again:

main.cpp:

#include "Server.h"
#include <iostream>
#include "ConfigFile.cpp"

using namespace std;

int main()
{
	system("color 0a");
	std::cout << "Server Started" << std::endl;
	Server MyServer(srvport); //port is stored in the config file
	for (int i = 0; i < 100; i++) //Up to 100 times...
	{
		MyServer.ListenForNewConnection(); //Accept new connection (if someones trying to connect)
	}
	system("pause");
	return 0;
}

ConfigFile.cpp:

#include <iostream>
#include <string>
#include <sstream>
#include <map>
#include <fstream>

class Convert
{
public:
	template <typename T>
	static std::string T_to_string(T const &val)
	{
		std::ostringstream ostr;
		ostr << val;

		return ostr.str();
	}

	template <typename T>
	static T string_to_T(std::string const &val)
	{
		std::istringstream istr(val);
		T returnVal;
		if (!(istr >> returnVal))
			exitWithError("CFG: Not a valid " + (std::string)typeid(T).name() + " received!\n");

		return returnVal;
	}

	template <>
	static std::string string_to_T(std::string const &val)
	{
		return val;
	}
};

void exitWithError(const std::string &error)
{
	std::cout << error;
	std::cin.ignore();
	std::cin.get();

	exit(EXIT_FAILURE);
}

class ConfigFile
{
private:
	std::map<std::string, std::string> contents;
	std::string fName;

	void removeComment(std::string &line) const
	{
		if (line.find(';') != line.npos)
			line.erase(line.find(';'));
	}

	bool onlyWhitespace(const std::string &line) const
	{
		return (line.find_first_not_of(' ') == line.npos);
	}
	bool validLine(const std::string &line) const
	{
		std::string temp = line;
		temp.erase(0, temp.find_first_not_of("\t "));
		if (temp[0] == '=')
			return false;

		for (size_t i = temp.find('=') + 1; i < temp.length(); i++)
			if (temp[i] != ' ')
				return true;

		return false;
	}

	void extractKey(std::string &key, size_t const &sepPos, const std::string &line) const
	{
		key = line.substr(0, sepPos);
		if (key.find('\t') != line.npos || key.find(' ') != line.npos)
			key.erase(key.find_first_of("\t "));
	}
	void extractValue(std::string &value, size_t const &sepPos, const std::string &line) const
	{
		value = line.substr(sepPos + 1);
		value.erase(0, value.find_first_not_of("\t "));
		value.erase(value.find_last_not_of("\t ") + 1);
	}

	void extractContents(const std::string &line)
	{
		std::string temp = line;
		temp.erase(0, temp.find_first_not_of("\t "));
		size_t sepPos = temp.find('=');

		std::string key, value;
		extractKey(key, sepPos, temp);
		extractValue(value, sepPos, temp);

		if (!keyExists(key))
			contents.insert(std::pair<std::string, std::string>(key, value));
		else
			exitWithError("CFG: Can only have unique key names!\n");
	}

	void parseLine(const std::string &line, size_t const lineNo)
	{
		if (line.find('=') == line.npos)
			exitWithError("CFG: Couldn't find separator on line: " + Convert::T_to_string(lineNo) + "\n");

		if (!validLine(line))
			exitWithError("CFG: Bad format for line: " + Convert::T_to_string(lineNo) + "\n");

		extractContents(line);
	}

	void ExtractKeys()
	{
		std::ifstream file;
		file.open(fName.c_str());
		if (!file)
			exitWithError("CFG: File " + fName + " couldn't be found!\n");

		std::string line;
		size_t lineNo = 0;
		while (std::getline(file, line))
		{
			lineNo++;
			std::string temp = line;

			if (temp.empty())
				continue;

			removeComment(temp);
			if (onlyWhitespace(temp))
				continue;

			parseLine(temp, lineNo);
		}

		file.close();
	}
public:
	ConfigFile(const std::string &fName)
	{
		this->fName = fName;
		ExtractKeys();
	}

	bool keyExists(const std::string &key) const
	{
		return contents.find(key) != contents.end();
	}

	template <typename ValueType>
	ValueType getValueOfKey(const std::string &key, ValueType const &defaultValue = ValueType()) const
	{
		if (!keyExists(key))
			return defaultValue;

		return Convert::string_to_T<ValueType>(contents.find(key)->second);
	}
	};

	int srvport;

int Configs()
{
	ConfigFile cfg("config.cfg");

	int srvport = cfg.getValueOfKey<int>("srvport", 1111);

	std::cin.get();
	return 0;
}

im getting these errors:

Severity	Code	Description	Project	File	Line	Suppression State
Error	LNK2005	"void __cdecl exitWithError(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?exitWithError@@YAXABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) already defined in ConfigFile.obj	serverside	C:\Users\alex_\Documents\Visual Studio 2015\Projects\serverside\serverside\Server.obj	1	


Severity	Code	Description	Project	File	Line	Suppression State
Error	LNK2005	"void __cdecl exitWithError(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?exitWithError@@YAXABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) already defined in ConfigFile.obj	serverside	C:\Users\alex_\Documents\Visual Studio 2015\Projects\serverside\serverside\Source.obj	1	

Severity	Code	Description	Project	File	Line	Suppression State
Error	LNK1169	one or more multiply defined symbols found	serverside	C:\Users\alex_\Documents\Visual Studio 2015\Projects\serverside\Debug\serverside.exe	1	

Severity	Code	Description	Project	File	Line	Suppression State
Error	LNK2005	_main already defined in Server.obj	serverside	C:\Users\alex_\Documents\Visual Studio 2015\Projects\serverside\serverside\Source.obj	1	

does anyone know how to fix them?

also are the configuration file ok?

and config.cfg:

srvport = 1111;

Share this post


Link to post
Share on other sites

Define exitWithError() in one place and refer to it. Don't just redefine it in every TLU unless you have some reason to do so.
 
If you do have such a reason (You really, truly don't, believe me.) then make it static in all the places where it's defined, or put it within the scope of an anonymous namespace.

 
It also appears to be complaining that you have main() defined more than once...
 
Wait, are you including .cpp files?
 

main.cpp:

#include "ConfigFile.cpp"

 

Nononononononono...

 

Include headers. Don't include cpp files.

 

Headers should only contain declarations and inlines, cpp files should contain definitions.

 

Declaration:

void foo();

Definition:

void foo() {
  std::cout << bar();
}

When you compile your program each cpp file is treated as a translation unit. The compiler pulls in the headers that it includes and builds that unit, then when the units are all compiled the linker starts pasting them together. The reason headers are used is that the cpp file can refer to things that have been declared but not defined - as long as the linker can find those things later on when it's pulling everything together. In your case you're including a cpp file, so the compiler builds 'ConfigFile.cpp' and then tried to build main.cpp, but because of the include there it compiles all of ConfigFile.cpp again in the main.cpp TLU (main.obj). When the linker goes to pull the program together it finds things that exist in both places and it doesn't know which one to use in what place, so you get link errors.

Share this post


Link to post
Share on other sites

sth like this?

ConfigFile.cpp:

#include <iostream>
#include <string>
#include <sstream>
#include <map>
#include <fstream>

using namespace std;

class Convert
{
public:
    template <typename T>
    static std::string T_to_string(T const &val)
    {
        std::ostringstream ostr;
        ostr << val;

        return ostr.str();
    }

    template <typename T>
    static T string_to_T(std::string const &val)
    {
        std::istringstream istr(val);
        T returnVal;
        if (!(istr >> returnVal))
            cout << "error" << endl;

        return returnVal;
    }

    template <>
    static std::string string_to_T(std::string const &val)
    {
        return val;
    }
};

class ConfigFile
{
private:
    std::map<std::string, std::string> contents;
    std::string fName;

    void removeComment(std::string &line) const
    {
        if (line.find(';') != line.npos)
            line.erase(line.find(';'));
    }

    bool onlyWhitespace(const std::string &line) const
    {
        return (line.find_first_not_of(' ') == line.npos);
    }
    bool validLine(const std::string &line) const
    {
        std::string temp = line;
        temp.erase(0, temp.find_first_not_of("\t "));
        if (temp[0] == '=')
            return false;

        for (size_t i = temp.find('=') + 1; i < temp.length(); i++)
            if (temp[i] != ' ')
                return true;

        return false;
    }

    void extractKey(std::string &key, size_t const &sepPos, const std::string &line) const
    {
        key = line.substr(0, sepPos);
        if (key.find('\t') != line.npos || key.find(' ') != line.npos)
            key.erase(key.find_first_of("\t "));
    }
    void extractValue(std::string &value, size_t const &sepPos, const std::string &line) const
    {
        value = line.substr(sepPos + 1);
        value.erase(0, value.find_first_not_of("\t "));
        value.erase(value.find_last_not_of("\t ") + 1);
    }

    void extractContents(const std::string &line)
    {
        std::string temp = line;
        temp.erase(0, temp.find_first_not_of("\t "));
        size_t sepPos = temp.find('=');

        std::string key, value;
        extractKey(key, sepPos, temp);
        extractValue(value, sepPos, temp);

        if (!keyExists(key))
            contents.insert(std::pair<std::string, std::string>(key, value));
        else
            cout << "error" << endl;
    }

    void parseLine(const std::string &line, size_t const lineNo)
    {
        if (line.find('=') == line.npos)
            cout << "error" << endl;

        if (!validLine(line))
            cout << "bad format" << endl;

        extractContents(line);
    }

    void ExtractKeys()
    {
        std::ifstream file;
        file.open(fName.c_str());
        if (!file)
            cout << "CFG file couldnt be found" << endl;

        std::string line;
        size_t lineNo = 0;
        while (std::getline(file, line))
        {
            lineNo++;
            std::string temp = line;

            if (temp.empty())
                continue;

            removeComment(temp);
            if (onlyWhitespace(temp))
                continue;

            parseLine(temp, lineNo);
        }

        file.close();
    }
public:
    ConfigFile(const std::string &fName)
    {
        this->fName = fName;
        ExtractKeys();
    }

    bool keyExists(const std::string &key) const
    {
        return contents.find(key) != contents.end();
    }

    template <typename ValueType>
    ValueType getValueOfKey(const std::string &key, ValueType const &defaultValue = ValueType()) const
    {
        if (!keyExists(key))
            return defaultValue;

        return Convert::string_to_T<ValueType>(contents.find(key)->second);
    }
};

int mainC()
{
    ConfigFile cfg("config.cfg");
    int srvport = cfg.getValueOfKey<int>("srvport", 1111);
    std::cin.get();
    return 0;
}

Config.h:

#pragma once
#include <iostream>
#include <string>
#include <sstream>
#include <map>
#include <fstream>


class Convert;
class ConfigFile;
int mainC();

but im getting errors in the main.cpp

#include "Server.h"
#include <iostream>
#include <string>
#include <sstream>
#include <map>
#include <fstream>
#include "ConfigFile.h"

using namespace std;



int main()
{
    system("color 0a");
    std::cout << "Server Started" << std::endl;
    Server MyServer(srvport); //port is stored in the config file
    for (int i = 0; i < 100; i++) //Up to 100 times...
    {
        MyServer.ListenForNewConnection(); //Accept new connection (if someones trying to connect)
    }
    system("pause");
    return 0;
}

Errors:

Severity    Code    Description    Project    File    Line    Suppression State
Error    C2065    'srvport': undeclared identifier    serverside    c:\users\alex_\documents\visual studio 2015\projects\serverside\serverside\source.cpp    17    

Severity    Code    Description    Project    File    Line    Suppression State
Error (active)        identifier "srvport" is undefined    serverside    c:\Users\alex_\Documents\Visual Studio 2015\Projects\serverside\serverside\Source.cpp    17    


(Updated)

Edited by alextoti99

Share this post


Link to post
Share on other sites
int main()
{
    system("color 0a");
    std::cout << "Server Started" << std::endl;
    Server MyServer(srvport); //port is stored in the config file
    for (int i = 0; i < 100; i++) //Up to 100 times...
    {
        MyServer.ListenForNewConnection(); //Accept new connection (if someones trying to connect)
    }
    system("pause");
    return 0;
}
The error says exactly what your problem is, srvport isn't defined where you're writing it.

Also you can't really put a blank class definition in a header and then a defined one in a cpp file because then the compiler can't figure out the size of the class if anything else tries to instantiate a copy of it.

Share this post


Link to post
Share on other sites

A class header generally looks something like:

#pragma once

class Foo {
public:
  Foo();
  ~Foo();
  void frobnicate();
private:
  int value;
};

And the cpp file would be:

#include "Foo.h"
#include <iostream>

Foo::Foo() {
  value = 0;
}

Foo::~Foo() {
  std::cout << "The object had a value of " << value << " when it was destroyed!\n";
}

void Foo::frobnicate() {
  value++;
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this