Newsgroup: it.comp.lang.delphi
Titolo: Errore TcpServer-TcpClient: non me ne capacito...

Ciao a tutti!
Stavo facendo alcune prove con i componenti in oggetto e ho notato un 
comportamento anomalo. Visto che non sono riuscito a capire perchè tutto 
questo accadeva, vi sottopongo il problema nella speranza che mi possiate 
aiutare...
In una Form vuota, piazzo un componente TTcpServer e setto LocalHost a 
'localhost' (come si vedrà in seguito questo dato non è necessario) e 
LocalPort a 2000 (abbondantemente sopra le porte riservate).
Sulla Form piazzo anche un TCheckBox, associo al suo evento OnClick il 
seguente codice:
  if CheckBox1.Checked then
    TcpServer1.Open
  else
    TcpServer1.Close;
in modo che spuntando la casella si avvii il server e vuotandola lo si 
arresti.
Piazzo ora nella Form un componente TTcpClient e setto RemoteHost a 
'localhost' e RemotePort a 2000, in accordo con i dati del TTcpServer già 
introdotto. Piazzo una TLabel sulla Form ed associo all'evento OnError del 
TTcpClient il seguente codice:
  Label3.Caption := 'socket error #' + IntToStr (SocketError);
Piazzo un'altra TCheckBox ed associo il seguente codice al suo evento 
OnClick:
  Label3.Caption := 'error resetted';
  if CheckBox2.Checked then
    TcpClient1.Open
  else
    TcpClient1.Close;
cioè esattamente come per il TTcpServer, con l'aggiunta della prima riga che 
resetta il contenuto della stringa adibita a mostrare i messaggi d'errore 
del TTcpClient ogni volta che si apre/chiude una connessione utilizzando 
proprio questo componente.
Prima di eseguire l'applicazione, aggiungo altre due TLabel alla Form ed un 
TTimer. Associo questo codice all'evento OnTimer del TTimer:
  if TcpServer1.Active then
    Label1.Caption := TcpServer1.LocalHost + ':' + TcpServer1.LocalPort
  else
    Label1.Caption := 'server not working';
  if TcpClient1.Active then
    Label2.Caption := TcpClient1.LocalHost + ':' + TcpClient1.LocalPort + ' 
hooked to ' + TcpClient1.RemoteHost + ':' + TcpClient1.RemotePort
  else
    Label2.Caption := 'client not working';
in modo da avere un minimo di informazione sullo stato dei componenti 
TTcpServer e TTcpClient durante l'esecuzione.
Eseguo la prima volta... appena partito le ultime due TLabel introdotte 
dichiarano che sia il server che il client non funzionano. Se provo ad 
attivare il client prima di aver attivato il server, ottengo l'errore #10061 
(che non so cosa voglia dire esattamente, ma immagino che voglia dire 
'server non esistente' o simili).
A questo punto ridisattivo il client, attivo il server e riattivo il client: 
nessun messaggio d'errore, la connessione è stata stabilita correttamente!
Sfortunatamente, sia il client che il server sono settati all'avvio su 
connessioni di tipo Blocking, cioè sincrone. A me interessa avere una unica 
connessione asincrona tra questo client e questo server e quindi chiudo 
l'applicazione a runtime e torno a designtime dove setto la proprietà 
BlockMode del server e del client su bmNonBlocking. Rieseguo l'applicazione 
e scopro con orrore che ogni volta che tento la connessione con server (non 
cambia nulla se questo è funzionante o no) ottengo l'errore socket #10035 
(che non so cosa voglia dire e di cui non sono riuscito ad immaginare il 
significato).
Ho provato tutte le combinazioni possibili dei valori BlockMode del client e 
del server ottenendo sempre lo stesso risultato (a parte il caso descritto 
all'inizio, ottengo sempre l'errore #10035).
Preso da scrupolo cancello il valore 'localohost' dalla proprietà LocalHost 
del TTcpServer (che nell'help si dice di settare solo LocalPort) e rieseguo: 
il firewall di Windows XP sente che potenzialmente possono giungere 
connessioni dall'esterno e mi chiede se voglio sbloccare l'applicazione 
(prima non lo aveva chiesto): lo faccio, ma ottengo sempre la stessa 
casistica d'errore che ho descritto sopra... provo allora a modificare la 
proprietà RemoteHost da localohost alla stringa corrispondente al mio IP. 
Nessuna variazione nel risultato.
Che cosa sbaglio? Le connessioni asincrone esistono, delphi le supporta ed 
anche i due componenti di cui sopra le supportano altrimenti non si 
spiegherebbe la presenza delle proprietà BlockMode nei componenti... Magari 
sapendo cosa significa l'erorre #10035...
Insomma, aspetto un vostro aiuto perchè mi sa che io da solo non ci salto 
fuori!!!
Ciao,
   Stefano 

Il LocalHost di un Server non e' necessario in quanto nel Bind il Socket usa
sempre INADDR_ANY cioe' l'IP della macchina stessa.
Il Client RemoteHost impostalo esplicitamente all'IP della macchina e la
RemotePort=LocalPort del Server .
Se non avvii il Server prima che il Client chieda la connessione e' normale
l'errore.
Pe quanto riguarda il passare da un sock bloccante, piu' semplice da
implementare, ad uno non bloccante comporta anche la registrazione degli
eventi che desideri gestire, senza cio' ti  verra' di continuo restituito
quell'errore che ottieni.
La funzione WinSock.WSAAsyncSelect(FSocket, Handle, WM_SOCK, Ev); permette
di impostare gli eventi da ricevere: es. l'ACCEPT, il CONNECT, ecc.
Se non trovi queste essenziali funzioni puo' essere che l'implementazione
che usi sia nata esclusivamente per funzionare in modo bloccante.
Sotto riporto l'elenco degli ERRORI SOCKET, se qualcuno lo sa mettere nei
Tips della lista mi farebbe un favore.
WSABASEERR=10000;
   Case Value Of
      WSABASEERR+4 : Result := 'WSAEINTR';
      WSABASEERR+9 : Result := 'WSAEBADF';
      WSABASEERR+13 : Result := 'WSAEACCES';
      WSABASEERR+14 : Result := 'WSAEFAULT';
      WSABASEERR+22 : Result := 'WSAEINVAL';
      WSABASEERR+24 : Result := 'WSAEMFILE';
      WSABASEERR+35 : Result := 'WSAEWOULDBLOCK';
      WSABASEERR+36 : Result := 'WSAEINPROGRESS';
      WSABASEERR+37 : Result := 'WSAEALREADY';
      WSABASEERR+38 : Result := 'WSAENOTSOCK';
      WSABASEERR+39 : Result := 'WSAEDESTADDRREQ';
      WSABASEERR+40 : Result := 'WSAEMSGSIZE';
      WSABASEERR+41 : Result := 'WSAEPROTOTYPE';
      WSABASEERR+42 : Result := 'WSAENOPROTOOPT';
    WSABASEERR+43 : Result := 'WSAEPROTONOSUPPORT';
      WSABASEERR+44 : Result := 'WSAESOCKTNOSUPPORT';
      WSABASEERR+45 : Result := 'WSAEOPNOTSUPP';
      WSABASEERR+46 : Result := 'WSAEPFNOSUPPORT';
      WSABASEERR+47 : Result := 'WSAEAFNOSUPPORT';
      WSABASEERR+48 : Result := 'WSAEADDRINUSE';
      WSABASEERR+49 : Result := 'WSAEADDRNOTAVAIL';
    WSABASEERR+50 : Result := 'WSAENETDOWN';
      WSABASEERR+51 : Result := 'WSAENETUNREACH';
      WSABASEERR+52 : Result := 'WSAENETRESET';
      WSABASEERR+53 : Result := 'WSAECONNABORTED';
      WSABASEERR+54 : Result := 'WSAECONNRESET';
      WSABASEERR+55 : Result := 'WSAENOBUFS';
      WSABASEERR+56 : Result := 'WSAEISCONN';
    WSABASEERR+57 : Result := 'WSAENOTCONN';
      WSABASEERR+58 : Result := 'WSAESHUTDOWN';
      WSABASEERR+59 : Result := 'WSAETOOMANYREFS';
      WSABASEERR+60 : Result := 'WSAETIMEDOUT';
      WSABASEERR+61 : Result := 'WSAECONNREFUSED';
      WSABASEERR+62 : Result := 'WSAELOOP';
      WSABASEERR+63 : Result := 'WSAENAMETOOLONG';
      WSABASEERR+64 : Result := 'WSAEHOSTDOWN';
      WSABASEERR+65 : Result := 'WSAEHOSTUNREACH';
      WSABASEERR+66 : Result := 'WSAENOTEMPTY';
      WSABASEERR+67 : Result := 'WSAEPROCLIM';
      WSABASEERR+68 : Result := 'WSAEUSERS';
      WSABASEERR+69 : Result := 'WSAEDQUOT';
      WSABASEERR+70 : Result := 'WSAESTALE';
    WSABASEERR+71 : Result := 'WSAEREMOTE';
      WSABASEERR+91 : Result := 'WSASYSNOTREADY';
      WSABASEERR+92 : Result := 'WSAVERNOTSUPPORTED';
      WSABASEERR+93 : Result := 'WSANOTINITIALISED';
      WSABASEERR+101 : Result := 'WSAEDISCON';
      WSABASEERR+1001 : Result := 'WSAHOST_NOT_FOUND';
      WSABASEERR+1002 : Result := 'WSATRY_AGAIN';
      WSABASEERR+1003 : Result := 'WSANO_RECOVERY';
      WSABASEERR+1004 : Result := 'WSANO_DATA';
Giorgio Padoan

 Tips della lista mi farebbe un favore.
Ottimo lavoro Giorgio. :-)
-- 
Morde. 
M-List di icld: 
http://it.groups.yahoo.com/group/icld/