Linux — сокет C ++, никогда не готовый для записи с опросом

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

код опроса:

/**
*@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() просто возвращает FD, возвращенный socket(int,int,int) в 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:

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, можно предположить, что подключение и чтение / запись обрабатываются правильно. Тест не пройден при опросе на запись

1

Решение

В 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 произошло.

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]