2013-07-25 2 views
1

Я пишу обертку C++ для сокетов в Linux. Я могу подключить чтение/запись к http-серверу. Моя функция опроса отлично работает для чтения, но по какой-то причине она не будет работать с записью. Я попытался с помощью GDB, и кажется, опрос устанавливает fd.revents на 0, когда fd.events является POLLOUTC++ socket никогда не готов для записи с опросом

опроса Код:

/** 
*@brief assigns request.reply based on fd.revents 
*/ 
static void translate_request(mizaru::PollRequest &request, pollfd &fd) 
{ 

    assert((fd.revents & POLLHUP) == 0); 
    assert((fd.revents & POLLERR) == 0); 
    assert((fd.revents & POLLNVAL) == 0); 


    switch(fd.revents) 
    { 
     case (POLLIN | POLLOUT) : 
     request.reply = mizaru::POLL_REPLY_RW; 
     break; 
     case POLLIN : 
     request.reply = mizaru::POLL_REPLY_READ; 
     break; 
     case POLLOUT : 
     request.reply = mizaru::POLL_REPLY_WRITE; 
     default : 
     request.reply = 0; 
    } 

} 

/** 
* @fills in fd.events based on request.request 
* and fd.fd based on request.sock 
*/ 
static void prep_request(mizaru::PollRequest &request, pollfd &fd) 
{ 

    fd.fd = request.sock.get_handle(); 
    switch(request.request) 
    { 

    case mizaru::PollType::POLL_READ : 
     fd.events = POLLIN; 
     break; 
    case mizaru::PollType::POLL_WRITE : 
     fd.events = POLLOUT; 
     break; 
    default : 
     fd.events = POLLIN | POLLOUT; 

    } 


} 

void mizaru::trans::poll(mizaru::PollRequest &request,const std::chrono::milliseconds& wait_time) noexcept 
{ 

    pollfd fd; 
    prep_request(request, fd); 
    poll(&fd, 1, wait_time.count()); 
    translate_request(request, fd); 
} 

mizaru::PollRequest структура:

struct PollRequest 
{ 
    PollRequest(PollType request, const SyncSocket &sock) : sock(sock), request(request), reply(POLL_REPLY_FAIL) {} 
    const SyncSocket & sock; 
    PollType request; 
    uint8_t reply; 
}; 

SyncSocket.get_handle() просто возвращает ФД возвращенной socket(int,int,int) in sys/socket.h

контрольная функция :

bool test_poll() 
{ 
    mizaru::IPv4 ip ("54.225.138.124"); 
    mizaru::SyncSocketTCP sock (ip, 80 ,true); 
    mizaru::PollRequest request{mizaru::PollType::POLL_READ, sock}; 
    std::chrono::milliseconds time(1000); 

    mizaru::poll(request, time); 

    if(request.reply == mizaru::POLL_REPLY_READ) 
    { 
     std::cout << "fail test_poll first read" <<std::endl; 
     return false; 
    } 

    request.request = mizaru::PollType::POLL_WRITE; 
    mizaru::poll(request, time); 

    if(request.reply != mizaru::POLL_REPLY_WRITE) 
    { 
     std::cout << "fail test_poll first write" << std::endl; 
     return false; 
    } 

std::string toWrite ("GET/http/1.1\nHost: httpbin.org\n\n"); 
mizaru::byte_buffer write_buff; 

for (char c : toWrite) 
    { 
     write_buff.push_back (c); 
    } 

    unsigned int r_value = sock.write (write_buff); 

    if (r_value != toWrite.size()) 
    { 
     std::cout << "fail test_poll r_value" << std::endl; 
     return false; 
    } 



    request.request = mizaru::PollType::POLL_READ; 

    mizaru::poll(request, time); 

    if(request.reply != mizaru::POLL_REPLY_READ) 
    { 
     std::cout << "fail test_poll second read" << std::endl; 
     return false; 
    } 

    request.request = mizaru::PollType::POLL_WRITE; 

    mizaru::poll(request, time); 

    if(request.reply != mizaru::POLL_REPLY_WRITE) 
    { 
     std::cout << "fail test_poll second write " << std::endl; 
     return false; 
    } 

    return true; 
} 

PollType перечислений:

enum PollType {POLL_READ, POLL_WRITE, POLL_RW};

POLL_REPLY_* константы:

constexpr uint8_t POLL_REPLY_READ = 0x01; 
constexpr uint8_t POLL_REPLY_WRITE = 0x02; 
constexpr uint8_t POLL_REPLY_RW = POLL_REPLY_READ | POLL_REPLY_WRITE; 
constexpr uint8_t POLL_REPLY_FAIL = 0; 

Я сожалею, что образец кода непосредственно не компилируется я пытался сделать его коротким, Поскольку я получаю правильный ответ HTTP 200 OK, вы можете предположить, что соединение и чтение/запись обрабатываются d надлежащим образом. Тест терпит неудачу, когда опрос для записи

+0

if (request.reply == mizaru :: POLL_REPLY_READ) { std :: cout << "fail test_poll first read" << std :: endl; return false;} Должен ли он показывать сообщение об ошибке, когда ответ == читается? – Lochemage

+0

@Lochemage Да, первый из них, так как HTTP-сервер не получил запрос на ответ, и, следовательно, нет данных для чтения, также если я удалю опрос записи теста из тестового примера, он преуспеет –

ответ

5

В translate_request():

switch(fd.revents) 
{ 
    case (POLLIN | POLLOUT) : 
    request.reply = mizaru::POLL_REPLY_RW; 
    break; 

    case POLLIN : 
    request.reply = mizaru::POLL_REPLY_READ; 
    break; 

    case POLLOUT : 
    request.reply = mizaru::POLL_REPLY_WRITE; 
    default : 
    request.reply = 0; 
} 

Вы пропускаете break в обоих POLLOUT и default случаев. POLLOUT проваливается до default, удаляя доказательства, что произошло POLLOUT.

+0

Спасибо !!! У меня нет идеи, как я пропустил это –