//  Xb2.NET sample showing how to create a simple Telnet server
    //------------------------------------------------------------------------------------
    
    #include "xb2net.ch"
    #include "common.ch"
    #include "xbp.ch"
    
    #pragma  library ("xb2net.lib")
    
    #define CRLF            (Chr(13)+Chr(10))
    #xtranslate NTrim()   =>  LTrim(Str())
    
    
    procedure Main()
       Local nKey, cKey, oServer
    
       // start server on port 23 (the standard Telnet port)
       oServer := xbServer():new( INADDR_ANY, 23 )
    
       if oServer:ErrorCode > 0
          MsgBox("Unable to start server!" + chr(10) +;
                 "Error code: " + LTrim(Str(oServer:ErrorCode)) + " (" + oServer:ErrorText(oServer:ErrorCode) + ")" )
          Return
       endif
    
       // this is the codeblock that will be evaluated when a client connection is accepted
       oServer:onConnect := {||ServiceClient()}
    
       // start the server in it's own thread
       oServer:start()
    
       SetPos(MaxRow(),0)
       ? "Server started on host:", oServer:LocalName, ", Thread:", NTrim(oServer:ThreadID) + ", At:",  oServer:DateStarted, NTrim(oServer:TimeStarted), "Sec."
       ?
    
       while .t.
          nKey := inkey(0.2)
          cKey := Upper(chr(nKey))
    
          do case
          case nKey == 27
             if ConfirmBox(nil, "Are you sure you want to terminate the telnet server?", "Quit", ;
                XBPMB_OKCANCEL, XBPMB_WARNING+XBPMB_MOVEABLE+XBPMB_APPMODAL, XBPMB_DEFBUTTON2) == XBPMB_RET_OK
                exit
             endif
    
          case cKey == "S"
             oServer:Stop()
             ? Str(ThreadID(),3), "Server stopped"
    
          case cKey == "R"
             oServer:start()
             ? Str(ThreadID(),3), "Server started"
    
          case cKey == "L"
             ? "ClientList:", oServer:ClientList
    
          endcase
    
          DispOutAt( 0,0, PadR("(ESC)=Exit, (S)=Stop Server, (R)=Restart Server, (L)=List Clients",80), "gr+/bg" )
          DispOutAt( 1,0, PadR("ActiveConnections: " + NTrim(oServer:ActiveConnections()) + ", ConnectCount: " + NTrim(oServer:ConnectCount),80), "gr+/bg" )
          DispOutAt( 2,0, Space(80))
       end
    
       // DON'T FORGET TO DESTROY THE OBJECT !!
       oServer:destroy()
    
       Return
    
    //-----------------------------------------------------------------------------
    procedure ServiceClient()
       Local cRecv, cSend, cFileName, cColor
       Local cThreadID := Str(ThreadID(),3)
       Local oClient   := ThreadObject()
    
       ? cThreadID, "** CONNECT: RemoteName:", oClient:RemoteName, " Address:", oClient:InetNtoA(oClient:RemoteAddr), "Port:", NTrim(oClient:RemotePort)
    
       // send welcome message to client with some instructions
       oClient:Send( "Hello " + oClient:RemoteName + CRLF +;
                     "You are connected to my Xbase++ telnet server" + CRLF +;
                     "Try typing a DOS command like DIR..." + CRLF )
    
       // temp file name to redirect output of DOS commands to
       cFileName := "~" + NTrim(oClient:Handle) + ".TMP"
    
       // wait until we receive something on client socket (or error occurs)
       // remember this is running in it's own thread
    
       while (cRecv := oClient:RecvLine()) != NIL
    
          cSend := cRecv
          cRecv := StrTran(StrTran(cRecv,chr(10),""),chr(13),"")
          ? cThreadID, cRecv
    
          // execute DOS command received from client
          // redirecting output to a temp file
          RunShell( "/C " + cRecv + " > " + cFileName,,.f.,.t. )
    
          // read contents from temp file so we can send it to the client
          cSend += MemoRead(cFileName)
          FErase(cFileName)
    
          if oClient:Send( cSend ) < 0
             exit
          endif
       end
    
       cColor := SetColor("w/r")
       ? cThreadID, "** QUIT **"
       SetColor( cColor )
    
       Return
    

    home     download     top of page