2008-11-15 5 views

답변

3

물론입니다! Boost ASIO를 사용하면 기본/기본 데이터 (이 경우 SOCKET 자체)에 액세스 할 수 있습니다.

boost::asio::ip::tcp::socket my_socket; 

과의 이미 open 또는 bind 또는 실제로 my_socket 가능하게 일부 멤버 함수를 호출 한 가정 해 봅시다 : 그래서, 당신이 가정 해 봅시다. 그런 다음, 기본 소켓 값을 얻기 위해 전화 :

SOCKET native_sock = my_socket.native(); 
int result = SOCKET_ERROR; 

if (INVALID_SOCKET != native_sock) 
{ 
    result = setsockopt(native_sock, SOL_SOCKET, <the pertinent params you want to use>); 
} 

을 이렇게 거기 당신은 그것이있다! Boost의 ASIO를 사용하면 가능한 한 많은 작업을보다 신속하게 수행 할 수 있지만 일반 소켓 라이브러리가 필요로하는 많은 것들이 있습니다. 이것은 그들 중 하나입니다.

+2

가장 낮은 레벨의 send/recv 기능을 제외하고 모두 EAGAIN을 명시 적으로 catch하는 호출에 대해 (;;) 루프가 있습니다. Boost에서 송수신 기능의 95 %를 폐기하지 않으면 SO_ {SND, RCV} TIMEO 옵션이 효과적으로 쓸모 없게됩니다. 따라서 옵션을 설정하는 것이 허용된다는 것은 의의가 있습니다. 라이브러리의 나머지 부분을 사용하지 않는 것이 유일한 방법이기 때문에 ... – Tom

+0

우수 포인트. 나는 지금 이것을 치렀다. 젠장. –

3

현재 Boost.Asio (현재 Boost SVN 현재)에는 내장되어 있지 않지만, boost::asio::detail::socket_option을 시뮬레이트하기 위해 고유 한 클래스를 작성하려는 경우 언제든지 boost/asio/socket_base.hpp의 예제를 따라갈 수 있습니다.

typedef boost::asio::detail::socket_option::timeval<SOL_SOCKET, SO_SNDTIMEO> 
    send_timeout; 
typedef boost::asio::detail::socket_option::timeval<SOL_SOCKET, SO_RCVTIMEO> 
    receive_timeout; 

(물론, 난 당신이 boost::asio::detail::socket_option 네임 스페이스에 timeval 클래스를 주입 제안 아니지만, 나는 순간에 사용하는 것이 하나 생각할 수 없다 - P.) 그리고 다음을 수행

편집 : 내 샘플 구현 socket_option::timeval,기준:

// Helper template for implementing timeval options. 
template <int Level, int Name> 
class timeval 
{ 
public: 
    // Default constructor. 
    timeval() 
    : value_(zero_timeval()) 
    { 
    } 

    // Construct with a specific option value. 
    explicit timeval(::timeval v) 
    : value_(v) 
    { 
    } 

    // Set the value of the timeval option. 
    timeval& operator=(::timeval v) 
    { 
    value_ = v; 
    return *this; 
    } 

    // Get the current value of the timeval option. 
    ::timeval value() const 
    { 
    return value_; 
    } 

    // Get the level of the socket option. 
    template <typename Protocol> 
    int level(const Protocol&) const 
    { 
    return Level; 
    } 

    // Get the name of the socket option. 
    template <typename Protocol> 
    int name(const Protocol&) const 
    { 
    return Name; 
    } 

    // Get the address of the timeval data. 
    template <typename Protocol> 
    ::timeval* data(const Protocol&) 
    { 
    return &value_; 
    } 

    // Get the address of the timeval data. 
    template <typename Protocol> 
    const ::timeval* data(const Protocol&) const 
    { 
    return &value_; 
    } 

    // Get the size of the timeval data. 
    template <typename Protocol> 
    std::size_t size(const Protocol&) const 
    { 
    return sizeof(value_); 
    } 

    // Set the size of the timeval data. 
    template <typename Protocol> 
    void resize(const Protocol&, std::size_t s) 
    { 
    if (s != sizeof(value_)) 
     throw std::length_error("timeval socket option resize"); 
    } 

private: 
    static ::timeval zero_timeval() 
    { 
    ::timeval result = {}; 
    return result; 
    } 

    ::timeval value_; 
}; 
+0

그냥 할 수 없어 : typedef boost :: asio :: detail :: socket_option :: integer send_timeout; recv 타임 아웃과 동일합니까? 왜 timeval 구조체가 필요한가요? –

+0

하하하, 내 대답의 첫 번째 버전에서 보게 될 것입니다. 그것이 내가 생각한 것입니다. 그러나 http://www.opengroup.org/onlinepubs/009695399/functions/setsockopt.html을 읽고 타임 아웃 값은 int가 아니라 timeval을 사용하는 것을 볼 수 있습니다. –

0

이 문제의 쉬운 해결 방법은 기본 읽기 및 쓰기 기능을 사용하는 것입니다. 1 초 시간 제한으로 쓰기 위해

:

struct timeval tv = { 1, 0 }; 
setsockopt(socket.native_handle(), SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); 
ssize_t nsent = ::write(socket->native_handle(), buff, size); 
if (nsent > 0) { 
    BOOST_LOG_TRIVIAL(debug) << "Sent " << nsent << " bytes to remote client " << ep; 
} else if (nsent == 0) { 
BOOST_LOG_TRIVIAL(info) << "Client " << ep << " closed connection"; 
} else if (errno != EAGAIN) { 
    BOOST_LOG_TRIVIAL(info) << "Client " << ep << " error: " <<  strerror(errno); 
} 

1 초 시간 제한과 독서의 경우는 :

struct timeval tv = { 1, 0 }; 
setsockopt(socket.native_handle(), SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); 
ssize_t nread = ::read(socket.native_handle(), buff, audio_buff_size); 
if (nread > 0) { 
} else if (nread == 0) { 
    BOOST_LOG_TRIVIAL(info) << "Source " << source << " server " << host << " closed connection"; 
    break; 
} else if (errno != EAGAIN) { 
    BOOST_LOG_TRIVIAL(info) << "Source " << source << " server " << host << " error: " << strerror(errno); 
    break; 
} 

이 나를 위해 잘 일했다.