Win32 Pop3 Client

Pagina: 1
Acties:

  • eborn
  • Registratie: April 2000
  • Laatst online: 12-09 13:59
Ik ben bezig met een Win32 Pop3 client. Hiervoor gebruik ik sockets. Alles gaat prima (connect, inloggen). Maar zodra ik een STAT doe om te kijken wat er op de server staat krijg ik niets terug. Hoe kan dit? Ik gebruik het volgende stukje code:

sprintf( buf, "STAT\r\n" );
if ( send ( sock, buf, strlen(buf)+1, 0 ) == SOCKET_ERROR )
{
ShowError( NULL, "Fout\n" );
return false;
}
memset ( buf, 0, 256 );
if ( recv ( sock, buf, 256, 0 ) == SOCKET_ERROR )
{
ShowError( NULL, "Fout\n" );
return false;
}
if( strncmp( buf, "+OK", 3 ) == 0 )
{
ShowError( NULL, (CString)"Resultaat: " + buf );
}

Kan dit zo wel? Of moet ik als het ware wachten totdat er iets te ontvangen ís?

Graag wat hulp!

Verwijderd

Misschien interessant om eerst de sessie met telnet uit te voeren, zie je precies wanneer er wat binnen komt, wanneer je moet wachten en waarop enzo.
Als STAT je met telnet lukt is het niet meer zo moeilijk om het in je programeertaal voor elkaar te krijgen...

  • eborn
  • Registratie: April 2000
  • Laatst online: 12-09 13:59
STAT in telnet werkt dus ook wel (net als alle andere commando's. En in de C++ code krijg ik ook geen foutmelding terug. Er komt alleen ook geen reactie, alleen een lege buffer. Maar zou het kunnen zijn dat het programma te snel is en dat hij nog eventjes moet wachten voor hij de server om reactie moet vragen?

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Met de select-functie kun je het systeem laten blocken totdat er data beschikbaar is op een of meerdere sockets uit een gegeven selectie.

Overigens, als recv inderdaad een lege buffer teruggeeft:

If no error occurs, recv returns the number of bytes received. If the connection has been gracefully closed, the return value is zero. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError.

Lijkt er dus eerder op dat het inloggen toch niet zo goed gelukt is, want een 'graceful close' in dit geval betekent botweg dat de server je vriendelijk buitengeknikkerd heeft ;)

ps. die docs hierboven komen uit de WinSock documentatie maar die implementatie is transparant voor alle Berkeley socket-uitvoeringen en dus ook geldig voor Linux/Unix. Alleen die WSAGetLastError moet je dan iets anders voor doen :)

Professionele website nodig?


  • eborn
  • Registratie: April 2000
  • Laatst online: 12-09 13:59
bedankt voor de tip! ik ga het meteen uitproberen!

oh, en de server laat me wel toe, want ik krijg op het USER en het PASS commando een +OK terug.

  • eborn
  • Registratie: April 2000
  • Laatst online: 12-09 13:59
werkt helaas nog niet. De select geeft de controle meteen terug aan de functie. Dus volgens heb staat er data te wachten (of gaat de recv functie niet blocken)

Dit is mijn extra stukje code:

// Wacht op een respons
fd_set rset;
FD_SET( sock, &rset );
timeval tv;
tv.tv_sec = 3;
tv.tv_usec = 0;

if( select( 0, &rset, NULL, NULL, &tv ) == 0 )
{
dlg->setItemStatus( "Timeout" );
goto pop3_quit;
}

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Op zondag 06 januari 2002 01:09 schreef eborn het volgende:
werkt helaas nog niet. De select geeft de controle meteen terug aan de functie. Dus volgens heb staat er data te wachten (of gaat de recv functie niet blocken)
Een graceful disconnect doet select ook meteen terugvallen... je bent er echt uitgekicked hoor.

Professionele website nodig?


  • eborn
  • Registratie: April 2000
  • Laatst online: 12-09 13:59
Ja, maar hoe kan dat dan? Want ik doe het meteen nadat ik heb teruggekregen:

+OK Name is valid mailbox
en
+OK Maildrop locked and ready

