diff --git a/Code/Game/GameClient/GameClientState/LanMenuState.cpp b/Code/Game/GameClient/GameClientState/LanMenuState.cpp index 1baed344..c1341f32 100644 --- a/Code/Game/GameClient/GameClientState/LanMenuState.cpp +++ b/Code/Game/GameClient/GameClientState/LanMenuState.cpp @@ -9,6 +9,8 @@ #include "GameState.h" #include "../Network/NetworkAPI/NetworkClient.h" +#include + #include "EventHandler\EventHandler.h" #include "Buttons\ButtonRectangle.h" #include "Buttons\TextField.h" @@ -21,6 +23,7 @@ using namespace ::Oyster; using namespace ::Oyster::Network; using namespace ::Oyster::Event; using namespace ::Oyster::Math3D; +using namespace ::GameLogic; struct LanMenuState::MyData { @@ -34,6 +37,9 @@ struct LanMenuState::MyData TextField *connectIP; unsigned short connectPort; + + std::string ip; + } privData; void OnButtonInteract_Connect( Oyster::Event::ButtonEvent& e ); @@ -82,6 +88,11 @@ bool LanMenuState::Init( SharedStateContent &shared ) this->privData->connectPort = 15151; + if(!this->privData->nwClient->StartListeningForBroadcasting(this->privData->connectPort)) + { + return false; + } + return true; } @@ -95,6 +106,8 @@ GameClientState::ClientState LanMenuState::Update( float deltaTime ) EventHandler::Instance().Update( mouseState ); + this->privData->nwClient->Update(); + return this->privData->nextState; } @@ -116,6 +129,11 @@ bool LanMenuState::Render( ) bool LanMenuState::Release() { + if(privData) + { + this->privData->nwClient->StopListeningForBroadcasting(); + } + privData = NULL; return true; } @@ -156,3 +174,41 @@ void OnButtonInteract_Exit( Oyster::Event::ButtonEvent& e ) default: break; } } + +const GameClientState::NetEvent& LanMenuState::DataRecieved( const NetEvent &message ) +{ + if( message.args.type == NetworkClient::ClientEventArgs::EventType_ProtocolFailedToSend ) + { // TODO: Reconnect + const char *breakpoint = "temp trap"; + this->privData->nwClient->Disconnect(); + this->ChangeState( GameClientState::ClientState_Main ); + } + + // fetching the id data. + short ID = message.args.data.protocol[0].value.netShort; + + CustomNetProtocol data = message.args.data.protocol; + + switch(ID) + { + case protocol_Broadcast_Test: + { + Protocol_Broadcast_Test decoded(data); + + unsigned short port = decoded.port; + std::string ip = decoded.ip; + std::string name = decoded.name; + printf("Broadcast message: %d: %s: %s\n", port, ip.c_str(), name.c_str()); + + //this->privData->connectPort = port; + //this->privData->ip = ip; + } + break; + + default: + break; + } + + + return message; +} diff --git a/Code/Game/GameClient/GameClientState/LanMenuState.h b/Code/Game/GameClient/GameClientState/LanMenuState.h index 57889eee..1edf1308 100644 --- a/Code/Game/GameClient/GameClientState/LanMenuState.h +++ b/Code/Game/GameClient/GameClientState/LanMenuState.h @@ -20,6 +20,8 @@ namespace DanBias virtual bool Render(); virtual bool Release(); void ChangeState( ClientState next ); + + virtual const NetEvent & DataRecieved( const NetEvent &message ); private: struct MyData; diff --git a/Code/Game/GameProtocols/GeneralProtocols.h b/Code/Game/GameProtocols/GeneralProtocols.h index db50b61f..cb58f3f8 100644 --- a/Code/Game/GameProtocols/GeneralProtocols.h +++ b/Code/Game/GameProtocols/GeneralProtocols.h @@ -72,5 +72,50 @@ namespace GameLogic Oyster::Network::CustomNetProtocol protocol; }; + //#define protocol_Broadcast_Test 102 + struct Protocol_Broadcast_Test :public Oyster::Network::CustomProtocolObject + { + unsigned short port; + std::string ip; + std::string name; + + Protocol_Broadcast_Test() + { + this->protocol[0].type = Oyster::Network::NetAttributeType_Short; + this->protocol[0].value.netShort = protocol_Broadcast_Test; + this->protocol[1].type = Oyster::Network::NetAttributeType_UnsignedShort; + this->protocol[2].type = Oyster::Network::NetAttributeType_CharArray; + this->protocol[3].type = Oyster::Network::NetAttributeType_CharArray; + this->port = 0; + } + Protocol_Broadcast_Test(unsigned short port, std::string ip, std::string name) + { + this->protocol[0].type = Oyster::Network::NetAttributeType_Short; + this->protocol[0].value.netShort = protocol_Broadcast_Test; + this->protocol[1].type = Oyster::Network::NetAttributeType_UnsignedShort; + this->port = port; + this->protocol[2].type = Oyster::Network::NetAttributeType_CharArray; + this->ip = ip; + this->protocol[3].type = Oyster::Network::NetAttributeType_CharArray; + this->name = name; + } + Protocol_Broadcast_Test(Oyster::Network::CustomNetProtocol& p) + { + this->port = p[1].value.netUShort; + this->ip.assign(p[2].value.netCharPtr); + this->name.assign(p[3].value.netCharPtr); + } + Oyster::Network::CustomNetProtocol GetProtocol() override + { + this->protocol[1].value = this->port; + this->protocol.Set(2, ip); + this->protocol.Set(3, name); + + return protocol; + } + + private: + Oyster::Network::CustomNetProtocol protocol; + }; } #endif //!GAMELOGIC_CONTROL_PROTOCOLS_H \ No newline at end of file diff --git a/Code/Game/GameProtocols/ProtocolIdentificationID.h b/Code/Game/GameProtocols/ProtocolIdentificationID.h index 79235e2f..e1a23850 100644 --- a/Code/Game/GameProtocols/ProtocolIdentificationID.h +++ b/Code/Game/GameProtocols/ProtocolIdentificationID.h @@ -20,6 +20,7 @@ #define protocol_GeneralMIN 100 #define protocol_General_Status 100 #define protocol_General_Text 101 +#define protocol_Broadcast_Test 102 #define protocol_GeneralMAX 199 diff --git a/Code/Game/GameServer/Implementation/GameServer.cpp b/Code/Game/GameServer/Implementation/GameServer.cpp index f003fc50..d2b86332 100644 --- a/Code/Game/GameServer/Implementation/GameServer.cpp +++ b/Code/Game/GameServer/Implementation/GameServer.cpp @@ -10,6 +10,8 @@ #include "..\GameLobby.h" #include "..\GameSession.h" +#include "..\GameProtocols\GeneralProtocols.h" + #include #include @@ -18,6 +20,9 @@ #include #include +//For conversion from wstring to string +#include + using namespace DanBias; using namespace Oyster::Network; using namespace Oyster::Thread; @@ -41,12 +46,26 @@ namespace } +std::string wstring_to_utf8 (const std::wstring& str) +{ + std::wstring_convert> myconv; + return myconv.to_bytes(str); +} DanBiasServerReturn GameServerAPI::ServerInitiate(const ServerInitDesc& desc) { ServerOptions opt; opt.mainOptions.listenPort = desc.listenPort; opt.mainOptions.ownerSession = &lobby; + + std::string serverName = wstring_to_utf8(desc.serverName); + + GameLogic::Protocol_Broadcast_Test broadcastMessage(opt.mainOptions.listenPort, "127.0.0.1", serverName); + + opt.broadcastOptions.broadcast = true; + opt.broadcastOptions.broadcastInterval = 1.0f; + opt.broadcastOptions.broadcastMessage = broadcastMessage.GetProtocol(); + if(server.Init(opt) == NetworkServer::ServerReturnCode_Error) { return DanBiasServerReturn_Error; @@ -54,7 +73,10 @@ DanBiasServerReturn GameServerAPI::ServerInitiate(const ServerInitDesc& desc) GameSession::GameDescription d; std::printf("Server created!\t-\t%s: [%i]\n\n", server.GetLanAddress().c_str(), desc.listenPort); - + + GameLogic::Protocol_Broadcast_Test broadcastMessage2(opt.mainOptions.listenPort, server.GetLanAddress(), serverName); + server.SetBroadcastMessage(broadcastMessage2.GetProtocol()); + return DanBiasServerReturn_Sucess; } void GameServerAPI::ServerStart() diff --git a/Code/Misc/Utilities/Thread/OysterThread_Impl.cpp b/Code/Misc/Utilities/Thread/OysterThread_Impl.cpp index 91430eab..e2809c4f 100644 --- a/Code/Misc/Utilities/Thread/OysterThread_Impl.cpp +++ b/Code/Misc/Utilities/Thread/OysterThread_Impl.cpp @@ -193,8 +193,11 @@ using namespace Utility::DynamicMemory; if(w->msec > 0) std::this_thread::sleep_for(std::chrono::milliseconds(w->msec)); - while (w->state == OYSTER_THREAD_STATE_IDLE) + while (w->state == OYSTER_THREAD_STATE_IDLE) + { + CheckPriority(w); std::this_thread::yield(); + } } static void ThreadingFunction(ThreadData* w) { diff --git a/Code/Network/NetworkAPI/NetworkClient.cpp b/Code/Network/NetworkAPI/NetworkClient.cpp index 56425109..57155ef7 100644 --- a/Code/Network/NetworkAPI/NetworkClient.cpp +++ b/Code/Network/NetworkAPI/NetworkClient.cpp @@ -13,6 +13,7 @@ #include "CustomNetProtocol.h" #include "NetworkSession.h" +#include "../NetworkDependencies/ConnectionUDP.h" #include "../NetworkDependencies/Connection.h" #include "../NetworkDependencies/PostBox.h" #include "../NetworkDependencies/WinsockFunctions.h" @@ -25,6 +26,8 @@ #include #include +#include + //For conversion from wstring to string #include @@ -60,6 +63,15 @@ struct NetworkClient::PrivateData : public IThreadObject HANDLE socketEvents[2]; HANDLE shutdownEvent; + //Broadcasting + bool broadcastingStarted; + HANDLE broadcastEvent; + HANDLE broadcastShutdownEvent; + std::thread broadcastThread; + ConnectionUDP broadcastConnection; + OysterByte broadcastTempMessage; + Translator broadcastTranslator; + //The OysterByte each message is packed in. OysterByte tempMessage; @@ -77,6 +89,7 @@ struct NetworkClient::PrivateData : public IThreadObject , owner(0) , outputEvent(0) { + broadcastingStarted = false; numPackages = 0; bufferedSend.Resize(MAX_NETWORK_MESSAGE_SIZE); tempMessage.Resize(MAX_NETWORK_MESSAGE_SIZE); @@ -120,6 +133,26 @@ struct NetworkClient::PrivateData : public IThreadObject CloseHandle(shutdownEvent); } + //Thread for receiving broadcast messages + void BroadcastThread() + { + WSANETWORKEVENTS wsaEvents; + + while(WaitForSingleObject(broadcastShutdownEvent, 0) != WAIT_OBJECT_0) + { + int result = WSAWaitForMultipleEvents(1, &broadcastEvent, FALSE, 100, FALSE) - WSA_WAIT_EVENT_0; + if(result == 0) + { + WSAEnumNetworkEvents(this->broadcastConnection.GetSocket(), broadcastEvent, &wsaEvents); + if((wsaEvents.lNetworkEvents & FD_READ) && (wsaEvents.iErrorCode[FD_READ_BIT] == 0)) + { + //Recieve a message + RecvUDP(); + } + } + } + } + bool DoWork() override { WSANETWORKEVENTS wsaEvents; @@ -128,7 +161,7 @@ struct NetworkClient::PrivateData : public IThreadObject { if(!this->connection.IsConnected()) return false; - int result = WSAWaitForMultipleEvents(2, socketEvents, FALSE, 100, FALSE) - WSA_WAIT_EVENT_0; + int result = WSAWaitForMultipleEvents(3, socketEvents, FALSE, 100, FALSE) - WSA_WAIT_EVENT_0; if(result == 0) { WSAEnumNetworkEvents(this->connection.GetSocket(), socketEvents[0], &wsaEvents); @@ -161,6 +194,47 @@ struct NetworkClient::PrivateData : public IThreadObject return false; } + void RecvUDP() + { + int errorCode = -1; + + errorCode = this->broadcastConnection.Recieve(broadcastTempMessage); + + if(errorCode == 0 && broadcastTempMessage.GetSize()) + { + CustomNetProtocol protocol; + bool ok = this->broadcastTranslator.Unpack(protocol, broadcastTempMessage); + + //Check if the protocol was unpacked correctly + if(ok) + { + CEA parg; + parg.type = CEA::EventType_ProtocolRecieved; + parg.data.protocol = protocol; + NetEvent e; + e.sender = this->parent; + e.args.data.protocol = parg.data.protocol; + e.args.type = parg.type; + + this->recieveQueue.Push(e); + + if(this->outputEvent) + { + printf("\t(ID: %i | IP: %s | Protocol: %i) Message recieved!\n", this->ID, this->connection.GetIpAddress().c_str(), protocol[0].value.netShort); + } + } + else + { + if(this->outputEvent) + { + printf("\t(ID: %i | IP: %s) Failed to unpack CustomNetProtocol!\n", this->ID, this->connection.GetIpAddress().c_str()); + } + } + + broadcastTempMessage.Clear(); + } + } + void SendBuffer() { if(bufferedSend.GetSize() > 0) @@ -482,7 +556,7 @@ bool NetworkClient::Connect(unsigned short port, const char serverIP[]) if(!this->privateData) this->privateData = new PrivateData(); - + int result = this->privateData->connection.Connect(port, serverIP, true); //Connect has succeeded @@ -598,4 +672,86 @@ std::string NetworkClient::GetIpAddress() void NetworkClient::OutputEventData(bool output) { this->privateData->outputEvent; -} \ No newline at end of file +} + +bool NetworkClient::StartListeningForBroadcasting(unsigned short port) +{ + //Create privateData if it doesn't exists. + if(this->privateData == NULL) + { + privateData = new PrivateData; + } + + //Initiate broadcasting only if it's not started. + if(!this->privateData->broadcastingStarted) + { + //Create UDP connection + int result = this->privateData->broadcastConnection.InitiateBroadcastClient(port); + if(result) + { + return false; + } + + //Create event for closing the thread. + this->privateData->broadcastShutdownEvent = CreateEvent(NULL, true, false, NULL); + if(this->privateData->broadcastShutdownEvent == NULL) + { + this->privateData->broadcastConnection.Disconnect(); + return false; + } + + //Creating event for broadcast messages on the UDP connection. + this->privateData->broadcastEvent = WSACreateEvent(); + if(this->privateData->broadcastEvent == WSA_INVALID_EVENT) + { + this->privateData->broadcastConnection.Disconnect(); + CloseHandle(this->privateData->broadcastShutdownEvent); + return false; + } + + //Set the event for only Receiving. + if(WSAEventSelect(this->privateData->broadcastConnection.GetSocket(), this->privateData->broadcastEvent, FD_READ) == SOCKET_ERROR) + { + this->privateData->broadcastConnection.Disconnect(); + CloseHandle(this->privateData->broadcastShutdownEvent); + WSACloseEvent(this->privateData->broadcastEvent); + return false; + } + + //Start thread receiving broadcast messages. + this->privateData->broadcastThread = thread(&PrivateData::BroadcastThread, this->privateData); + if(!this->privateData->broadcastThread.joinable()) + { + this->privateData->broadcastConnection.Disconnect(); + CloseHandle(this->privateData->broadcastShutdownEvent); + WSACloseEvent(this->privateData->broadcastEvent); + return false; + } + + this->privateData->broadcastingStarted = true; + } + + return true; +} + +void NetworkClient::StopListeningForBroadcasting() +{ + if(this->privateData) + { + if(this->privateData->broadcastingStarted) + { + //Tell the thread to shutdown + WSASetEvent(this->privateData->broadcastShutdownEvent); + + //Wait for thread + this->privateData->broadcastThread.join(); + + WSACloseEvent(this->privateData->broadcastEvent); + CloseHandle(this->privateData->broadcastShutdownEvent); + + this->privateData->broadcastConnection.Disconnect(); + + this->privateData->broadcastingStarted = false; + } + } +} diff --git a/Code/Network/NetworkAPI/NetworkClient.h b/Code/Network/NetworkAPI/NetworkClient.h index dddef221..9a3a367f 100644 --- a/Code/Network/NetworkAPI/NetworkClient.h +++ b/Code/Network/NetworkAPI/NetworkClient.h @@ -153,6 +153,19 @@ namespace Oyster */ void SetOutputEventDataStream(FILE out); + + /** Starts a seperate thread for listening to broadcast messages. + * @param port: The port to listen for messages on. + * @return Returns true if broadcasting is already started or if it started now. + Returns false if it failed to start broadcasting. + */ + bool StartListeningForBroadcasting(unsigned short port); + + /** Stops the seperate thread for broadcast messages. + * + */ + void StopListeningForBroadcasting(); + private: NetworkClient(const NetworkClient& obj); NetworkClient& operator =(const NetworkClient& obj); diff --git a/Code/Network/NetworkAPI/NetworkServer.cpp b/Code/Network/NetworkAPI/NetworkServer.cpp index 7d1cbdc5..a761c207 100644 --- a/Code/Network/NetworkAPI/NetworkServer.cpp +++ b/Code/Network/NetworkAPI/NetworkServer.cpp @@ -10,6 +10,8 @@ #include "NetworkServer.h" +#include "Translator.h" +#include "../NetworkDependencies/ConnectionUDP.h" #include "../NetworkDependencies/Listener.h" #include "../NetworkDependencies/PostBox.h" #include "../NetworkDependencies/WinsockFunctions.h" @@ -18,6 +20,7 @@ #include "Thread/OysterThread.h" #include "WinTimer.h" +#include using namespace Oyster::Network; using namespace Utility::DynamicMemory; @@ -81,7 +84,15 @@ public: , port(-1) , broadcast(0) , broadcastTime(1.0f, 0.0f) - { } + , broadcastMutex(new std::mutex) + { + InitWinSock(); + serverOptions.broadcastOptions.broadcastInterval = 1.0f; + serverOptions.broadcastOptions.broadcast = true; + broadcastMessage.Resize(MAX_NETWORK_MESSAGE_SIZE); + + broadcastConnection.InitiateBroadcastServer(15151, "255.255.255.255"); + } ~PrivateData() { if(listener) @@ -106,6 +117,12 @@ public: int port; bool broadcast; + ServerOptions serverOptions; + + SmartPointer broadcastMutex; + ConnectionUDP broadcastConnection; + OysterByte broadcastMessage; + TimeInstance broadcastTime; Utility::WinTimer serverTimer; @@ -113,11 +130,18 @@ public: bool NetworkServer::PrivateData::DoWork() { - if(broadcast) + if(serverOptions.broadcastOptions.broadcast) { - if( (this->serverTimer.getElapsedSeconds() - this->broadcastTime.previous) >= this->broadcastTime.length ) + if( (this->serverTimer.getElapsedSeconds() - this->broadcastTime.previous) >= this->serverOptions.broadcastOptions.broadcastInterval ) { - Broadcast(); + //broadcastMessage.Clear(); + //Translator t; + //t.Pack(broadcastMessage, serverOptions.broadcastOptions.broadcastMessage); + serverTimer.reset(); + + broadcastMutex->lock(); + broadcastConnection.Send(broadcastMessage); + broadcastMutex->unlock(); } } @@ -197,6 +221,8 @@ NetworkServer::ServerReturnCode NetworkServer::Init(ServerOptions& options) return NetworkServer::ServerReturnCode_Error; } + this->privateData->serverOptions.broadcastOptions = options.broadcastOptions; + this->privateData->isInitiated = true; this->privateData->isReleased = false; return NetworkServer::ServerReturnCode_Sucess; @@ -319,6 +345,47 @@ int NetworkServer::GetPort() return this->privateData->port; } +/*************************************** + Broadcast functions +***************************************/ +//Set broadcast settings. +void NetworkServer::SetBroadcast(CustomNetProtocol& broadcastMessage, float interval, bool enable) +{ + this->privateData->broadcastMutex->lock(); + this->privateData->serverOptions.broadcastOptions.broadcast = enable; + this->privateData->serverOptions.broadcastOptions.broadcastMessage = broadcastMessage; + this->privateData->serverOptions.broadcastOptions.broadcastInterval = interval; + this->privateData->broadcastMessage.Clear(); + Translator t; + t.Pack(this->privateData->broadcastMessage, broadcastMessage); + this->privateData->broadcastMutex->unlock(); +} +//Set broadcast settings. +void NetworkServer::SetBroadcastMessage(CustomNetProtocol& broadcastMessage) +{ + this->privateData->broadcastMutex->lock(); + this->privateData->serverOptions.broadcastOptions.broadcastMessage = broadcastMessage; + this->privateData->broadcastMessage.Clear(); + Translator t; + t.Pack(this->privateData->broadcastMessage, broadcastMessage); + this->privateData->broadcastMutex->unlock(); +} + +//Enable/disable broadcast. +void NetworkServer::SetBroadcast(bool enable) +{ + this->privateData->broadcastMutex->lock(); + this->privateData->serverOptions.broadcastOptions.broadcast = enable; + this->privateData->broadcastMutex->unlock(); +} + +//Set interval between each broadcast message in seconds. +void NetworkServer::SetBroadcastInterval(float interval) +{ + this->privateData->broadcastMutex->lock(); + this->privateData->serverOptions.broadcastOptions.broadcastInterval = interval; + this->privateData->broadcastMutex->unlock(); +} \ No newline at end of file diff --git a/Code/Network/NetworkDependencies/ConnectionUDP.cpp b/Code/Network/NetworkDependencies/ConnectionUDP.cpp index 44a49d2d..2c0e5b25 100644 --- a/Code/Network/NetworkDependencies/ConnectionUDP.cpp +++ b/Code/Network/NetworkDependencies/ConnectionUDP.cpp @@ -41,8 +41,24 @@ int ConnectionUDP::Connect(unsigned short port, const char serverName[]) } + //this->Address = htonl(0xffffffff); this->Address = *(unsigned long*)hostEnt->h_addr; this->port = htons(this->port); + + if(this->Address == 0) + { + sockaddr_in addr; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_family = AF_INET; + addr.sin_port = this->port; + + int result = bind(socket, (const sockaddr*)&addr, sizeof(addr)); + if(result) + { + int a = 0; + } + } + return 0; } @@ -89,19 +105,46 @@ int ConnectionUDP::InitiateClient() return InitiateSocket(); } -int ConnectionUDP::InitiateBroadcast(unsigned short port) +int ConnectionUDP::InitiateBroadcastServer(unsigned short port, const char serverName[]) { int result = InitiateSocket(); - int flag = 1; - result = setsockopt(this->socket, /* socket affected */ - SOL_SOCKET, /* set option at TCP level */ - SO_BROADCAST, /* name of option */ - (char *) &flag, /* the cast is historical cruft */ - sizeof(flag)); /* length of option value */ + result = setsockopt(this->socket, SOL_SOCKET, SO_BROADCAST, (char *) &flag, sizeof(flag)); if (result < 0) return -1; + + closed = false; + stillSending = true; + + struct hostent *hostEnt; + if((hostEnt = gethostbyname(serverName)) == NULL) + { + return SOCKET_ERROR; + } + + this->Address = *(unsigned long*)hostEnt->h_addr; + this->port = htons(port); + + return 0; +} + +int ConnectionUDP::InitiateBroadcastClient(unsigned short port) +{ + int result = InitiateSocket(); + + struct sockaddr_in recvAddr; + recvAddr.sin_family = AF_INET; + recvAddr.sin_addr.s_addr = INADDR_ANY; + recvAddr.sin_port = htons(port); + + if(bind(this->socket, (sockaddr*)&recvAddr, sizeof(recvAddr)) == SOCKET_ERROR) + { + closesocket(this->socket); + return SOCKET_ERROR; + } + + return result; } int ConnectionUDP::Send(OysterByte &bytes) @@ -201,6 +244,12 @@ int ConnectionUDP::SetBlockingMode( bool blocking ) //Success return 0; } + +int ConnectionUDP::GetSocket() +{ + return socket; +} + ////////////////////////////////////// // Private Methods ////////////////////////////////////// diff --git a/Code/Network/NetworkDependencies/ConnectionUDP.h b/Code/Network/NetworkDependencies/ConnectionUDP.h index 163ad741..83a48482 100644 --- a/Code/Network/NetworkDependencies/ConnectionUDP.h +++ b/Code/Network/NetworkDependencies/ConnectionUDP.h @@ -22,18 +22,23 @@ namespace Oyster virtual int InitiateServer( unsigned short port ); virtual int InitiateClient(); - virtual int InitiateBroadcast(unsigned short port); + virtual int InitiateBroadcastServer(unsigned short port, const char serverName[]); + virtual int InitiateBroadcastClient(unsigned short port); virtual int Send ( OysterByte &byte ); virtual int Recieve( OysterByte &byte ); virtual int Connect( unsigned short port, const char serverName[] ); + //Doesn't do anything now. + virtual int Reconnect() { return 0; } + virtual int Disconnect(); bool IsSending(); bool IsConnected(); int GetIpSize(); + int GetSocket(); int SetBlockingMode( bool blocking );