обертка над сокетами кидает исключение

329
03 июня 2017, 17:06

здравствуйте, решил написать небольшую обертку над си-шными сокетами, подскажите почему вылетает sigpipe в функции write?

socket.hpp

#ifndef SOCKET_HPP
#define SOCKET_HPP

#include <iostream>
#include <vector>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <strings.h>
enum class socket_type {
    client,
    server,
};

class ISocket {
public:
    ISocket() = default;
    virtual ~ISocket() = default;
    virtual void connect() = 0;
    virtual void close() = 0;
    virtual void receive(char* buff, std::size_t len) = 0;
    virtual void receive(std::vector<char>& buff, std::size_t len) = 0;
    virtual void send(char* buff, std::size_t len) = 0;
    virtual void send(std::vector<char> &buff, std::size_t len) = 0;
protected:
    virtual void bind() = 0;
    virtual void accept() = 0;
    virtual void listen() = 0;
    virtual int getdescriptor() = 0;
};
class serv_socket : public ISocket {
public:
    // у серверного сокета должен быть порт
    serv_socket(int port);
    ~serv_socket() = default;
    virtual void connect() final;
    virtual void close() final;
    virtual void receive(char *buff, std::size_t len) final;
    virtual void receive(std::vector<char> &buff, std::size_t len) final;
    virtual void send(char *buff, std::size_t len) final;
    virtual void send(std::vector<char> &buff, std::size_t len) final;
protected:
    virtual void bind() final;
    virtual void accept() final;
    virtual void listen() final;
    virtual int getdescriptor() final;
private:
    //дескриптор сокета который прослушиваем
    int descriptor;
    // дескриптор сокета к которому accept-имся
    int newdescriptor;
    // адрес сокета который прослушиваем
    struct sockaddr_in addr;
    // адрес сокета к которому accept-имся
    struct sockaddr cli_addr;
    //
    socklen_t clilen;
    // тип сокета
    socket_type type;
};
class client_socket : public ISocket {
public:
    client_socket(char * const address, int port);
    ~client_socket() = default;
    virtual void connect() final;
    virtual void close() final;
    virtual void receive(char* buff, std::size_t len) final;
    virtual void receive(std::vector<char> &buff, std::size_t len) final;
    virtual void send(char *buff, std::size_t len) final;
    virtual void send(std::vector<char> &buff, std::size_t len) final;

protected:
    virtual void bind() final;
    virtual void accept() final;
    virtual void listen() final;
    virtual int getdescriptor() final;
private:
    //дескриптор сокета
    int descriptor;
    //характеристики сокета
    struct sockaddr_in serv_addr;
    // хост
    struct hostent *server;
    // тип сокета
    socket_type type;
};
#endif // SOCKET_HPP

socket.cpp:

#include <socket.hpp>
#include <vector>
#include <netdb.h>
serv_socket::serv_socket(int port)
    : ISocket(),
      descriptor(0),
      newdescriptor(0),
      type(socket_type::server)
{
    descriptor = ::socket(AF_INET, SOCK_STREAM, 0);
    bzero((char *) &addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(port);
}
void serv_socket::bind() {
    if(::bind(descriptor,
              (struct sockaddr *) &addr,
              sizeof(addr)) < 0
    )
        log_("ERROR in bind socket");
}
void serv_socket::listen()
{
    ::listen(descriptor, 5);
}
void serv_socket::accept()
{
    clilen = sizeof(cli_addr);
    newdescriptor = ::accept(descriptor,
                     (struct sockaddr *) &cli_addr,
                     &clilen);
}
void serv_socket::close() {
    ::close(newdescriptor);
    ::close(descriptor);
}
void serv_socket::receive(std::vector<char>& buff, std::size_t len) {
    int n = ::read(newdescriptor, buff.data(), len);
    if(n < 0)
        log_("ERROR reading from socket");
}
void serv_socket::receive(char *buff, std::size_t len) {
    int n = ::read(newdescriptor, buff, len);
    if(n < 0)
        log_("ERROR reading from socket");
}
void serv_socket::send(std::vector<char>& buff, std::size_t len) {
    int n = ::write(newdescriptor, buff.data(), len);
}
void serv_socket::send(char *buff, std::size_t len) {
    int n = ::write(newdescriptor, buff, len);
}
void serv_socket::connect()
{
    bind();
    listen();
    accept();
}
int serv_socket::getdescriptor() {
    return descriptor;
}
// ------------------клиентский сокет
client_socket::client_socket(char* const address, int port)
    : ISocket(),
      descriptor(0),
      type(socket_type::client)
{
    // создаем сокет
    descriptor = socket(AF_INET, SOCK_STREAM, 0);
    // устанавливаем адрес сервера
    server = gethostbyname(address);
    if(server == nullptr)
        log_("ERROR");
    //
    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    bcopy((char *)server->h_addr,
         (char *)&serv_addr.sin_addr.s_addr,
         server->h_length);
    serv_addr.sin_port = htons(port);
}
void client_socket::connect() {
    if (::connect(descriptor,
                  (struct sockaddr *)&serv_addr,
                  sizeof(serv_addr)) < 0
        )
            log_("ERROR connecting");
}
void client_socket::close() {
    ::close(descriptor);
}
void client_socket::receive(std::vector<char> &buff, std::size_t len) 
{
    int n = ::read(descriptor, buff.data(), len);
    if(n < 0)
        log_("ERROR reading from socket");
}
void client_socket::receive(char* buff, std::size_t len) {
    int n = ::read(descriptor, buff, len);
    if(n < 0)
        log_("ERROR reading from socket");
}
void client_socket::send(std::vector<char>& buff, std::size_t len) {
    int n = ::write(descriptor, buff.data(), len);
}
void client_socket::send(char* buff, std::size_t len) {
    int stop = 0;
    int n = ::write(descriptor, buff, len);     <<---------------вот тут вылетает sigpipe
}
void client_socket::bind() {
}
void client_socket::accept() {
}
void client_socket::listen() {
}
int client_socket::getdescriptor() {
    return descriptor;
}

main.cpp:

int main(int argc, char** argv) {
    client_socket cs("127.0.0.1", 80);
    cs.connect();
    cs.send("hello", 6);
    cs.close();
    return 0;
}
Answer 1

в общем sigpipe кидался из-за посылки в несуществующее соединение... поправил write на send с флагом MSG_NOSIGNAL и перестал приходить sigpipe... а несуществующим соединение было из-за того что бинарь запускал не от рута, а к меньшему чем 1024 порту пользовательский сокет(не рут) не может быть прибинден... заменил порт на 1200 и все стало нормально

READ ALSO
Считывание из файла c++

Считывание из файла c++

В текстовом файле имеется информация, представленная в таком формате

360
Как это сделать [требует правки]

Как это сделать [требует правки]

Определить класс, который позволяет хранить данные об исключении объекта, который должен содержать информацию о том, что () для возвращения...

451
Как передать в главный поток строку, получаемую через командную строку?

Как передать в главный поток строку, получаемую через командную строку?

Нужно в программу передать имя файла, получаемое через открытие через командную строкуfile_name должно быть типа стринг

234
Векторы с++. Создание двумерного вектора

Векторы с++. Создание двумерного вектора

У меня есть Вектор 1, для обозначения времени сутокВ нем находятся 24 нуля

229