Привет. Произвел замеры времени потерь для разных участков кода, заметил плохую тенденцию: на recv вызовах теряется ОЧЕНЬ много времени(чуть менее 1 минуты). Подскажите, что конкретно я не так делаю(простая RAII обертка):
#include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <netdb.h> #include <cerrno>
class socket : public sph::types::noncopyable { public: socket(addrinfo* const addr) throw(sph::exceptions::network_connection_error); ~socket() throw(); ssize_t send(const char *buf, size_t len) throw(); void send_all(const char *buf, size_t len = 0) throw(sph::exceptions::network_error); ssize_t recv(char *buf, size_t len) throw(); void set_recv_timeout(unsigned int milliseconds) throw(); protected: addrinfo* _addr; int _socket; private: bool _self_made_addrinfo; bool _socket_created; };
socket::socket(addrinfo* const addr) throw(X) : _addr(addr), _self_made_addrinfo(false), _socket_created(false) { // For each resolved ip for (addrinfo* addr_iterator = _addr; addr_iterator != NULL; addr_iterator = addr_iterator->ai_next) { // Try to create socket _socket = ::socket(addr_iterator->ai_family, addr_iterator->ai_socktype, addr_iterator->ai_protocol); // Error create socket if (_socket == -1) throw(X); // Move next if can't connect if (::connect(_socket, addr_iterator->ai_addr, addr_iterator->ai_addrlen) != 0) continue; _socket_created = true; return; } throw(X); } socket::~socket() throw() { // Free addrinfo only if this class creates it if (_self_made_addrinfo) freeaddrinfo(_addr); // Close socket only if we ever create it if (_socket_created) { shutdown(_socket, SHUT_RDWR); close(_socket); } } void socket::send_all(const char *buf, size_t len) throw(sph::exceptions::network_error) { if (len == 0) len = sph::c::strlen(buf); int send_bytes_count = 0; while(send_bytes_count != len) { int ret = send(buf+send_bytes_count, len - send_bytes_count); // If error occured if (ret == -1) throw(sph::exceptions::network_error(errno)); send_bytes_count += ret; } }
inline ssize_t socket::send(const char *buf, size_t len) throw() { return ::send(_socket, const_cast<char*>(buf), len, 0); } inline ssize_t socket::recv(char *buf, size_t len) throw() { return ::recv(_socket, const_cast<char*>(buf), len, 0); } inline void socket::set_recv_timeout(unsigned int milliseconds) throw() { const struct timeval tv = { milliseconds/1000, milliseconds%1000 }; setsockopt (_socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); }
addrinfo получаю следующим образом: const struct addrinfo hints = {0, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL, NULL}; int resolve_code = getaddrinfo("server", "80", &hints, &_addr);