diff --git a/slsSupportLib/src/DataSocket.cpp b/slsSupportLib/src/DataSocket.cpp index 71205a71a..a38fe602d 100755 --- a/slsSupportLib/src/DataSocket.cpp +++ b/slsSupportLib/src/DataSocket.cpp @@ -3,13 +3,15 @@ #include "sls_detector_exceptions.h" #include #include +#include #include +#include #include #include +#include #include #include #include -#include namespace sls { @@ -41,27 +43,54 @@ DataSocket &DataSocket::operator=(DataSocket &&move) noexcept { } int DataSocket::receiveData(void *buffer, size_t size) { - //TODO!(Erik) Add sleep? how many reties? - int dataRead = 0; - while (dataRead < size) { - auto thisRead = - ::read(getSocketId(), reinterpret_cast(buffer) + dataRead, - size - dataRead); - if (thisRead <= 0) + // TODO!(Erik) Add sleep? how many reties? + assert(size > 0); + int bytes_expected = static_cast(size); // signed size + int bytes_read = 0; + while (bytes_read < bytes_expected) { + auto this_read = + ::read(getSocketId(), reinterpret_cast(buffer) + bytes_read, + bytes_expected - bytes_read); + if (this_read <= 0) break; - dataRead += thisRead; + bytes_read += this_read; + } + if (bytes_read == bytes_expected) { + return bytes_read; + } else { + std::ostringstream ss; + ss << "TCP socket error read " << bytes_read << " bytes instead of " + << bytes_expected << " bytes"; + throw sls::SocketError(ss.str()); } - return dataRead; } -int DataSocket::read(void *buffer, size_t size){ - return ::read(getSocketId(), buffer, size); +int DataSocket::sendData(const void *buffer, size_t size) { + int bytes_sent = 0; + int data_size = static_cast(size); // signed size + while (bytes_sent < (data_size)) { + auto this_send = ::write(getSocketId(), buffer, size); + if (this_send <= 0) + break; + bytes_sent += this_send; + } + if (bytes_sent != data_size){ + std::ostringstream ss; + ss << "TCP socket error sent " << bytes_sent << " bytes instead of " + << data_size << " bytes"; + throw sls::SocketError(ss.str()); + } + return bytes_sent; } -int DataSocket::write(void *buffer, size_t size){ +int DataSocket::write(void *buffer, size_t size) { return ::write(getSocketId(), buffer, size); } +int DataSocket::read(void *buffer, size_t size) { + return ::read(getSocketId(), buffer, size); +} + int DataSocket::setReceiveTimeout(int us) { timeval t{}; t.tv_sec = 0; @@ -70,20 +99,6 @@ int DataSocket::setReceiveTimeout(int us) { sizeof(struct timeval)); } - -int DataSocket::sendData(const void *buffer, size_t size) { - int dataSent = 0; - while (dataSent < (int)size) { - auto thisSend = ::write(getSocketId(), buffer, size); - if (thisSend <= 0) - break; - dataSent += thisSend; - } - if(dataSent != size) - throw SocketError("Could not send\n"); - return dataSent; -} - int DataSocket::setTimeOut(int t_seconds) { if (t_seconds <= 0) return -1; diff --git a/tests/include/tests/testenum.h b/tests/include/tests/testenum.h index 34e56ea4b..cd484b921 100644 --- a/tests/include/tests/testenum.h +++ b/tests/include/tests/testenum.h @@ -1,5 +1,5 @@ #pragma once #include -enum class func_id{read_data, read_int}; +enum class func_id{read_data, read_int, read_half_data}; constexpr size_t MB = 1048576; constexpr size_t DATA_SIZE = 50*MB; \ No newline at end of file diff --git a/tests/src/testclient.cpp b/tests/src/testclient.cpp index 3af6bf6cc..771a0ec81 100644 --- a/tests/src/testclient.cpp +++ b/tests/src/testclient.cpp @@ -1,18 +1,20 @@ #include "ClientSocket.h" +#include "sls_detector_exceptions.h" #include "clara.hpp" #include "tests/testenum.h" -#include #include "container_utils.h" +#include +bool help = false; - -int main(int argc, char** argv) { +int main(int argc, char **argv) { std::cout << "Test client\n"; std::string hostname{"localhost"}; int port = 2345; auto cli = - clara::Opt(hostname, "hostname")["-hn"]["--hostname"]("Hostname") | + clara::Help(help) | + clara::Opt(hostname, "hostname")["-n"]["--hostname"]("Hostname") | clara::Opt(port, "port")["-p"]["--port"]("Port to send to"); auto result = cli.parse(clara::Args(argc, argv)); @@ -21,25 +23,58 @@ int main(int argc, char** argv) { << std::endl; exit(1); } + if (help) { + std::cout << cli << std::endl; + return 0; + } + std::cout << "Sending to: " << hostname << ":" << port << "\n"; - - + auto data = sls::make_unique(DATA_SIZE); - for (int64_t i = 0; i!=50; ++i){ + // Many connections sending small amounts + for (int i = 0; i != 100; ++i) { std::cout << "Sending: " << i << "\n"; auto socket = sls::ClientSocket("test", hostname, port); - std::cout << "Sent: " << socket.sendData(func_id::read_int) << " bytes\n"; + std::cout << "Sent: " << socket.sendData(func_id::read_int) + << " bytes\n"; std::cout << "Sent: " << socket.sendData(i) << " bytes\n"; } - for (int64_t i = 0; i!=5; ++i){ + // Sending larger blocks + for (int i = 0; i != 5; ++i) { std::cout << "Sending data\n"; auto socket = sls::ClientSocket("test", hostname, port); - std::cout << "Sent: " << socket.sendData(func_id::read_data) << " bytes\n"; - std::cout << "Sent: " << socket.sendData(data.get(), DATA_SIZE) << " bytes\n"; + std::cout << "Sent: " << socket.sendData(func_id::read_data) + << " bytes\n"; + std::cout << "Sent: " << socket.sendData(data.get(), DATA_SIZE) + << " bytes\n"; } - + // Send too little data + { + auto socket = sls::ClientSocket("test", hostname, port); + std::cout << "Sent: " << socket.sendData(func_id::read_data) + << " bytes\n"; + std::cout << "Sent: " << socket.sendData(data.get(), DATA_SIZE / 2) + << " bytes\n"; + } + // Send too much data + try{ + auto socket = sls::ClientSocket("test", hostname, port); + std::cout << "Sent: " << socket.sendData(func_id::read_half_data) + << " bytes\n"; + std::cout << "Sent: " << socket.sendData(data.get(), DATA_SIZE) + << " bytes\n"; + }catch(const sls::SocketError& e){ + } + // Some ints again + for (int i = 0; i != 10; ++i) { + std::cout << "Sending: " << i << "\n"; + auto socket = sls::ClientSocket("test", hostname, port); + std::cout << "Sent: " << socket.sendData(func_id::read_int) + << " bytes\n"; + std::cout << "Sent: " << socket.sendData(i) << " bytes\n"; + } } diff --git a/tests/src/testserver.cpp b/tests/src/testserver.cpp index c30c6846b..ed7f10247 100644 --- a/tests/src/testserver.cpp +++ b/tests/src/testserver.cpp @@ -3,44 +3,54 @@ #include "tests/testenum.h" +#include "ServerInterface2.h" #include "container_utils.h" #include #include -#include "ServerInterface2.h" -struct EnumClassHash -{ - template - std::size_t operator()(T t) const - { +// For hashing of enum with C++11, not needed in 14 +struct EnumClassHash { + template std::size_t operator()(T t) const { return static_cast(t); } }; using Interface = sls::ServerInterface2; -using func_ptr = int (*)(Interface &); +using func_ptr = void (*)(Interface &); -int read_data(Interface &socket) { +/******************************************** + * Mapped functions * + ********************************************/ + +void read_data(Interface &socket) { auto data = sls::make_unique(DATA_SIZE); std::cout << "Read: " << socket.receiveData(data.get(), DATA_SIZE) << " bytes into buffer\n"; - return 0; } -int read_int(Interface &socket) { +void read_half_data(Interface &socket) { + auto data = sls::make_unique(DATA_SIZE); + std::cout << "Read: " << socket.receiveData(data.get(), DATA_SIZE / 2) + << " bytes into buffer\n"; +} + +void read_int(Interface &socket) { auto i = socket.receive(); std::cout << "Read : " << i << "\n"; - return 0; } -static std::unordered_map fmap{ - {func_id::read_data, &read_data}, {func_id::read_int, &read_int}}; +// Map from int to function pointer, in this case probably a map would be faster +std::unordered_map fmap{ + {func_id::read_data, &read_data}, + {func_id::read_int, &read_int}, + {func_id::read_half_data, &read_half_data}}; int main(int argc, char **argv) { - std::cout << "Test server\n"; + std::cout << "Starting test server...\n"; int port = 2345; - auto cli = clara::Opt(port, "port")["-p"]["--port"]("Port to send to"); + // Parse command line arguments using clara + auto cli = clara::Opt(port, "port")["-p"]["--port"]("Port to send to"); auto result = cli.parse(clara::Args(argc, argv)); if (!result) { std::cerr << "Error in command line: " << result.errorMessage() @@ -48,17 +58,17 @@ int main(int argc, char **argv) { exit(1); } std::cout << "Listening to port: " << port << "\n"; - auto server = sls::ServerSocket(port); + auto server = sls::ServerSocket(port); while (true) { try { auto socket = server.accept(); auto fnum = socket.receive(); std::cout << "Calling func: " << (int)fnum << "\n"; - auto ret = (*fmap[fnum])(socket); - // std::cout << "function returned: " << ret << "\n"; + (*fmap[fnum])(socket); // call mapped function } catch (const sls::RuntimeError &e) { + // Do nothing, error is printed when the exeption is created } } }