你好,我决定在 c 套接字上写一个小包装器,告诉我为什么 sigpipe 在写函数中崩溃?
套接字.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
套接字.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;
}
主.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 由于发送到一个不存在的连接而匆忙......更正了使用 MSG_NOSIGNAL 标志发送的写入并停止接收 sigpipe ...并且不存在的连接是由于二进制文件不是从root,但是不能绑定到小于 1024 套接字的用户端口(不是 root)...将端口更改为 1200,一切都很好