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) { }
void handle_write(union sigval sigev_value) { }
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)
{ }
else
{
const int currentFlags = fcntl(incomingSocket, F_GETFL, 0);
if(currentFlags < 0) { }
if(fcntl(incomingSocket, F_SETFL, currentFlags | O_APPEND) == -1) { }
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) { }
}
}
}
send(void* data, const size_t dataLength)
{
const int cancellingResult = aio_cancel(socketDesc, readingAiocb);
if(cancellingResult != AIO_CANCELED)
{
if(cancellingResult == AIO_NOTCANCELED)
{
puts(strerror(aio_return(readingAiocb)));
}
}
else
{
aio_write(...);
}
}
source
share