здравствуйте, решил написать небольшую обертку над си-шными сокетами, подскажите почему вылетает 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;
}
в общем sigpipe кидался из-за посылки в несуществующее соединение... поправил write на send с флагом MSG_NOSIGNAL и перестал приходить sigpipe... а несуществующим соединение было из-за того что бинарь запускал не от рута, а к меньшему чем 1024 порту пользовательский сокет(не рут) не может быть прибинден... заменил порт на 1200 и все стало нормально
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Определить класс, который позволяет хранить данные об исключении объекта, который должен содержать информацию о том, что () для возвращения...
Нужно в программу передать имя файла, получаемое через открытие через командную строкуfile_name должно быть типа стринг
У меня есть Вектор 1, для обозначения времени сутокВ нем находятся 24 нуля