Skip to content

Instantly share code, notes, and snippets.

@vittorioromeo
Created July 17, 2013 16:29
Show Gist options
  • Save vittorioromeo/6022172 to your computer and use it in GitHub Desktop.
Save vittorioromeo/6022172 to your computer and use it in GitHub Desktop.
temp server/client
#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; }
#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
#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