C - How to use both aio_read () and aio_write ()

I use a game server where I need to read and write. So I accept the incoming connection and start reading from it using aio_read () , but when I need to send something, I stop reading using aio_cancel () , and then use aio_write () . In the write callback, I resume reading. So, I read all the time, but when I need to send something, I pause reading.

It works for ~ 20% of the time - in another case, the call to aio_cancel () ends with an error "Current operation" - and I can not cancel it (even during a constant cycle). Thus, my added write operation never happens.

How to use these functions? What did I miss?

EDIT: Used under Linux 2.6.35. Ubuntu 10 - 32 bit.

Code example:

void handle_read(union sigval sigev_value) { /* handle data or disconnection */ }
void handle_write(union sigval sigev_value) { /* free writing buffer memory */ }
void start()
{
    const int acceptorSocket = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in addr;
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(port);
    bind(acceptorSocket, (struct sockaddr*)&addr, sizeof(struct sockaddr_in));

    listen(acceptorSocket, SOMAXCONN);

    struct sockaddr_in address;
socklen_t addressLen = sizeof(struct sockaddr_in);

    for(;;)
    {
         const int incomingSocket = accept(acceptorSocket, (struct sockaddr*)&address, &addressLen);
         if(incomingSocket == -1)
         { /* handle error ... */}
         else
         {
              //say socket to append outcoming messages at writing:
              const int currentFlags = fcntl(incomingSocket, F_GETFL, 0);
              if(currentFlags < 0) { /* handle error ... */ }
              if(fcntl(incomingSocket, F_SETFL, currentFlags | O_APPEND) == -1) { /* handle another error ... */ }

              //start reading:
              struct aiocb* readingAiocb = new struct aiocb;
              memset(readingAiocb, 0, sizeof(struct aiocb));
              readingAiocb->aio_nbytes = MY_SOME_BUFFER_SIZE;
              readingAiocb->aio_fildes = socketDesc;
              readingAiocb->aio_buf = mySomeReadBuffer;
              readingAiocb->aio_sigevent.sigev_notify = SIGEV_THREAD;
              readingAiocb->aio_sigevent.sigev_value.sival_ptr = (void*)mySomeData;
              readingAiocb->aio_sigevent.sigev_notify_function = handle_read;
              if(aio_read(readingAiocb) != 0) { /* handle error ... */ }
          }
    }
}

//called at any time from server side:
send(void* data, const size_t dataLength)
{
    //... some thread-safety precautions not needed here ...

    const int cancellingResult = aio_cancel(socketDesc, readingAiocb);
    if(cancellingResult != AIO_CANCELED)
    {
        //this one happens ~80% of the time - embracing previous call to permanent while cycle does not help:
        if(cancellingResult == AIO_NOTCANCELED)
        {
            puts(strerror(aio_return(readingAiocb))); // "Operation now in progress"
            /* don't know what to do... */
        }
    }
    //otherwise it okay to send:
    else
    {
        aio_write(...);
    }
}
+5
source share
4 answers

If you want to have separate AIO queues for reading and writing, so that a subsequently published record can be performed before a reading released earlier, you can use it dup()to create a duplicate socket and use it to read reads, and the other writes.

, AIO epoll() -driven . , - , , , , , .

+3

, aio. -, braindead (, aio - breaindead). ; Linux, libaio (io_submit ). aio (7) .

.
aio, , . aio_read aio_write (aiocb) . , . , , , . , : .

/* populate read_aiocb */
rc = aio_read(&read_aiocb);

/* time passes ... */
/* populate write_aiocb */
rc = aio_write(&write_aiocb)

, aio_suspend, , aio_error, ..

, epoll . libaio.

+4

aio , . , , - , . , /, aiocb "" , , "" , , , . , "" . , aiocb , , ... , " ".

, , / /. , . , , aiocb, "" โ†’ "" โ†’ "" . , aiocb "" , "" .

+1

, POSIX AIO ( aio_read(), aio_write() ..), . man- aio_read():

   The  data  is  read starting at the absolute file offset aiocbp->aio_offset, regardless of the
   current file position.  After this request, the value of the current file position is unspeciโ€
   fied.

, , , AFAICS, POSIX AIO undefined. , , , .

, Linux POSIX AIO glibc .

, , IO epoll(). epoll() , , ( select()/poll()); POSIX AIO .

0

All Articles