Trouwens, om de een of andere onverklaarbare wijze blijft select nu ook de 3 seconden hangen en geeft dus een timeout waarschuwing. Ik snap er allemaal niets meer van. Waarom is dit nou zo ingewikkeld?

  • eborn
  • Registratie: April 2000
  • Laatst online: 12-09 13:59
Ik heb hier trouwens een voorbeeld aan een asynchroon werkend programma en dat werkt wel. Maar het hoort synchroon ook te werken.

  • elevator
  • Registratie: December 2001
  • Niet online

elevator

Officieel moto fan :)

Op zondag 06 januari 2002 01:35 schreef eborn het volgende:
Ik heb hier trouwens een voorbeeld aan een asynchroon werkend programma en dat werkt wel. Maar het hoort synchroon ook te werken.
is dit een blocking of niet blocking socket? wat krijg je terug als je de errorcode op vraagt (WsaGetLastError() oid)?

Als je een send() uitvoert (willekeurig iets), en daarna de error opvraagt welke error krijg je dan terug?

  • eborn
  • Registratie: April 2000
  • Laatst online: 12-09 13:59
Er is geen errorcode: WSAGetLastError() == 0

Verwijderd

Probeer eens een loopje te maken die twee dingen doet:
- Checken of er iets binnen komt (lengte buffer > 0)
- Checken of de connectie er niet onder vandaan gedonderd is

en dat natuurlijk gedurende een bepaalde timeout (60 secs moet wel kunnen denk ik ;))

even in pragma-code (hou niet van taal-afhankelijkheid)

buf = readBuf();
while (size(buf) < 0 AND connection_up) {
buf = readBuf();
}

if (connection_up)
{
do stuff with buf
}
else {
generate error msg, act accordingly
}

dit use ik zelf als communicatie-constructie in mijn eigen java smtp/pop3/imap server :)

Soon-to-come as open-source progje, einde sluikreclame ;-)

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Op zondag 06 januari 2002 01:51 schreef eborn het volgende:
Er is geen errorcode: WSAGetLastError() == 0
Dan heb je denk ik inderdaad zoals elevator suggereert per ongeluk een non-blocking socket gemaakt... eigenlijk het enige wat nog kan.

Heb je de code helemaal zelf geschreven of deels 'geleend'?

Staat er ergens iets in de richting van:
code:
1
2
3
BOOL value = TRUE;

ioctlsocket(sock, FIONBIO, &value);

Als je er echt niet uitkomt mail de code maar ff door, zal ik wel eens proberen.

Professionele website nodig?


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Ik zie trouwens net het volgende regeltje in je code:
code:
1
ShowError( NULL, (CString)"Resultaat: " + buf );

Waarom gebruik je wel de MFC string class en niet de MFC socket classes? :?

Professionele website nodig?


  • elevator
  • Registratie: December 2001
  • Niet online

elevator

Officieel moto fan :)

Op zondag 06 januari 2002 02:43 schreef curry684 het volgende:

[..]

Dan heb je denk ik inderdaad zoals elevator suggereert per ongeluk een non-blocking socket gemaakt... eigenlijk het enige wat nog kan.
als het een non-blocking socket is, en de recv() geeft 0 terug, moet de WsaGetLastError() een WSAEWOULDBLOCK (oid) terug geven.. Dat doet hij schijnbaar ook niet.

Wat ik doe in mijn TCP clients, is ik zet de socket as non-blocking, en heb een functie (Delphi) als dergelijk:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function tTcpClient.GetConnection: Boolean;
var TempCH     : Char;
    Returncode : longint;
    TempError  : longint;
begin
  if NOT HaveConnection then
    begin
    Result := false;
    EXIT;
    end; { if }

  Result := true;
  ReturnCode := SockRecv(SockHandle, @TempCH, SizeOf(TempCH), MSG_PEEK);
  TempError := WsaGetLastError;


  if ((TempError <> WSAEWOULDBLOCK) AND (TempError <> 00)) OR (ReturnCode=0) then
    begin
    Result := false;
    HaveConnection := false;
    end; { if }
end; { func. GetConnection }

als zowel de recv() 0 terug geeft, en de WsaGetLastError() geeft 0 terug, misschien eens een simpele:
code:
1
sleep(3000);  // of de 'c' variant

proberen?
Pagina: 1