diff --git a/Code/Misc/ThreadSafeQueue.h b/Code/Misc/ThreadSafeQueue.h index d0125f71..19775f55 100644 --- a/Code/Misc/ThreadSafeQueue.h +++ b/Code/Misc/ThreadSafeQueue.h @@ -132,6 +132,7 @@ namespace Oyster this->front = NULL; this->back = NULL; } + mutex.UnlockMutex(); return item; } @@ -146,6 +147,7 @@ namespace Oyster mutex.LockMutex(); if(front != NULL) { + mutex.UnlockMutex(); return this->front->item; } mutex.UnlockMutex(); diff --git a/Code/Network/NetworkDependencies/Connection.cpp b/Code/Network/NetworkDependencies/Connection.cpp index 3f303542..19556bbd 100644 --- a/Code/Network/NetworkDependencies/Connection.cpp +++ b/Code/Network/NetworkDependencies/Connection.cpp @@ -96,7 +96,7 @@ int Connection::Recieve(OysterByte& bytes) { int nBytes; - bytes.Clear(1000); + bytes.Resize(1000); nBytes = recv(this->socket, bytes, 500, 0); if(nBytes == SOCKET_ERROR) { @@ -109,8 +109,6 @@ int Connection::Recieve(OysterByte& bytes) std::cout << "Size of the recieved data: " << nBytes << " bytes" << std::endl; - //bytes.byteArray[nBytes] = '\0'; - return 0; } @@ -139,15 +137,24 @@ int Connection::InitiateSocket() return 0; } -void Connection::SetBlockingMode(bool blocking) +int Connection::SetBlockingMode(bool blocking) { - //TODO: Implement this function. Setting the socket to blocking or non-blocking. + DWORD nonBlocking; + if(blocking) { - //fcntl(this->socket, F_SETFL, O_NONBLOCK); + nonBlocking = 0; } else { - + nonBlocking = 1; } + + int result = ioctlsocket(this->socket, FIONBIO, &nonBlocking); + if(result != 0) + { + return WSAGetLastError(); + } + + return 0; } \ No newline at end of file diff --git a/Code/Network/NetworkDependencies/Connection.h b/Code/Network/NetworkDependencies/Connection.h index b46ccb02..27933abf 100644 --- a/Code/Network/NetworkDependencies/Connection.h +++ b/Code/Network/NetworkDependencies/Connection.h @@ -20,7 +20,6 @@ namespace Oyster Connection( int socket ) { this->socket = socket; }; virtual ~Connection(); - virtual int InitiateServer( unsigned short port ); virtual int InitiateClient(); @@ -32,9 +31,11 @@ namespace Oyster virtual int Listen(); + //Setting the socket to blocking/non-blocking mode. + int SetBlockingMode( bool blocking ); + private: int InitiateSocket(); - void SetBlockingMode( bool blocking ); int socket; diff --git a/Code/Network/NetworkDependencies/IPostBox.h b/Code/Network/NetworkDependencies/IPostBox.h index 31c1bef7..70dc7558 100644 --- a/Code/Network/NetworkDependencies/IPostBox.h +++ b/Code/Network/NetworkDependencies/IPostBox.h @@ -15,7 +15,7 @@ namespace Oyster public: virtual ~IPostBox() {} virtual void PostMessage(T& message) = 0; - virtual void FetchMessage(T& message) = 0; + virtual bool FetchMessage(T& message) = 0; virtual bool IsFull() = 0; }; diff --git a/Code/Network/NetworkDependencies/OysterByte.cpp b/Code/Network/NetworkDependencies/OysterByte.cpp index ef7aa434..8df493f1 100644 --- a/Code/Network/NetworkDependencies/OysterByte.cpp +++ b/Code/Network/NetworkDependencies/OysterByte.cpp @@ -21,13 +21,20 @@ OysterByte::~OysterByte() delete[] byteArray; } -void OysterByte::Clear(unsigned int cap) +void OysterByte::Clear() { - delete[] byteArray; - byteArray = new unsigned char[cap]; size = 0; } +void OysterByte::Resize(unsigned int cap) +{ + if(capacity < cap) + { + delete[] byteArray; + byteArray = new unsigned char[cap]; + } +} + int OysterByte::GetSize() { return size; diff --git a/Code/Network/NetworkDependencies/OysterByte.h b/Code/Network/NetworkDependencies/OysterByte.h index 87a0103c..9a6bc75a 100644 --- a/Code/Network/NetworkDependencies/OysterByte.h +++ b/Code/Network/NetworkDependencies/OysterByte.h @@ -18,7 +18,8 @@ namespace Oyster OysterByte(int cap); virtual ~OysterByte(); - void Clear(unsigned int cap); + void Clear(); //Resets size to 0 + void Resize(unsigned int cap); //Resizes the array with, it does not keep anything in it. int GetSize(); unsigned char* GetByteArray(); diff --git a/Code/Network/NetworkDependencies/PostBox.h b/Code/Network/NetworkDependencies/PostBox.h index b2e553f8..960b6f34 100644 --- a/Code/Network/NetworkDependencies/PostBox.h +++ b/Code/Network/NetworkDependencies/PostBox.h @@ -23,7 +23,7 @@ namespace Oyster virtual ~PostBox(); virtual void PostMessage(T& message); - virtual void FetchMessage(T& message); + virtual bool FetchMessage(T& message); virtual bool IsFull(); private: @@ -49,13 +49,15 @@ namespace Oyster } template - void PostBox::FetchMessage(T& message) + bool PostBox::FetchMessage(T& message) { if(IsFull()) { message = messages.Front(); - messages.Pop(); + messages.Pop(); + return true; } + return false; } template diff --git a/Code/Network/NetworkDependencies/ThreadedClient.cpp b/Code/Network/NetworkDependencies/ThreadedClient.cpp index 73a5ebb2..dafe70b8 100644 --- a/Code/Network/NetworkDependencies/ThreadedClient.cpp +++ b/Code/Network/NetworkDependencies/ThreadedClient.cpp @@ -4,7 +4,6 @@ using namespace Oyster::Network; using namespace Oyster::Thread; - ThreadedClient::ThreadedClient() { this->connection = new Connection(); @@ -17,6 +16,21 @@ ThreadedClient::ThreadedClient(unsigned int socket) this->connection = new Connection(socket); this->sendPostBox = new PostBox(); this->recvPostBox = NULL; + + connection->SetBlockingMode(false); + + thread.Create(this, true); +} + +ThreadedClient::ThreadedClient(IPostBox* postBox, unsigned int socket) +{ + this->connection = new Connection(socket); + this->sendPostBox = new PostBox; + this->recvPostBox = postBox; + + connection->SetBlockingMode(false); + + thread.Create(this, true); } ThreadedClient::~ThreadedClient() @@ -35,7 +49,9 @@ ThreadedClient::~ThreadedClient() int ThreadedClient::Send(OysterByte* byte) { + mutex.LockMutex(); this->sendPostBox->PostMessage(byte); + mutex.UnlockMutex(); return 0; } @@ -43,13 +59,13 @@ int ThreadedClient::Send() { int errorCode = 0; mutex.LockMutex(); - if(!sendPostBox->IsFull()) + if(sendPostBox->IsFull()) { OysterByte *temp = NULL; sendPostBox->FetchMessage(temp); errorCode = this->connection->Send(*temp); - mutex.UnlockMutex(); } + mutex.UnlockMutex(); return errorCode; } @@ -57,42 +73,48 @@ int ThreadedClient::Send() int ThreadedClient::Recv() { int errorCode = 0; - mutex.LockMutex(); - if(!recvPostBox->IsFull()) + + OysterByte *temp = new OysterByte(); + errorCode = this->connection->Recieve(*temp); + + if(errorCode == 0) { - OysterByte *temp = NULL; - errorCode = this->connection->Recieve(*temp); + mutex.LockMutex(); recvPostBox->PostMessage(temp); mutex.UnlockMutex(); } + else + { + delete temp; + } + return errorCode; } void ThreadedClient::ThreadEntry() { - std::cout<< "Thread started" << std::endl; + std::cout<< "Client Thread started" << std::endl; } void ThreadedClient::ThreadExit() { - std::cout << "Thread exit" << std::endl; + std::cout << "Client Thread exit" << std::endl; } bool ThreadedClient::DoWork() { int errorCode; errorCode = Send(); - - if(errorCode != 0) + /*if(errorCode != 0) { return false; - } + }*/ errorCode = Recv(); - if(errorCode != 0) + /*if(errorCode != 0) { return false; - } + }*/ return true; } diff --git a/Code/Network/NetworkDependencies/ThreadedClient.h b/Code/Network/NetworkDependencies/ThreadedClient.h index 384fe96c..dbf99347 100644 --- a/Code/Network/NetworkDependencies/ThreadedClient.h +++ b/Code/Network/NetworkDependencies/ThreadedClient.h @@ -20,6 +20,7 @@ namespace Oyster public: ThreadedClient(); ThreadedClient(unsigned int socket); + ThreadedClient(IPostBox* postBox, unsigned int socket); virtual ~ThreadedClient(); int Send(OysterByte* byte); @@ -27,8 +28,8 @@ namespace Oyster int Connect(unsigned short port, const char serverName[]); void setRecvPostBox(IPostBox* postBox); - private: + private: virtual int Send(); virtual int Recv(); @@ -36,9 +37,7 @@ namespace Oyster virtual void ThreadExit(); virtual bool DoWork(); - - - + private: Connection* connection; IPostBox* sendPostBox; IPostBox* recvPostBox; diff --git a/Code/Network/OysterNetworkClient/ClientMain.cpp b/Code/Network/OysterNetworkClient/ClientMain.cpp index bbf2ec6f..45861c96 100644 --- a/Code/Network/OysterNetworkClient/ClientMain.cpp +++ b/Code/Network/OysterNetworkClient/ClientMain.cpp @@ -7,14 +7,18 @@ #include "../NetworkDependencies/OysterByte.h" #include "../../Misc/ThreadSafeQueue.h" #include "../NetworkDependencies/ThreadedClient.h" +#include "../../Misc/WinTimer.h" +#include "../../Misc/Utilities.h" #pragma comment(lib, "ws2_32.lib") using namespace std; using namespace Oyster::Network::Protocols; using namespace Oyster::Network; +using namespace Utility; void chat(ThreadedClient &client); +void PrintOutMessage(ProtocolSet* set); int main() { @@ -27,10 +31,10 @@ int main() cout << "Client" << endl; //Create Client - ThreadedClient client; + ThreadedClient* client = new ThreadedClient; //Connect to server - errorCode = client.Connect(9876, "localhost"); + errorCode = client->Connect(9876, "localhost"); if(errorCode != 0) { @@ -38,7 +42,8 @@ int main() wcout << "errorMessage: " << errorTest << endl; } - //chat(client); + chat(*client); + delete client; ShutdownWinSock(); @@ -49,82 +54,77 @@ int main() void chat(ThreadedClient &client) { Oyster::Network::Translator *t = new Oyster::Network::Translator(); + IPostBox* postBox = new PostBox; - Oyster::Network::OysterByte msgRecv; - string msgSend = ""; + client.setRecvPostBox(postBox); + + Oyster::Network::OysterByte* msgRecv = NULL; + Oyster::Network::OysterByte* msgSend = new OysterByte(); ProtocolSet* set = new ProtocolSet; ProtocolPlayerPos test; test.ID = 5; - test.matrix = new float[16]; + test.nrOfFloats = 5; + test.matrix = new float[test.nrOfFloats]; float temp = 10; - for(int i = 0; i < 5; i++) + for(int i = 0; i < (int)test.nrOfFloats; i++) { test.matrix[i] = temp; temp++; } + t->Pack(test, *msgSend); - bool chatDone = false; - /* - while(!chatDone) + WinTimer timer; + + while(1) { - client.Recv(msgRecv); - - t->Unpack(set, msgRecv); - - switch(set->type) + //Fetch new messages from the postbox + if(postBox->FetchMessage(msgRecv)) { - case PackageType_header: - break; - case PackageType_test: - cout <<"Client 2: " << set->Protocol.pTest->textMessage <Protocol.pTest->numOfFloats; i++) - { - cout << set->Protocol.pTest->f[i] << ' ' ; - } - cout << endl; - break; - case PackageType_player_pos: - cout << "Server: ID " << set->Protocol.pPlayerPos->ID << endl; - for(int i = 0; i < set->Protocol.pPlayerPos->nrOfFloats; i++) - { - cout << set->Protocol.pPlayerPos->matrix[i] << ' '; - } - cout << endl; - break; - } - - set->Release(); - msgRecv.Clear(1000); + t->Unpack(set, *msgRecv); + delete msgRecv; - /*std::getline(std::cin, msgSend); - - - - if( msgSend != "exit") - { - if(msgSend.length() < 1) - { - msgSend = "ERROR!"; - } - - test.textMessage = msgSend; - - t->Pack(test, msgRecv); - - client.Send(msgRecv); + PrintOutMessage(set); + set->Release(); } - else + //Send message to server each second + if(timer.getElapsedSeconds() > 1) { - chatDone = true; + cout << "Sending to server." << endl; + timer.reset(); + client.Send(msgSend); } - - cin.clear();*/ - /* } + delete msgSend; + delete postBox; delete t; delete set; - */ +} + +void PrintOutMessage(ProtocolSet* set) +{ + switch(set->type) + { + case PackageType_header: + break; + case PackageType_test: + cout <<"Client 2: " << set->Protocol.pTest->textMessage <Protocol.pTest->numOfFloats; i++) + { + cout << set->Protocol.pTest->f[i] << ' ' ; + } + cout << endl; + break; + + case PackageType_player_pos: + cout << "ID " << set->Protocol.pPlayerPos->ID << endl; + for(int i = 0; i < (int)set->Protocol.pPlayerPos->nrOfFloats; i++) + { + cout << set->Protocol.pPlayerPos->matrix[i] << ' '; + } + cout << endl; + break; + } } \ No newline at end of file diff --git a/Code/Network/OysterNetworkServer/ServerMain.cpp b/Code/Network/OysterNetworkServer/ServerMain.cpp index ec35b1e1..95a07641 100644 --- a/Code/Network/OysterNetworkServer/ServerMain.cpp +++ b/Code/Network/OysterNetworkServer/ServerMain.cpp @@ -18,10 +18,15 @@ using namespace Oyster::Network; using namespace ::Protocols; using namespace Utility; +void PrintOutMessage(ProtocolSet* set); + int main() { - OysterByte recvBuffer; + OysterByte sendBuffer; + OysterByte* recvBuffer = NULL; + ProtocolSet* set = new ProtocolSet; IPostBox* postBox = new PostBox(); + IPostBox* recvPostBox = new PostBox(); cout << "Server" << endl; Translator t; @@ -43,7 +48,7 @@ int main() ProtocolPlayerPos test; test.clientID = 0; test.ID = 5; - test.nrOfFloats = 16; + test.nrOfFloats = 10; test.matrix = new float[test.nrOfFloats]; for(int i = 0; i < (int)test.nrOfFloats; i++) @@ -51,7 +56,7 @@ int main() test.matrix[i] = (float)i; } - t.Pack(test, recvBuffer); + t.Pack(test, sendBuffer); WinTimer timer; @@ -59,14 +64,13 @@ int main() int client = -1; while(1) { - client = -1; - postBox->FetchMessage(client); - if(client != -1) + //Fetch new clients from the postbox + if(postBox->FetchMessage(client)) { cout << "Client connected: " << client << endl; - clients.push_back(new ThreadedClient(client)); + clients.push_back(new ThreadedClient(recvPostBox, client)); - clients.at(clients.size()-1)->Send(&recvBuffer); + clients.at(clients.size()-1)->Send(&sendBuffer); } //Send a message every 1 secounds to all clients. @@ -76,51 +80,52 @@ int main() timer.reset(); for(int i = 0; i < (int)clients.size(); i++) { - clients.at(i)->Send(&recvBuffer); + clients.at(i)->Send(&sendBuffer); } } - Sleep(100); + + //Fetch messages + if(recvPostBox->FetchMessage(recvBuffer)) + { + t.Unpack(set, *recvBuffer); + delete recvBuffer; + + PrintOutMessage(set); + set->Release(); + } + + Sleep(1); } listener.Shutdown(); - /* - ProtocolSet* set = new ProtocolSet; - - client1.Send(recvBuffer); - - while(1) - { - client1.Recv(recvBuffer); - - t.Unpack(set, recvBuffer); - cout << set->Protocol.pTest->clientID << ' ' << set->Protocol.pTest->packageType << ' ' << set->Protocol.pTest->size << endl; - cout << "Client1: " << set->Protocol.pTest->textMessage << endl; - for(int i = 0; i < (int)set->Protocol.pTest->numOfFloats; i++) - { - cout << set->Protocol.pTest->f[i] << ' '; - } - cout << endl; - set->Release(); - client2.Send(recvBuffer); - - client2.Recv(recvBuffer); - - t.Unpack(set, recvBuffer); - cout << set->Protocol.pTest->clientID << ' ' << set->Protocol.pTest->packageType << ' ' << set->Protocol.pTest->size << endl; - cout << "Client2: " << set->Protocol.pTest->textMessage << endl; - for(int i = 0; i < (int)set->Protocol.pTest->numOfFloats; i++) - { - cout << set->Protocol.pTest->f[i] << ' '; - } - cout << endl; - set->Release(); - client1.Send(recvBuffer); - } - - - ShutdownWinSock(); - delete set; - */ system("pause"); + + delete postBox; return 0; } + +void PrintOutMessage(ProtocolSet* set) +{ + switch(set->type) + { + case PackageType_header: + break; + case PackageType_test: + cout <<"Client 2: " << set->Protocol.pTest->textMessage <Protocol.pTest->numOfFloats; i++) + { + cout << set->Protocol.pTest->f[i] << ' ' ; + } + cout << endl; + break; + + case PackageType_player_pos: + cout << "ID " << set->Protocol.pPlayerPos->ID << endl; + for(int i = 0; i < (int)set->Protocol.pPlayerPos->nrOfFloats; i++) + { + cout << set->Protocol.pPlayerPos->matrix[i] << ' '; + } + cout << endl; + break; + } +} \ No newline at end of file