Skip to Content

Verteilte Systeme

Socket-Wrapper

socket.hpp

#include <string> #include <cerrno> #include <cstring> #include <netinet/in.h> class Socket { private: sockaddr_in _address; int _sfd; public: Socket(std::string ip, int port); Socket(int socket); void send(std::string msg); std::string recv(void); void close(void); };

Socket.cpp

#include <iostream> #include "socket.hpp" #include <unistd.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> Socket::Socket(std::string ip, int port) { _sfd = ::socket(AF_INET, SOCK_STREAM, 0); if (_sfd == -1) throw SocketException(strerror(errno)); _address.sin_family = AF_INET; _address.sin_addr.s_addr = ::inet_addr(ip.c_str()); _address.sin_port = ::htons(port); int len = sizeof(_address); int flag = ::connect(_sfd, (struct sockaddr *)&_address, len); if (flag == -1) throw SocketException(strerror(errno)); Socket::Socket(int socket) : _sfd(socket) {} void Socket::send(std::string msg) { // Lösung Übung 13 string header = to_string(req.size()); // string ist plattformabhängig string msg; msg += header + ":" + req + "]]]"; size_t msglen = msg.size(); size_t len = 0; while (len < msglen) { // zu lange Nachrichten zerstückeln string buf = msg.substr(0, MSG_SIZE); ssize_t r = ::write(_sfd, buf.c_str(), buf.size()); if (-1 == r) throw SocketException(string("send: ") + strerror(errno)); len += r; msg = msg.substr(r); } } std::string Socket::recv() { // Lösung Übung 13 string msg, res; string::size_type pos; // falls mit dem letzten recv mehrere Nachrichten empfangen wurden if (_tail.size() > 0 && _tail.find("]]]") != string::npos) { pos = _tail.find("]]]"); res = _tail.substr(0, pos); _tail = _tail.substr(pos + 3); pos = res.find(":"); return res.substr(pos + 1); } else msg = _tail; ssize_t len; char block[MSG_SIZE]; do { // memset(block, 0, c_msg_size); len = ::read(_sfd, block, MSG_SIZE); if (-1 == len) throw SocketException(string("recv: ") + strerror(errno)); if (len > 0) { block[len] = '\0'; msg += block; } if (len == 0) // connection closed throw SocketException("connection closed"); } while (msg.find("]]]") == string::npos); pos = msg.find(":"); string header = msg.substr(0, pos); size_t msgLen = stoi(header); res = msg.substr(pos+1, msgLen); _tail = msg.substr(pos + 1 + msgLen + 3); return res; } void Socket::close(void) { ::close(_sfd); } }

Server-Socket-Wrapper

serverSocket.hpp

#include <string> #include <cerrno> #include <cstring> #include <netinet/in.h> #include "socket.hpp" class ServerSocket { private: sockaddr_in _address; int _sfd; socklen_t _addrlen; public: ServerSocket(int port, int queueSize); ~ServerSocket(void); Socket accept(void); void send(std::string msg); std::string recv(void); };

serverSocket.cpp

#include ... ServerSocket::ServerSocket(int port, int qSize) { // create a server-socket _sfd = ::socket(AF_INET, SOCK_STREAM, 0); if (_sfd == -1) throw SocketException(strerror(errno)); // Fehler "cannot bind socket: Address already in use" abfangen int i = 1; ::setsockopt(_sfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)); // bind server port _address.sin_family = AF_INET; _address.sin_addr.s_addr = INADDR_ANY; _address.sin_port = ::htons(port); int r = ::bind(_sfd,(struct sockaddr *)&_address, sizeof(_address)); if (r == -1) throw SocketException(strerror(errno)); // listen for incoming requests ::listen(_sfd, qSize); _addrlen = sizeof(struct sockaddr_in); } ServerSocket::~ServerSocket() { ::close(_sfd); } Socket ServerSocket::accept(void) { // waiting for incoming requests cout << "waiting for incoming requests ..." << endl; int conn = ::accept(_sfd, (struct sockaddr *)&_address, &_addrlen); if (conn == -1) throw SocketException(strerror(errno)); cout << "----> accept socket: " << conn << endl; return Socket(conn); }

Echo-Server

Der Echo-Server ist ein einfacher Server, der eine Nachricht von einem Client empfängt und diese wieder an den Client zurücksendet. Oft wird diese Art von Server verwendet zur Fehlersuche.

server.cpp

#include "socket.hpp" #include "servSocket.hpp" using namespace std; int main(int argc, char **argv) { ServerSocket server(6200, 10); while (1) { Socket acceptSocket = server.accept(); string req = acceptSocket.recv(); acceptSocket.send("ECHO REPLY: " + req); acceptSocket.close(); } }

client.cpp

#include "socket.hpp" #include <iostream> #include <string> using namespace std; string host = "127.0.0.1"; int port = 6200; void work(string req) { try { Socket sock(host, port); sock.send(req); string msg = sock.recv(); cout << "received from server: " << msg << endl; } catch (SocketException e) { cout << e.getError() << endl; } } int main(int argc, char **argv) { string req[7] = {"ECHO:Hallo, Welt!", "DATE:now", "TIME:now", "RANDOM:20000", "PRIME:1234567899", "GGT:12345678, 23456789", "blubb"}; for (int i = 0; i < 20; i++) { work(req[i % 7]); } }
Last updated on