Tranvick

Sockets

May 20th, 2014
272
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.14 KB | None | 0 0
  1. #include <sys/socket.h>
  2. #include <sys/types.h>
  3. #include <sys/un.h>
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <unistd.h>
  7. #include <stdio.h>
  8. #include <netdb.h>
  9. #include <arpa/inet.h>
  10. #include <stdexcept>
  11. #include <vector>
  12.  
  13. #include <iostream>
  14.  
  15.  
  16. typedef std::vector<char> Buffer;
  17.  
  18. void appendTo (Buffer *buffer, char *begin, size_t size) {
  19.    buffer->insert(buffer->end(), begin, begin + size);
  20. }
  21.  
  22. class OkOrException {
  23. private:
  24.    bool is_good_;
  25.    std::runtime_error exception_;
  26.  
  27. public:
  28.    OkOrException() :
  29.        is_good_(true),
  30.        exception_(std::runtime_error(""))
  31.        {}
  32.  
  33.    void setException(const std::runtime_error &exception) {
  34.        is_good_ = false;
  35.        exception_ = exception;
  36.    }
  37.  
  38.    void check() const {
  39.        if (!is_good_) {
  40.            throw exception_;
  41.        }
  42.    }
  43. };
  44.  
  45. typedef OkOrException Status;
  46.  
  47. struct InternetAddress {
  48. private:
  49.    std::string address_;
  50.    int port_;
  51.  
  52. public:
  53.    explicit InternetAddress(std::string address, int port) :
  54.        address_(address),
  55.        port_(port)
  56.        {}
  57.  
  58.    struct sockaddr getSocketAddress() const {
  59.        struct sockaddr_in address;
  60.        address.sin_family = AF_INET;
  61.        address.sin_port = htons(port_);
  62.        address.sin_addr.s_addr = inet_addr(address_.c_str());
  63.        memset(address.sin_zero, '\0', sizeof address.sin_zero);
  64.        return *((sockaddr *) &address);
  65.    }
  66.    
  67.    ~InternetAddress() {}
  68. };
  69.  
  70. class ConnectionSocket {
  71. private:
  72.    int connection_fd_;
  73.    Status status_;
  74.    bool have_resources_;
  75.  
  76. public:
  77.  
  78.    ConnectionSocket(int connection_fd) :
  79.        connection_fd_(connection_fd),
  80.        have_resources_(true)
  81.        {}
  82.  
  83.    ConnectionSocket(const ConnectionSocket &) = delete;
  84.    ConnectionSocket &operator=(const ConnectionSocket &) = delete;
  85.    ConnectionSocket(ConnectionSocket &&other) {
  86.        connection_fd_ = other.connection_fd_;
  87.        status_ = std::move(other.status_);
  88.        other.have_resources_ = false;
  89.        have_resources_ = true;
  90.    }
  91.  
  92.    Buffer read() {
  93.        constexpr int BUFFER_SIZE = 100;
  94.        char buffer[BUFFER_SIZE];
  95.  
  96.        Buffer result;
  97.  
  98.        while (true) {
  99.            memset(buffer, 0, BUFFER_SIZE);
  100.            int recv_result = recv(connection_fd_, buffer, BUFFER_SIZE, 0);
  101.            appendTo(&result, buffer, BUFFER_SIZE);
  102.            
  103.            if (recv_result < BUFFER_SIZE) {
  104.                break;
  105.            }
  106.        }
  107.      
  108.        std::cout << "1\n";
  109.        return std::move(result);
  110.    }
  111.  
  112.    void write(Buffer buffer) {
  113.        send(connection_fd_, buffer.data(), buffer.size(), 0);
  114.    }
  115.  
  116.    ~ConnectionSocket() {
  117.        if (have_resources_) {
  118.            ::close(connection_fd_);
  119.        }
  120.    }
  121. };
  122.  
  123. class ServerSocket {
  124. private:
  125.    int fd_;
  126.    Status status_;
  127.  
  128.    void initSocket() {
  129.        fd_ = ::socket(AF_INET, SOCK_STREAM, 0);
  130.        if (fd_ < 0) {
  131.            throw std::runtime_error("Failed to create socket");
  132.        }
  133.    }
  134.  
  135.    void bindToAddress(const InternetAddress &internet_address) {
  136.        struct sockaddr address = internet_address.getSocketAddress();
  137.        int bound = ::bind(fd_, (struct sockaddr *) &address, sizeof(address));
  138.        if (bound == -1) {
  139.            throw std::runtime_error("Failed to bind socket");
  140.        }
  141.    }
  142.  
  143.    void listenTo() {
  144.        int listen_result = ::listen(fd_, 10);
  145.        if (listen_result == -1) {
  146.            throw std::runtime_error("Failed to listen");
  147.        }
  148.    }
  149.  
  150.    void closeSocket() {
  151.        ::close(fd_);
  152.        //::unlink(fd_);
  153.    }
  154.  
  155. public:
  156.    ServerSocket(const InternetAddress &internet_address) {
  157.        try {
  158.            initSocket();
  159.            bindToAddress(internet_address);
  160.            listenTo();
  161.        } catch(const std::runtime_error &exception) {
  162.            status_.setException(exception);
  163.        }
  164.    }
  165.  
  166.    ConnectionSocket newConnection() {
  167.        int new_fd = ::accept(fd_, 0, 0);
  168.        if (new_fd < 0) {
  169.            throw std::runtime_error("Failed to accept socket");
  170.        }
  171.        return std::move(ConnectionSocket(new_fd));
  172.    }
  173.  
  174.    ServerSocket(const ServerSocket &) = delete;
  175.    ServerSocket &operator=(const ServerSocket &) = delete;
  176.  
  177.    void check() const {
  178.        status_.check();
  179.    }
  180.  
  181.    ~ServerSocket() {
  182.        closeSocket();
  183.    }
  184. };
  185.  
  186. int main() {
  187.    static constexpr char LOCALHOST[] = "127.0.0.1";
  188.    static constexpr int DEFAULT_PORT = 8992;
  189.  
  190.    InternetAddress address = InternetAddress(LOCALHOST, DEFAULT_PORT);
  191.    ServerSocket server_socket(address);
  192.  
  193.    try {
  194.        server_socket.check();
  195.    } catch (const std::exception &ex) {
  196.        std::cerr << ex.what() << std::endl;
  197.        return 1;
  198.    }
  199.  
  200.    std::string respond("HTTP/1.1 200 OK\n\n<html>hello<html>\n");
  201.    Buffer respond_buffer = Buffer(respond.begin(), respond.end());
  202.  
  203.    try {
  204.        while (true) {
  205.            ConnectionSocket connection_socket(server_socket.newConnection());
  206.            Buffer read_buffer = connection_socket.read();
  207.            connection_socket.write(respond_buffer);
  208.        }
  209.    } catch (const std::exception &ex) {
  210.        std::cerr << ex.what() << std::endl;
  211.        return 1;
  212.    }
  213.  
  214.    return 0;
  215. }
Advertisement
Add Comment
Please, Sign In to add comment