Доброго дня. В работе с сокетами использую неблокирующие сокеты.
Подскажите пример для чтения данных, с использованием kevent()
Или подскажите, что необходимо учитывать или на что обращать внимание...
Вот мой код:
int Console::ReadMsg( PString & str ){
cout << "Console::ReadMsg( PString & str )" << endl;
int retn=-1;
int poller = kqueue();
Buffer[0]='\0';
PAssertOS( poller>0 );
struct kevent event;
struct kevent result;
struct timespec ts = { 0, 0 };
int what = 0;
int step=0;
memset( &event, 0, sizeof(event) );
event.ident = sock;
event.filter = EVFILT_READ;
event.flags = EV_ADD | EV_ENABLE;
what = kevent( poller, &event, 1, NULL, 0, &ts );
ts.tv_sec = 3; // таймаут на 3 сек.
while( true ){
cout << "while(true) step: "<< step << endl;
while (1){
what = kevent( poller, NULL, 0, &result, 1, &ts );
cout << "what=" << what << " errno=" << errno << endl;
if ( what<0 ){
if ( errno==EINTR || errno==EAGAIN) continue;
PAssertAlways( strerror( errno ) );
}
break;
}
// до сих пор вроде как ясно...
// итак, получили событие.
if ( what == 1 ){
PAssertOS( (int) result.ident == sock );
cout << "Read... " << endl;
// прочитали сокет
retn = recv(sock, Buffer, 2048, 0);
cout << "retn=" << retn << endl;
if ( retn < 0 ){
// вот тут начинаются вопросы:
// если получаем retn=-1 и EAGAIN or EINTR, то что делать дальше? попытаться читать сокет еще раз, или продолжать ловить событие от kevent(), потом читать... короче по кругу.
if ( errno != EAGAIN || errno != EINTR){
retn = -1;
break;
}else{
// таки не прочитали сокет...
retn = str.GetLength();
break;
}
}else if ( retn > 0 ){
// успешно прочитали сокет
Buffer[retn]='\0';
str += (PString)Buffer;
}
//break;
}else if ( what == 0 ){
// нарвались на таймаут...
retn =- 1;
break;
}
step+=1;
}
PAssertOS( close( poller ) == 0 );
cout << retn <<"-------------------------------------------------\n\r"
<< Buffer
<< "\n\r-------------------------------------------------\n\r"
<< endl;
return retn;
}