SocketTools 4.5 Support for PureBasic

Developed or developing a new product in PureBasic? Tell the world about it.
Mike Stefanik
User
User
Posts: 53
Joined: Wed May 03, 2006 6:34 am
Location: California, United States
Contact:

SocketTools 4.5 Support for PureBasic

Post by Mike Stefanik »

SocketTools is a collection of Internet protocol libraries, originally written for Visual Basic and C/C++ and it's expanded to support quite a few other languages as well. We've had a few folks ask us about support for PureBasic so we created a set of include files and examples for the SocketTools Library Edition.

Although PureBasic has some basic TCP/IP support, if you're looking to do things like file transfers (FTP), submit form data to webservers (HTTP), send email (SMTP), manage mailboxes (POP3 and IMAP4) and so on, take a look at SocketTools. In total there's 18 Internet related libraries included with it.

You can download SocketTools 4.5 from here:
http://www.catalyst.com/cgi-bin/downloa ... oduct=4535

Then download the PureBasic 4.0 include files and examples from here:
ftp://ftp.catalyst.com/pub/cstools/supp ... basic4.zip

We even have special pricing for PureBasic developers who would like to purchase a copy for $95 (USD):
https://www.catalyst.com/cgi-bin/order.cgi?code=49381

If you need security features (SSL/TLS) for e-commerce types of applications, we also have a Secure Edition available. If you have any questions, just let me know. I monitor these forums, and of course you're welcome to post any questions or problems on our own support forums as well.

If you're curious as to what a simple program would look like, here's one that downloads a file from an FTP server. In general, it's quite a bit easier than using WinInet (and there's no external dependencies on WinInet, Internet Explorer, etc.):

Code: Select all

EnableExplicit

; Include SocketTools header files
IncludeFile "cstools4.pbi"
IncludeFile "cserror4.pbi"
IncludeFile "cstkey4.pbi"

; Initialize the SocketTools API
If Not FtpInitialize(#CSTOOLS4_LICENSE_KEY, #Null)
  MessageRequester("Error", "Unable to initialize SocketTools library")
  End
EndIf

If FtpDownloadFile("rfc0959.txt", "ftp://ftp.faqs.org/rfc/rfc959.txt;type=a", 30)
  MessageRequester("Success", "File downloaded successfully")
Else
  Define.l nError = FtpGetLastError()
  Define.s{128} strError

  FtpGetErrorString(nError, @strError, 128)
  MessageRequester("Error", strError)
EndIf

FtpUninitialize()
End
Mike Stefanik
sockettools.com
USCode
Addict
Addict
Posts: 923
Joined: Wed Mar 24, 2004 11:04 pm
Location: Seattle

Post by USCode »

Hi Mike,
Looks good, thanks.
Purebasic is a cross-platform development tool, have you thought about developing Mac OS X and Linux versions as well? Now THAT would be popular here!
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post by dracflamloc »

I also just want to say that even if it was cross platform I probably wouldn't purchase it because of the price. You do realize that you're charging more for your network functions than the entire cost of PB?

That said... thanks for supporting pb.
Fred
Administrator
Administrator
Posts: 18162
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Post by Fred »

It's always good to see third part libraries support for PureBasic, thanks for that ! About the other plateform support, it shouldn't be a problem as long you used only PB functions for your wrapper.
Mike Stefanik
User
User
Posts: 53
Joined: Wed May 03, 2006 6:34 am
Location: California, United States
Contact:

Post by Mike Stefanik »

They're imported functions from a standard Windows DLL, so it's not cross-platform. Similar to how we provide declarations for Visual Basic, Delphi and so on.

I realize that this isn't going to be something that most casual programmers would be interested in, it's more geared towards Windows developers who need Internet functionality for a commercial application, want something that is stable and supported, etc. Third-party languages are a kind of hobby of mine, and so when I find ones that interest me sometimes I like to see how it works with our software. Our customer base largely consists of folks using Visual Studio (VB, C++, C#) but I enjoy expanding support for it across other languages.

I must say, once I got used to some of the syntactical differences with PureBasic (for example, how variables are declared and the use of the ".") I think it's a very nice implementation and there's some features there (such as the fairly seemless support for Unicode) I wish other languages would implement. So, nice job all around. :)
Mike Stefanik
sockettools.com
Shannara
Addict
Addict
Posts: 1808
Joined: Thu Oct 30, 2003 11:19 pm
Location: Emerald Cove, Unformed

Post by Shannara »

Thank you Mike! I'll definately buy a copy in the next two weeks :)
dkirk
User
User
Posts: 24
Joined: Fri Nov 04, 2005 7:08 pm
Location: Flint, Michigan, USA

Post by dkirk »

I've been using Socket Tools 3.x for several years now with Clarion and they provide absolutely rock-solid software. Nice to see them support PB.
thefool
Always Here
Always Here
Posts: 5875
Joined: Sat Aug 30, 2003 5:58 pm
Location: Denmark

Post by thefool »

Missing the INDY socket package from delphi i must say, without trying the examples, that this looks quite interesting. 95$ isnt that bad, first i overlooked that and saw the normal price and i quickly browsed away :P
But for 95, its worth looking at. (i hereby dont say the lib isnt worth 395$, but just that its above the limit i have on this stuff.)

however it looks interesting!
Jan2004
Enthusiast
Enthusiast
Posts: 163
Joined: Fri Jan 07, 2005 7:17 pm

Post by Jan2004 »

Mike,

Would you describe example scenario for using security features (SSL/TLS) added to Secure Edition ?
Mike Stefanik
User
User
Posts: 53
Joined: Wed May 03, 2006 6:34 am
Location: California, United States
Contact:

Post by Mike Stefanik »

The most common would be e-commerce types of applications that require secure connections to a webserver using HTTPS. For example, a program that does credit card processing and needs to submit form data securely. Another would be secure file transfers using FTPS. A third example would be a utility that wants to check your Google GMail account, which requires that you use a secure POP3 connection. Basically whenever the server requires that you use SSL/TLS to connect to it.
Mike Stefanik
sockettools.com
uweb
User
User
Posts: 98
Joined: Wed Mar 15, 2006 9:40 am
Location: Germany

Post by uweb »

Do you know a example for a FTP-Server in a not object-oriented language ?
PureBasic would be perfect of course. :)
Shannara
Addict
Addict
Posts: 1808
Joined: Thu Oct 30, 2003 11:19 pm
Location: Emerald Cove, Unformed

Post by Shannara »

Thanks to Mike S. for the help.

Below are two files, Thread.pb, and EchoServer.pb. They have been modified to run in Console Mode (Used jaPBe to edit, can compile but not debug, yet :)). Also, the server will read and write lines now instead of bytes. And the server should not answer connection requests if it is maxed out now :) Theoreticly (sp?) preventing the server from responding to DOS attacks by criminals. Also keeps the thread count down, hehe...

Events.pb and Common.pb is no longer needed. It also shaves off about 10k :)

EchoServer.pb

Code: Select all

;
; Catalyst SocketTools 4.5 Build 4520
; Copyright 1995-2006, Catalyst Development Corporation
; All rights reserved
;
; This example demonstrates how to create a simple server
; which echoes back any data that is sent to it.
;
EnableExplicit

; A global count of the number of active client sessions
Global g_nClientCount.l = 0
Global MAXCLIENTS.l = 100

; Include SocketTools header files
IncludeFile "cstools4.pbi"
IncludeFile "cserror4.pbi"
IncludeFile "cstkey4.pbi"

IncludeFile "thread.pb"

Define.l Event, WindowID, GadgetID, EventType
Define.l hServer = #INVALID_SOCKET
Define.l nResult, nIndex
Define.l nLocalAddress, nLocalPort, hSocket = #INVALID_SOCKET, hThread
Define.s{64} strAddress
Define.s{128} strError
Define.s KeyPressed
Dim nAddressList.l(32)

OpenConsole()
ConsoleTitle("Echo Server")

; Initialize the SocketTools API
If Not InetInitialize(#CSTOOLS4_LICENSE_KEY, #Null)
  PrintN("Error: Unable to initialize SocketTools library")
  Input()
  End
EndIf


If hServer = #INVALID_SOCKET
  strAddress = "000.000.000.000" ; <- Change This! 
  nLocalAddress = InetGetAddress(strAddress)
  nLocalPort = 0000 ; <- Change This!
  
  ; Start listening for connections on that address and port
  hServer = InetListen(nLocalAddress, nLocalPort)
  If hServer = #INVALID_SOCKET
    InetGetErrorString(InetGetLastError(), @strError, 128)
    PrintN("ERROR: " + strError)
  EndIf
  
  PrintN("Listening for client connections on address " + strAddress + " port " + Str(nLocalPort))
EndIf

PrintN("Press ESC to quit ...")

Repeat ; Start of the event loop
  KeyPressed = Inkey()
  
  If g_nClientCount < MAXCLIENTS ; Only accept connections IF we are not @ our max!
    hSocket = InetAccept(hServer, 1)
    If hSocket <> #INVALID_SOCKET
      hThread = CreateThread(@ClientThread(), hSocket)
      If hThread = 0
        PrintN("ERROR: Unable to create thread to accept client connection")
      EndIf
    EndIf
  EndIf
  
  Delay(1)
Until KeyPressed = Chr(27) ; Wait until escape is pressed

; If socket handle is valid, stop listening for connections
If hServer <> #INVALID_SOCKET
  InetDisconnect(hServer)
  hServer = #INVALID_SOCKET
EndIf

; Uninitialize the SocketTools library
InetUninitialize()

CloseConsole()

End

Thread.pb

Code: Select all

;
; Catalyst SocketTools 4.5 Build 4520
; Copyright 1995-2006, Catalyst Development Corporation
; All rights reserved
;

#BUFSIZE = 1024
#TIMEOUT = 10

Import "kernel32.lib"
  GetCurrentThreadId.l()
  InterlockedDecrement.l(*lpAddend.l)
  InterlockedIncrement.l(*lpAddend.l)
EndImport

Procedure ClientThread(hClient.l)
  Define.l nThreadId = 0
  Define.l nPeerAddress, nPeerPort
  Define.l nBytesRead, nBytesWritten
  Define.l nError = 0
  Define.s{128} strError
  Define.s{64} strAddress;
  Define.s{#BUFSIZE} strBuffer
  
  ; Get the current thread ID and increment the client count
  ; so we can track the number of clients that have connected
  ; to our server
  nThreadId = GetCurrentThreadId()

  ; Attach socket to thread!
  InetAttachThread(hClient, 0)
  
  ; Lock!
  InterlockedIncrement(@g_nClientCount)
  
  If hClient <> #INVALID_SOCKET
    ; If the connection has been accepted, get the address of the
    ; client who has connected to us
    InetGetPeerAddress(hClient, @nPeerAddress, @nPeerPort)
    InetFormatAddress(nPeerAddress, @strAddress, 64);
    
    ; Check to make sure that there aren't more clients running
    ; than the maximum specified by the user
    If g_nClientCount > MAXCLIENTS
      PrintN("ERROR: Too many active clients, rejecting connection from " + strAddress)
      InetDisconnect(hClient)
      InterlockedDecrement(@g_nClientCount)
      ProcedureReturn
    EndIf
    
    ; Update the ListView gadget
    PrintN("Thread 0x" + Hex(nThreadId) + " accepting connection from " + strAddress)
  Else
    nError = InetGetLastError()
  EndIf
  
  ; Read any data that has been sent by the client and write
  ; that data back to them.
  While nError = 0
    ; Initialize nBytesRead to the maximum number of characters
    ; that can be stored in the string buffer
    nBytesRead = #BUFSIZE
    
    ; Read a line of data, buffered up to the carriage-return/newline
    If InetReadLine(hClient, @strBuffer, @nBytesRead)
      ; Some data has been read from the client, send it back
      ; exactly as we have read it
      nBytesWritten = nBytesRead
      If Not InetWriteLine(hClient, strBuffer, @nBytesWritten)
        nError = InetGetLastError()
      EndIf
    Else
      ; An error has occurred. If the error indicates that the
      ; connection was closed by the client, then simply exit
      ; the loop. If the error is a timeout, then just go back
      ; to waiting for more data from the client. Otherwise
      ; report the error and terminate the connection.
      nError = InetGetLastError()
      If nError = #ST_ERROR_CONNECTION_CLOSED
        nError = 0
        Break
      ElseIf nError = #ST_ERROR_OPERATION_TIMEOUT
        nError = 0
      EndIf
    EndIf
  Wend
  
  If nError = 0
    ; No error has occurred, the client has closed its connection
    PrintN("Thread 0x" + Hex(nThreadId) + " closing connection to client from " + strAddress)
  Else
    ; An error has occurred, report it to the user
    InetGetErrorString(nError, @strError, 128)
    PrintN("ERROR: Thread 0x" + Hex(nThreadId) + " error " + Hex(nError) + ": " + strError)
  EndIf
  
  ; Disconnect the client socket and decrement the count of
  ; active client sessions
  InetDisconnect(hClient)
  InterlockedDecrement(@g_nClientCount)
EndProcedure
Post Reply