Created
July 17, 2013 16:29
-
-
Save vittorioromeo/6022172 to your computer and use it in GitHub Desktop.
temp server/client
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <algorithm> | |
#include <string> | |
#include <thread> | |
#include <functional> | |
#include <future> | |
#include <SSVUtils/SSVUtils.h> | |
#include <SFML/Network.hpp> | |
#include "Common.h" | |
using namespace std; | |
using namespace ssvu; | |
using namespace sf; | |
Packet buildPingPacket() { Packet result; result << PacketType::Ping; return result; } | |
Packet buildHelloPacket() { Packet result; result << PacketType::Data << "hello bro!"; return result; } | |
class Client | |
{ | |
private: | |
TcpSocket socket; | |
bool busy{false}; | |
void trySendPacket(Packet mPacket) | |
{ | |
if(!busy) return; | |
if(asyncTry([&]{ return socket.send(mPacket) == Socket::Done; })) return; | |
log("Couldn't send packet to server - aborting and closing connection", "Client"); | |
busy = false; | |
} | |
void run() | |
{ | |
Uptr<thread>(new thread([&] | |
{ | |
while(busy) | |
{ | |
trySendPacket(buildHelloPacket()); | |
trySendPacket(buildPingPacket()); | |
this_thread::sleep_for(chrono::milliseconds(1000)); | |
} | |
}))->join(); | |
} | |
public: | |
void connect(IpAddress mIp, unsigned int mPort) | |
{ | |
if(busy) { log("Error: client is already connected", "Client"); return; } | |
if(!asyncTry([&]{ return socket.connect(mIp, mPort) == Socket::Done; })) return; | |
log("Connected to " + mIp.toString() + ":" + toStr(mPort), "Client"); | |
busy = true; run(); | |
} | |
void disconnect() { socket.disconnect(); } | |
}; | |
int main() { Client{}.connect("127.0.0.1", 53000); return 0; } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef SC_COMMON | |
#define SC_COMMON | |
#include <iostream> | |
#include <algorithm> | |
#include <string> | |
#include <thread> | |
#include <functional> | |
#include <future> | |
#include <SSVUtils/SSVUtils.h> | |
#include <SFML/Network.hpp> | |
#include "Common.h" | |
enum class LogMode { Default, Quiet }; | |
enum PacketType : unsigned int | |
{ | |
Ping = 0, | |
Data = 1 | |
}; | |
template<LogMode TLM = LogMode::Default> bool asyncTry(std::function<bool()> mFunc, const std::chrono::duration<int, std::milli>& mDuration = std::chrono::milliseconds(1500), int mTimes = 5) | |
{ | |
auto t(std::packaged_task<bool()>([&] | |
{ | |
for(int i{0}; i < mTimes; ++i) | |
{ | |
if(!mFunc()) | |
{ | |
if(TLM != LogMode::Quiet) ssvu::log("Error - retrying (" + ssvu::toStr(i + 1) + "/" + ssvu::toStr(mTimes) + ")", "asyncTry"); | |
std::this_thread::sleep_for(mDuration); continue; | |
} | |
return true; | |
} | |
return false; | |
})); | |
t(); | |
return t.get_future().get(); | |
} | |
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <algorithm> | |
#include <string> | |
#include <vector> | |
#include <chrono> | |
#include <thread> | |
#include <SSVUtils/SSVUtils.h> | |
#include <SFML/Network.hpp> | |
#include "Common.h" | |
using namespace std; | |
using namespace ssvu; | |
using namespace sf; | |
struct ClientHandler | |
{ | |
unsigned int uid; | |
static unsigned int lastUid; | |
TcpSocket socket; | |
bool busy{false}; | |
ClientHandler() : uid{lastUid} { socket.setBlocking(false); ++lastUid; } | |
void update() | |
{ | |
Packet packet; | |
if(asyncTry([&]{ return socket.receive(packet) == Socket::Done; })) | |
{ | |
unsigned int type; | |
string contents; | |
packet >> type >> contents; | |
log("Received packet", "ClientHandler(" + toStr(uid) + ")"); | |
log("Packet contents: '" + contents + "'", "ClientHandler(" + toStr(uid) + ")"); | |
} | |
else | |
{ | |
log("Lost connection to client (timed out)", "ClientHandler(" + toStr(uid) + ")"); | |
busy = false; return; | |
} | |
this_thread::sleep_for(chrono::milliseconds(100)); | |
} | |
void run() { while(busy) update(); } | |
}; | |
unsigned int ClientHandler::lastUid{0}; | |
class Server | |
{ | |
private: | |
unsigned int port{53000}; | |
TcpListener listener; | |
vector<Uptr<ClientHandler>> clientHandlers; | |
void grow() | |
{ | |
if(find_if(begin(clientHandlers), end(clientHandlers), [](const Uptr<ClientHandler>& mCH){ return !mCH->busy; }) != end(clientHandlers)) return; | |
log("Creating new client handlers", "Server"); | |
for(int i{0}; i < 10; ++i) clientHandlers.emplace_back(new ClientHandler); | |
} | |
void update() | |
{ | |
grow(); | |
for(auto& c : clientHandlers) | |
{ | |
if(c->busy) continue; | |
if(!asyncTry<LogMode::Quiet>([&]{ return listener.accept(c->socket) == Socket::Done; })) continue; | |
log("Accepted client (" + toStr(c->uid) + ")", "Server"); | |
c->busy = true; | |
Uptr<thread>(new thread([&]{ c->run(); }))->detach(); | |
} | |
this_thread::sleep_for(chrono::milliseconds(100)); | |
} | |
void run() | |
{ | |
Uptr<thread>(new thread([&]{ while(true) update(); }))->join(); | |
} | |
public: | |
Server() | |
{ | |
listener.setBlocking(false); | |
if(listener.listen(port) != Socket::Done) log("Error initializing listener", "Server"); | |
else log("Listener initialized", "Server"); | |
run(); | |
} | |
}; | |
int main() { Server s; return 0; } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment