Tsocket Bug

Davide
Posts: 190
Joined: Tue Mar 14, 2006 1:59 am
Location: Italy

Tsocket Bug

Post by Davide »

Hello all.

Small sample taken from senddata.prg:

Code: Select all | Expand

// Sockets use sample developed by Enrico M.G.#include "Fivewin.ch" FUNCTION MAIN()     LOCAL oWnd     DEFINE WINDOW oWnd     @ 1, 2 BUTTON "Send";            SIZE 100, 50;            ACTION SENDDATA( 25, "209.191.88.254")   // yahoo.com - Infinite loop//           ACTION SENDDATA( 25, "209.85.135.111") // smtp.gmail.com - This works good    ACTIVATE WINDOW oWnd RETURN NIL STATIC FUNCTION SENDDATA( nPort, cIP, cMsg )     LOCAL oSocket := TSocket():New( nPort )    oSocket:lDebug  :=.t.    oSocket:cLogFile:="senddata.log"    oSocket:bConnect := { || oSocket:GetData() , SysWait(1) , oSocket:SendData( "HELO TEST"+CRLF ), SysWait(1),;                             oSocket:GetData() , SysWait(1) , oSocket:SendData( "QUIT"+CRLF ), SysWait(1),;                             oSocket:GetData() , SysWait(1) , oSocket:End() }    oSocket:Connect( cIP ) RETURN NIL

When it's run through smtp.gmail.com you obtain a senddata.log file like follows:
04/19/10 02:23:14: Connect Socket handle: 340
04/19/10 02:23:14:
04/19/10 02:23:14: Write Socket handle: 340
04/19/10 02:23:14: Read Socket handle: 340
04/19/10 02:23:16: 220 mx.google.com ESMTP j10sm25406824mue.48
250 mx.google.com at your service

04/19/10 02:23:17: Read Socket handle: 340
04/19/10 02:23:17: Close Socket handle: 340
04/19/10 02:23:18: 221 2.0.0 closing connection j10sm25406824mue.48

While with yahoo.com ...
04/19/10 02:26:31: Connect Socket handle: 340
04/19/10 02:26:31:
04/19/10 02:26:32: Sent: -1 Len: 11 Buffer Len: 0 Error: 10057
04/19/10 02:26:32: Sent: -1 Len: 11 Buffer Len: 0 Error: 10057
04/19/10 02:26:32: Sent: -1 Len: 11 Buffer Len: 0 Error: 10057
04/19/10 02:26:32: Sent: -1 Len: 11 Buffer Len: 0 Error: 10057
04/19/10 02:26:32: Sent: -1 Len: 11 Buffer Len: 0 Error: 10057
... infinite

I tried manually telnetting the yahoo IP and it kindly reply me a couple of text lines stating that I'm disallowed because I'm on a residential/dynamic IP, then it puts the connection down, but that's not the problem (this is just a sample I made for you to understand the problem).
The problem is that looks like a WSA error in SendData() like the above puts tSocket in an infinite loop instead of retrieving those 2 lines of text, that are informative and helpful to know why the 10057 error was triggered, and then closing the socket.

How could I fix it ?

Thanks,
Davide
User avatar
Bayron
Posts: 815
Joined: Thu Dec 24, 2009 12:46 am
Location: Philadelphia, PA

Re: Tsocket Bug

Post by Bayron »

Davide,

Do you have a Yahoo Mail Plus account???

If you don't, that may be the problem......
=====>

Bayron Landaverry
(215)2226600 Philadelphia,PA, USA
+(502)46727275 Guatemala
MayaBuilders@gMail.com

FWH12.04||Harbour 3.2.0 (18754)||BCC6.5||UEstudio 10.10||
Windows 7 Ultimate

FiveWin, One line of code and it's done...
User avatar
xProgrammer
Posts: 464
Joined: Tue May 16, 2006 7:47 am
Location: Australia

Re: Tsocket Bug

Post by xProgrammer »

Hi Davide

At face value it looks like yahoo is dropping the connection (as per your telnet experience) and you pc keeps retrying the failed connection. Given your "success" with the gmail address it is less likely to be a "bug" in tsocket.

I have mainly done IP socket programming from[x]Harbour running on Linux, but I have successfully run sessions between Linux and Windows pcs. I know that I had to fiddle with timeouts and looping to get code that was working properly on Linux hosts to work on Windows hosts.

In case its of any use, here is the TSocket class that I am currently using:

Code: Select all | Expand

// Socket.prg#include "hbclass.ch"CLASS TSocket  CLASSDATA log_Initialised INIT .F.  DATA str_IPAddress  DATA int_PortNumber  DATA pSocket  DATA log_Connected  DATA str_Data  METHOD New() CONSTRUCTOR  METHOD SetIP( str_IPAddress )  METHOD SetPort( int_PortNumber )  METHOD CreateQueryObject()  METHOD Connect()  METHOD Send( cMessage )  METHOD Receive()  METHOD Close()  METHOD SendReceive( cMessage )  METHOD CleanUp()ENDCLASSMETHOD New() CLASS TSocket  ::str_IPAddress := "127.0.0.1"  ::int_PortNumber := 1800  IF !::log_Initialised     INetInit()     ::log_Initialised := .T.  ENDIF  RETURN selfMETHOD SetIP( str_IPAddress ) CLASS TSocket  ::str_IPAddress := AllTrim( str_IPAddress )  RETURN nilMETHOD SetPort( int_PortNumber ) CLASS TSocket  ::int_PortNumber := int_PortNumber  RETURN nilMETHOD CreateQueryObject()  RETURN( TQuery():New( self ) )METHOD Connect() CLASS TSocket  LOCAL log_OK  LOCAL log_Retry  log_Retry := .T.  DO WHILE log_Retry    log_OK := .T.    TRY      ::pSocket := INetConnect( ::str_IPAddress, ::int_PortNumber )    CATCH      MsgInfo( "Unable to connect to data server" )      log_OK := .F.    END    IF log_OK      IF INetErrorCode( ::pSocket ) == 0        ::log_Connected := .T.        RETURN .T.       ELSE        ? "Socket error:", INetErrorDesc( ::pSocket )      ENDIF    ENDIF    log_OK := .F.    ::log_Connected := .F.    // ? "Press [Esc] to exit, [Enter] to retry"    // IF InKey( 0 ) == 27    IF !MsgYesNo( "Can't communicate with the server. Do you want to retry?", "Communication Error" )       INetCleanUp()      log_OK := .F.      ProgExit()    ENDIF  ENDDOMETHOD Send( var_Message ) CLASS TSocket  INetSend( ::pSocket, var_Message )  RETURN nilMETHOD Receive() CLASS TSocket  LOCAL str_Buffer  LOCAL int_Bytes  INetSetTimeOut( ::pSocket, 1000 )  ::str_Data := ""  int_Bytes := 1  DO WHILE int_Bytes > 0    ? "in loop"    str_Buffer := Space( 1024 )    int_Bytes := INetRecv( ::pSocket, @str_Buffer )    ? int_Bytes    ::str_Data += Left( str_Buffer, int_Bytes )  ENDDO  RETURN nilMETHOD Close() CLASS TSocket  INetClose( ::pSocket )  RETURN nilMETHOD SendReceive( cMessage ) CLASS TSocket  ::Send( cMessage )  ::Receive()  ::Close()  RETURN ::cDataMETHOD CleanUp() CLASS TSocket  RETURN InetCleanUp() 
Davide
Posts: 190
Joined: Tue Mar 14, 2006 1:59 am
Location: Italy

Re: Tsocket Bug

Post by Davide »

Thank you guys for your replies.
Bayron wrote:Do you have a Yahoo Mail Plus account???

No, but I don't need to necessarily connect to that yahoo server. That was just an example to show the problem.
xProgrammer wrote:At face value it looks like yahoo is dropping the connection (as per your telnet experience) and you pc keeps retrying the failed connection. Given your "success" with the gmail address it is less likely to be a "bug" in tsocket.

The Google sample works good because that server doesn't drop the connection down, but replies as expected.
The Yahoo sample doesn't work because tSocket.prg doesn't correctly handle the 10057 WSA error.

Thank you for posting your class, but tSocket is used by other classes, like tSmtp, tWebClient, etc. so I need to fix the original one shipped with FWH because in reality this is causing me trouble on other classes, when the remote server closes the connection unexpectedly (for many reasons; not necessarily the reason in this sample).

Thanks,
Davide
Davide
Posts: 190
Joined: Tue Mar 14, 2006 1:59 am
Location: Italy

Re: Tsocket Bug

Post by Davide »

ok, this solves the endless loop (and even a problem with WSAGetLastError() that's called twice if logging is enabled):

Code: Select all | Expand

METHOD SendData( cData ) CLASS TSocket   local nSize := Len( cData )   local nLen  := nSize   local nSent := 0   local nError:= 0   if ! ::lSending      ::lSending = .t.   else      AAdd( ::aBuffer, cData )      return nSize   endif   while ( nLen > 0 .and. ;           ( nSent := SocketSend( ::nSocket, cData ) ) < nLen ) .or. ;      Len( ::aBuffer ) > 0      if ::lDebug .and. ! Empty( ::cLogFile )         nError:=WSAGetLastError()         LogFile( ::cLogFile, { "Sent:", nSent, "Len:", Len( cData ), "Buffer Len:", Len( ::aBuffer ), "Error:", nError } )      endif      // Check for buffered packets to send      if nLen == 0 .and. Len( ::aBuffer ) > 0         cData = ::aBuffer[ 1 ]         ADel( ::aBuffer, 1 )         ASize( ::aBuffer, Len( ::aBuffer ) - 1 )      endif      if nSent != -1         cData = SubStr( cData, nSent + 1 )         nLen  = Len( cData )      else         if WSAGetLastError() != WSAEWOULDBLOCK            // exit         endif        if !(::lDebug .and. ! Empty( ::cLogFile )) ; nError:=WSAGetLastError() ; Endif  // *GD* Cannot do it twice        if nError = 10057                 // WSAENOTCONN  *GD* 21.04.2010          cData:="" ; nSize:=0 ; exit // ::lSending:=.f. ; ::End()        endif      endif      SysRefresh()   end   // if ::lDebug .and. ! Empty( ::cLogFile )   //    LogFile( ::cLogFile, { cData } )   // endif   ::lSending = .f.return nSize 

however, I found out that the source of the problem is before this point.
Method ConnectTo() doesn't detect the dropdown and returns a 10060 WSA Error just when the Timeout expires.

Any chance to have ConnectTo() acting like the Terminal Emulator (retrieving the server's reply and returning immediately) ?

Thanks,
Davide
Horizon
Posts: 1326
Joined: Fri May 23, 2008 1:33 pm
Has thanked: 5 times

Re: Tsocket Bug

Post by Horizon »

Hi Davide,

Can you solve this problem?

I have 11.01. When I try to run SockCli.prg as an example without running SockSer.prg, Tsocket runs to bConnect. I think it should say can not connected.

Thanks,
Regards,

Hakan ONEMLI

Harbour & MSVC 2022 & FWH 23.04
Davide
Posts: 190
Joined: Tue Mar 14, 2006 1:59 am
Location: Italy

Re: Tsocket Bug

Post by Davide »

Dear Hakan,
Horizon wrote:I have 11.01. When I try to run SockCli.prg as an example without running SockSer.prg, Tsocket runs to bConnect. I think it should say can not connected.

unfortunately I never solved the problem above, and I'm still on 9.05

Hi,
Davide
Horizon
Posts: 1326
Joined: Fri May 23, 2008 1:33 pm
Has thanked: 5 times

Re: Tsocket Bug

Post by Horizon »

Daniel,

Can you help us?
Regards,

Hakan ONEMLI

Harbour & MSVC 2022 & FWH 23.04
User avatar
Daniel Garcia-Gil
Posts: 2365
Joined: Wed Nov 02, 2005 11:46 pm
Location: Isla de Margarita
Contact:

Re: Tsocket Bug

Post by Daniel Garcia-Gil »

Hello

yes, sure...

can you post a little sample?

or the sample in first post is enough?
our best documentation is the source code
Isla de Margarita Venezuela.
danielgarciagil@gmail.com
http://tdolphin.blogspot.com/
https://www.dropbox.com/referrals/NTI5N ... rc=global9
Horizon
Posts: 1326
Joined: Fri May 23, 2008 1:33 pm
Has thanked: 5 times

Re: Tsocket Bug

Post by Horizon »

Hi Daniel,

I use standart SockCli.prg and SockSer.prg's as an example.

My main problem is connect method. My scenario is like below.

SockSer.prg is not running. There is not any Socket server as I know. I use standart port 2000 and use 127.0.0.1 as IP. (I have tried several unknown ip)

I run SockCli.prg and connect. The bConnect block is evaluated, but the return value of connect method is -1. It is not connected. so if you call senddata method after that, the unexpected errors occur. The socket thinks connection is establish. but there is no connection.

if the senddata method is used in this situation, it gives an error. if the logfile is used, logfile is grow and grow. (Davide explained this above messages)

I think the other problem is checking the connection is established or not.
Regards,

Hakan ONEMLI

Harbour & MSVC 2022 & FWH 23.04
User avatar
Daniel Garcia-Gil
Posts: 2365
Joined: Wed Nov 02, 2005 11:46 pm
Location: Isla de Margarita
Contact:

Re: Tsocket Bug

Post by Daniel Garcia-Gil »

Hello

i tested sockserv.prg and sockcli.prg and run fine

from samples folder
Download: http://www.sitasoft.net/fivewin/samples/testsock.zip
sockserv.prg

Code: Select all | Expand

// Socket server connection sample#include "FiveWin.ch"#define ST_COMMAND  1#define ST_SENDFILE 2#define FILE_BLOCK 8000static oWnd, oSocket, oClient//------------------------------------------------------------------------//function Main()   local oBar   DEFINE WINDOW oWnd TITLE "Server socket"   DEFINE BUTTONBAR oBar OF oWnd _3D   DEFINE BUTTON OF oBar ACTION Server() TOOLTIP "Listen"   DEFINE BUTTON OF oBar ACTION oClient:SendData( "Hello from server!" ) TOOLTIP "Talk to client"   ACTIVATE WINDOW oWndreturn nil//------------------------------------------------------------------------//function Server()   oSocket = TSocket():New( 2000 )   oSocket:bAccept = { | oSocket | oClient := TSocket():Accept( oSocket:nSocket ),;                       oClient:Cargo := ST_COMMAND,;                       oClient:bRead := { | oSocket | OnRead( oSocket ) },;                       oClient:bClose := { | oSocket | OnClose( oSocket ) } }   oSocket:Listen()return nil//------------------------------------------------------------------------//function OnRead( oSocket )   local cData := oSocket:GetData()   local cToken   LogFile( "sockserv.txt", { Len( cData ), cData } )   do case      case oSocket:Cargo == ST_COMMAND           cToken = StrToken( cData, 1 )           do case              case cToken == "SENDFILE"                   oSocket:Cargo = ST_SENDFILE                   oSocket:hFile = fcreate( StrToken( cData, 2 ) )              case cToken == "MSG"                   MsgInfo( SubStr( cData, 5 ) )           endcase      case oSocket:Cargo == ST_SENDFILE           fwrite( oSocket:hFile, cData, Len( cData ) )           LogFile( "sockserv.txt", { "writting..." } )           if Len( cData ) < FILE_BLOCK              // fclose( oSocket:hFile )              // MsgInfo( Len( cData ) )              // oSocket:Cargo = ST_COMMAND           endif   endcasereturn nil//------------------------------------------------------------------------//function OnClose( oSocket )   MsgInfo( "Client has closed!" )   do case      case oSocket:Cargo == ST_SENDFILE           fclose( oSocket:hFile )   endcase   oSocket:End()return nil//------------------------------------------------------------------------// 



sockcli.prg

Code: Select all | Expand

// Socket server connection sample#include "FiveWin.ch"static oWnd, oSocketfunction Main()   local oBar   DEFINE WINDOW oWnd TITLE "Client socket"   DEFINE BUTTONBAR oBar OF oWnd _3D   DEFINE BUTTON OF oBar ACTION Client() TOOLTIP "Connect"   DEFINE BUTTON OF oBar ;      ACTION oSocket:SendData( "MSG This is a test" ) ;      TOOLTIP "Send data"         DEFINE BUTTON OF oBar ;      ACTION SendFile() TOOLTIP "Send file"   ACTIVATE WINDOW oWndreturn nilfunction Client()   oSocket = TSocket():New( 2000 )   oSocket:bRead    = { | oSocket | MsgInfo( oSocket:GetData() ) }   // Never use a MsgInfo() here because it hangs Windows!!!   oSocket:bConnect = { || oWnd:SetText( "Connected!" ) }   oSocket:bClose   = { || MsgInfo( "Server has closed!" ) }   oSocket:Connect( "127.0.0.1" ) // use the server IP address herereturn nilfunction SendFile()   local cFileName := cGetFile( "*.*", "Select a file to send by Internet" )   if ! Empty( cFileName ) .and. File( cFileName )      oSocket:SendData( "SENDFILE " + cFileName( cFileName ) )      oSocket:SendFile( cFileName )      MsgInfo( "File sent" )   endifreturn nil 
our best documentation is the source code
Isla de Margarita Venezuela.
danielgarciagil@gmail.com
http://tdolphin.blogspot.com/
https://www.dropbox.com/referrals/NTI5N ... rc=global9
Horizon
Posts: 1326
Joined: Fri May 23, 2008 1:33 pm
Has thanked: 5 times

Re: Tsocket Bug

Post by Horizon »

Hi Daniel,

I have tested your sockcli.exe in my computers. All of my computers says Connected, when I press connect button. There is no working socket server.
Regards,

Hakan ONEMLI

Harbour & MSVC 2022 & FWH 23.04
User avatar
Daniel Garcia-Gil
Posts: 2365
Joined: Wed Nov 02, 2005 11:46 pm
Location: Isla de Margarita
Contact:

Re: Tsocket Bug

Post by Daniel Garcia-Gil »

Hello...

can you contact with me by msn (danielgarciagil@cantv.net) or gmail chat (danielgarciagil@gmail.com) or other way? for test
our best documentation is the source code
Isla de Margarita Venezuela.
danielgarciagil@gmail.com
http://tdolphin.blogspot.com/
https://www.dropbox.com/referrals/NTI5N ... rc=global9
User avatar
Daniel Garcia-Gil
Posts: 2365
Joined: Wed Nov 02, 2005 11:46 pm
Location: Isla de Margarita
Contact:

Re: Tsocket Bug

Post by Daniel Garcia-Gil »

Horizon

i'll explain...

it isn't a bug... is a behavior of windows socket...

when we connected to socket, we are open a port to send and receive data, it's no a direct link to a server, the ip address is only the "path" between client and server...
we dont know if the server accept the connection until them notify us, i didn't found a message send by server to notify "connection accepted"

With a nonblocking socket, the connection attempt cannot be completed immediately. In this case, connect will return SOCKET_ERROR, and WSAGetLastError will return WSAEWOULDBLOCK. ( you can call WSAGetLastError after connect, will see )

try with this new sockcli.prg / socksrv.prg

look oSocket:bAccept ... i sent "ok" to notify the client the connection is accepted, other way the client no show "connected" only show "port opened"

Code: Select all | Expand

// Socket server connection sample#include "FiveWin.ch"#define ST_COMMAND  1#define ST_SENDFILE 2#define FILE_BLOCK 8000static oWnd, oSocket, oClient//------------------------------------------------------------------------//function Main()   local oBar   DEFINE WINDOW oWnd TITLE "Server socket"   DEFINE BUTTONBAR oBar OF oWnd _3D   DEFINE BUTTON OF oBar ACTION Server() TOOLTIP "Listen"   DEFINE BUTTON OF oBar ACTION oClient:SendData( "Hello from server!" ) TOOLTIP "Talk to client"   ACTIVATE WINDOW oWndreturn nil//------------------------------------------------------------------------//function Server()   oSocket = TSocket():New( 5000 )   oSocket:bAccept = { | oSocket | oClient := TSocket():Accept( oSocket:nSocket ),;                       oClient:Cargo := ST_COMMAND,;                       oClient:bRead := { | oSocket | OnRead( oSocket ) },;                       oClient:bClose := { | oSocket | OnClose( oSocket ) },;                       oClient:SendData( "ok" ),;                       MsgInfo( "accepted" ) }   oSocket:Listen()return nil//------------------------------------------------------------------------//function OnRead( oSocket )   local cData := oSocket:GetData()   local cToken   LogFile( "sockserv.txt", { Len( cData ), cData } )   do case      case oSocket:Cargo == ST_COMMAND           cToken = StrToken( cData, 1 )           do case              case cToken == "SENDFILE"                   oSocket:Cargo = ST_SENDFILE                   oSocket:hFile = fcreate( StrToken( cData, 2 ) )              case cToken == "MSG"                   MsgInfo( SubStr( cData, 5 ) )           endcase      case oSocket:Cargo == ST_SENDFILE           fwrite( oSocket:hFile, cData, Len( cData ) )           LogFile( "sockserv.txt", { "writting..." } )           if Len( cData ) < FILE_BLOCK              // fclose( oSocket:hFile )              // MsgInfo( Len( cData ) )              // oSocket:Cargo = ST_COMMAND           endif   endcasereturn nil//------------------------------------------------------------------------//function OnClose( oSocket )   MsgInfo( "Client has closed!" )   do case      case oSocket:Cargo == ST_SENDFILE           fclose( oSocket:hFile )   endcase   oSocket:End()return nil//------------------------------------------------------------------------// 


Code: Select all | Expand

// Socket server connection sample#include "FiveWin.ch"static oWnd, oSocketfunction Main()   local oBar   DEFINE WINDOW oWnd TITLE "Client socket"   DEFINE BUTTONBAR oBar OF oWnd _3D   DEFINE BUTTON OF oBar ACTION Client() TOOLTIP "Connect"       DEFINE BUTTON OF oBar ;      ACTION oSocket:SendData( "MSG This is a test" ) ;      TOOLTIP "Send data"         DEFINE BUTTON OF oBar ;      ACTION SendFile() TOOLTIP "Send file"   ACTIVATE WINDOW oWndreturn nilfunction Client()      if oSocket != NIL      oSocket:End()   endif   oSocket = TSocket():New( 5000 )   oSocket:bRead    = { | oSocket | HandleRecived( oSocket, oWnd ) }   // Never use a MsgInfo() here because it hangs Windows!!!   oSocket:bConnect = { || oWnd:SetText( "Socked Opened!" ) }   oSocket:bClose   = { || MsgInfo( "Server has closed!" ) }      oSocket:Connect( "127.0.0.1" )   MsgInfo( WSAGetLastError() )   return nilfunction SendFile()   local cFileName := cGetFile( "*.*", "Select a file to send by Internet" )   if ! Empty( cFileName ) .and. File( cFileName )      oSocket:SendData( "SENDFILE " + cFileName( cFileName ) )      oSocket:SendFile( cFileName )      MsgInfo( "File sent" )   endifreturn nilfunction HandleRecived( oSocket, oWnd )   local cData := oSocket:GetData()         if cData = "ok"      oWnd:SetText( "Connected!!" )   else       MsgInfo( cData )   endifreturn nil 
our best documentation is the source code
Isla de Margarita Venezuela.
danielgarciagil@gmail.com
http://tdolphin.blogspot.com/
https://www.dropbox.com/referrals/NTI5N ... rc=global9
Horizon
Posts: 1326
Joined: Fri May 23, 2008 1:33 pm
Has thanked: 5 times

Re: Tsocket Bug

Post by Horizon »

Thank you very much Daniel.

There is a help in Fivewin Function about ConnectTo like that.


ConnectTo( <nSocket>, <nPort>, <cIPAddr ) --> nRetCode

<nRetCode> Zero if successful, otherwise SOCKET_ERROR.

unfortunately, it does not work. It returns always -1.
Regards,

Hakan ONEMLI

Harbour & MSVC 2022 & FWH 23.04
Post Reply