Commit 63a7a3b6 authored by Andreas Kempe's avatar Andreas Kempe

Added basic networking. Packet sending/receiving/decoding.

parent c5cc8057
# Generated by YCM Generator at 2015-10-02 17:50:02.654563
# Generated by YCM Generator at 2015-10-02 21:46:33.349867
# This file is NOT licensed under the GPLv3, which is the license for the rest
# of YouCompleteMe.
......@@ -43,19 +43,25 @@ flags = [
'-DQT_NETWORK_LIB',
'-DQT_NO_DEBUG',
'-DQT_WIDGETS_LIB',
'-Dmandelnet_EXPORTS',
'-I/home/andkem/Dokument/Programmering/mpi-mandelbrot',
'-I/home/andkem/Dokument/Programmering/mpi-mandelbrot/network',
'-I/home/andkem/Program/imagemagick/include/ImageMagick-6',
'-I/home/kempe/Documents/Programmering/mpi-mandelbrot',
'-I/home/kempe/lib/include',
'-I/home/andkem/Program/openmpi/include',
'-I/home/kempe/lib/include/ImageMagick-6',
'-I/tmp/tmps_s0z8',
'-I/tmp/tmpljiixJ',
'-I/usr/include/qt5',
'-I/usr/include/qt5/QtCore',
'-I/usr/include/qt5/QtGui',
'-I/usr/include/qt5/QtNetwork',
'-I/usr/include/qt5/QtWidgets',
'-I/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++-64',
'-I/usr/lib64/qt5/mkspecs/linux-g++',
'-std=c++11',
'-I/home/kempe/Documents/Programmering/mpi-mandelbrot/network',
'-isystem', '/usr/include/qt5',
'-isystem', '/usr/include/qt5/QtCore',
'-isystem', '/usr/include/qt5/QtGui',
'-isystem', '/usr/include/qt5/QtNetwork',
'-isystem', '/usr/include/qt5/QtWidgets',
'-isystem', '/usr/lib64/qt5/mkspecs/linux-g++',
]
......
......@@ -10,9 +10,10 @@ find_package(Qt5Gui)
find_package(Qt5Network)
# Source files
set(SERVER_SRC server/main.cpp server/mandelbrot.cpp server/server_socket.cpp)
set(SERVER_SRC server/main.cpp server/mandelbrot.cpp)
set(CLIENT_SRC client/main.cpp client/main_window.cpp)
set(MANDELNET_SRC network/data_packet.cpp)
set(MANDELNET_SRC network/data_packet.cpp network/mandel_socket.cpp
network/mandel_tcp_server.cpp)
include_directories(/home/andkem/Program/imagemagick/include/ImageMagick-6
/home/kempe/lib/include/ImageMagick-6
......@@ -25,7 +26,7 @@ include_directories(/home/andkem/Program/imagemagick/include/ImageMagick-6
# Executables
add_executable(mpi-mandel-srv ${SERVER_SRC})
add_executable(mandel-clt ${CLIENT_SRC})
add_library(mandelnet ${MANDELNET_SRC})
add_library(mandelnet SHARED ${MANDELNET_SRC})
find_library(Magick Magick++-6.Q16
......@@ -35,8 +36,9 @@ find_library(Magick Magick++-6.Q16
# Set the MPI compilers
set(CMAKE_C_COMPILER mpicc)
set(CMAKE_CXX_COMPILER mpicxx)
set(CMAKE_CXX_FLAGS "-DMAGICKCORE_HDRI_ENABLE=0 -DMAGICKCORE_QUANTUM_DEPTH=16 -O3 -std=c++11 -fPIC")
set(CMAKE_CXX_FLAGS "-DMAGICKCORE_HDRI_ENABLE=0 -DMAGICKCORE_QUANTUM_DEPTH=16 -std=c++11 -fPIC")
# Libraries
target_link_libraries(mpi-mandel-srv mpi ${Magick} Qt5::Network mandelnet)
target_link_libraries(mandel-clt Qt5::Widgets Qt5::Gui Qt5::Network)
target_link_libraries(mpi-mandel-srv mpi ${Magick} mandelnet)
target_link_libraries(mandel-clt Qt5::Widgets Qt5::Gui ${Magick} mandelnet)
target_link_libraries(mandelnet Qt5::Network)
#include "main_window.h"
#include <QPixmap>
#include <QPushButton>
#include <QDebug>
#include <Magick++.h>
#include <string>
main_window::main_window(unsigned int port, QWidget* parent) :
port(port), QWidget(parent)
......@@ -21,7 +24,7 @@ main_window::main_window(unsigned int port, QWidget* parent) :
QPushButton* img_btn = new QPushButton("Show image", this);
connect(img_btn, &QPushButton::clicked, this, &main_window::show_image);
server = new QTcpServer(this);
server = new mandel_tcp_server(this);
connect(server, &QTcpServer::newConnection, this, &main_window::handle_new_connection);
server->listen(QHostAddress::Any, port);
}
......@@ -41,8 +44,8 @@ void main_window::handle_new_connection()
{
socket = server->nextPendingConnection();
connect(socket, &QTcpSocket::disconnected, this, &main_window::handle_socket_close);
connect(socket, &QTcpSocket::readyRead, this, &main_window::handle_recv_data);
connect(socket, &mandel_socket::disconnected, this, &main_window::handle_socket_close);
connect(socket, &mandel_socket::packet_ready, this, &main_window::handle_recv_data);
// Close the server since we only want one connection at a time.
server->close();
......@@ -57,4 +60,29 @@ void main_window::handle_socket_close()
void main_window::handle_recv_data()
{
data_packet* packet = socket->get_next_packet();
//TODO: Handle packet!
qDebug() << "Received a packet!";
switch (packet->get_op_code())
{
case op_codes::IMG_DATA:
{
qDebug() << "Received a data packet with op code IMG_DATA and a payload of size "
<< packet->get_payload_size() << " byte(s).";
Magick::Image recv_img;
std::string enc_img(packet->get_payload());
Magick::Blob blob;
blob.base64(enc_img);
recv_img.read(blob);
recv_img.write("output.png");
qDebug() << "Saved the image as \"output.png\"!";
}
}
delete packet;
}
......@@ -5,8 +5,8 @@
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsPixmapItem>
#include <QTcpServer>
#include <QTcpSocket>
#include "mandel_tcp_server.h"
#include "mandel_socket.h"
class main_window : public QWidget
{
......@@ -22,8 +22,8 @@ class main_window : public QWidget
QGraphicsView* view;
QGraphicsPixmapItem* item;
QTcpServer* server;
QTcpSocket* socket;
mandel_tcp_server* server;
mandel_socket* socket;
const unsigned int port;
......
#include "data_packet.h"
data_packet::data_packet(op_codes op_code, size_t payload_size, char* payload) :
data_packet::data_packet(op_codes op_code, uint payload_size, char* payload) :
op_code(static_cast<quint32>(op_code)), payload_size(payload_size), payload(payload)
{
}
data_packet::data_packet(quint32 op_code, uint payload_size, char* payload) :
op_code(op_code), payload_size(payload_size), payload(payload)
{
}
data_packet::~data_packet()
{
delete payload;
payload = nullptr;
}
op_codes data_packet::get_op_code()
{
return static_cast<op_codes>(op_code);
}
uint data_packet::get_payload_size()
{
return payload_size;
}
const char* data_packet::get_payload()
{
return payload;
}
QDataStream& operator<<(QDataStream& stream, const data_packet& packet)
{
stream << packet.op_code;
stream << packet.payload_size;
stream.writeRawData(packet.payload, packet.payload_size);
return stream;
......
#ifndef DATA_PACKET_H
#define DATA_PACKET_H
#include "network_defines.h"
#include <QDataStream>
enum class op_codes : quint32
{
TEST = 0x00000000
};
static unsigned short packet_header_size = 8;
class data_packet
{
......@@ -14,12 +12,17 @@ class data_packet
public:
// The user is responsible for allocating memory for payload.
// data_packet will then call delete on it in its constructor.
data_packet(op_codes op_code, size_t payload_size, char* payload);
data_packet(op_codes op_code, uint payload_size, char* payload);
data_packet(quint32 op_code, uint payload_size, char* payload);
~data_packet();
op_codes get_op_code();
uint get_payload_size();
const char* get_payload();
private:
quint32 op_code;
size_t payload_size;
uint payload_size;
char* payload;
};
......
#include "mandel_socket.h"
#include "data_packet.h"
#include <QDebug>
#include <QDataStream>
#include <QByteArray>
using namespace std;
mandel_socket::mandel_socket(QString host, unsigned int port, QObject* parent) :
QTcpSocket(parent)
{
setup_slot_connection();
connectToHost(host, port, QIODevice::ReadWrite, QAbstractSocket::AnyIPProtocol);
}
mandel_socket::mandel_socket(QObject* parent) : QTcpSocket(parent)
{
setup_slot_connection();
}
mandel_socket::~mandel_socket()
{
while (!packet_queue.empty())
{
delete packet_queue.front();
packet_queue.pop();
}
}
void mandel_socket::send_data_packet(const data_packet& packet)
{
QByteArray buf;
QDataStream stream(&buf, QIODevice::ReadWrite);
stream << packet;
write(buf);
flush();
}
data_packet* mandel_socket::get_next_packet()
{
if (packet_queue.empty())
return nullptr;
data_packet* tmp = packet_queue.front();
packet_queue.pop();
return tmp;
}
void mandel_socket::setup_slot_connection()
{
connect(this, &mandel_socket::readyRead, this, &mandel_socket::handle_recv_data);
}
void mandel_socket::decode_packet_data(QByteArray& incoming)
{
quint32 op_code = 0;
uint payload_size = 0;
recv_buf.append(incoming);
if (recv_buf.size() >= packet_header_size)
{
QDataStream reader(&recv_buf, QIODevice::ReadOnly);
reader >> op_code >> payload_size;
if (recv_buf.size() < payload_size + packet_header_size)
return;
char* payload = nullptr;
if (payload_size > 0)
{
payload = new char[payload_size + 1];
payload[payload_size] = '\0';
reader.readRawData(payload, payload_size);
}
data_packet* reassembled = new data_packet(op_code, payload_size, payload);
packet_queue.push(reassembled);
emit(packet_ready());
// Remove the read data from the buffer.
recv_buf.remove(0, payload_size + packet_header_size);
// If we still have data in the buffer we call ourselves to handle it.
if (recv_buf.size() > 0)
decode_packet_data(recv_buf);
}
}
void mandel_socket::handle_recv_data()
{
QByteArray incoming;
incoming = readAll();
decode_packet_data(incoming);
}
#ifndef MANDEL_SOCKET_H
#define MANDEL_SOCKET_H
#include "data_packet.h"
#include <QTcpSocket>
#include <queue>
class mandel_socket : public QTcpSocket
{
Q_OBJECT
public:
mandel_socket(QObject* parent = nullptr);
mandel_socket(QString host, unsigned int port, QObject* parent);
~mandel_socket();
void send_data_packet(const data_packet& packet);
data_packet* get_next_packet();
private:
void setup_slot_connection();
QByteArray recv_buf;
std::queue<data_packet*> packet_queue;
void handle_op_code(const QByteArray& data);
void decode_packet_data(QByteArray& incoming);
private slots:
void handle_recv_data();
signals:
void packet_ready();
};
#endif
#include "mandel_tcp_server.h"
mandel_tcp_server::mandel_tcp_server(QObject* parent) :
QTcpServer(parent)
{
}
mandel_socket* mandel_tcp_server::nextPendingConnection()
{
mandel_socket* tmp;
if (socket_stack.empty())
return nullptr;
tmp = socket_stack.front();
socket_stack.pop();
return tmp;
}
void mandel_tcp_server::incomingConnection(qintptr socketDescriptor)
{
mandel_socket* socket = new mandel_socket(this);
socket->setSocketDescriptor(socketDescriptor);
socket_stack.push(socket);
}
#ifndef MANDEL_TCP_SERVER_H
#define MANDEL_TCP_SERVER_H
#include "mandel_socket.h"
#include <QTcpServer>
#include <queue>
class mandel_tcp_server : public QTcpServer
{
public:
mandel_tcp_server(QObject* parent);
mandel_socket* nextPendingConnection() override final;
void incomingConnection(qintptr socketDescriptor) override final;
private:
std::queue<mandel_socket*> socket_stack;
};
#endif
#ifndef NETWORK_DEFINES_H
#define NETWORK_DEFINES_H
#include <Qt>
#define PORT 8910
enum op_codes : quint32
{
IMG_DATA = 0x1
};
#endif
#include "mandelbrot.h"
#include "server_socket.h"
#include "mandel_socket.h"
#include "network_defines.h"
#include "data_packet.h"
#include <mpi.h>
......@@ -48,11 +48,22 @@ void root_process_handling(unsigned long *receive_buffer)
pixel_cache.sync();
cout << "Progress: 100 % " << endl;
stringstream ss;
ss << "output.png";
cout << "Sending image!" << endl;
mandel_socket socket("127.0.0.1", PORT, nullptr);
socket.waitForConnected(10000);
Blob image_data;
my_image.magick("PNG");
my_image.write(&image_data);
std::string enc_img = image_data.base64();
char* data = new char[enc_img.size() + 1];
memcpy(data, enc_img.c_str(), enc_img.size() + 1);
data_packet packet(op_codes::IMG_DATA, enc_img.size() + 1, data);
socket.send_data_packet(packet);
cout << "Saving image!" << endl;
my_image.write(ss.str());
}
......@@ -60,12 +71,8 @@ int main(int argc, char** argv)
{
int id;
int procs;
unsigned long *calculated_values;
unsigned long *receive_buffer = nullptr;
server_socket socket("127.0.0.1", PORT, nullptr);
data_packet(op_codes::TEST, 0, nullptr);
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &procs);
......@@ -97,7 +104,6 @@ int main(int argc, char** argv)
if (id == 0)
root_process_handling(receive_buffer);
delete[] calculated_values;
delete[] receive_buffer;
MPI_Finalize();
......
#include "server_socket.h"
#include <QDebug>
using namespace std;
server_socket::server_socket(QString host, unsigned int port, QObject* parent)
{
connect(this, &QTcpSocket::readyRead, this, &server_socket::handle_recv_data);
connectToHost(host, port, QIODevice::ReadWrite, QAbstractSocket::AnyIPProtocol);
}
void server_socket::handle_recv_data()
{
qDebug() << "Received data!";
}
#ifndef SERVER_SOCKET_H
#define SERVER_SOCKET_H
#include <QTcpSocket>
class server_socket : public QTcpSocket
{
Q_OBJECT
public:
server_socket(QString host, unsigned int port, QObject* parent);
private slots:
void handle_recv_data();
};
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment