Page 1 of 1

TCP Sockets - IRC

Posted: Sun Jun 25, 2023 10:04 pm
by Jestr
I have been using the language for a little bit now and have been getting the hang of it however, I have noticed continuity issues across older versions specifically with seldom touched-on topics/protocols such as IRC. IRC is relatively simple in its design using simple TCP sockets with modern servers supporting connections without TLS.

I ask today whether there are any good resources to learn low-level networking using PureBasic? IRC WebSockets Telnet SNMP and so on?

Re: TCP Sockets - IRC

Posted: Sun Jun 25, 2023 10:06 pm
by jassing
Jestr wrote: Sun Jun 25, 2023 10:04 pm I have been using the language for a little bit now and have been getting the hang of it however, I have noticed continuity issues across older versions specifically with seldom touched-on topics/protocols such as IRC. IRC is relatively simple in its design using simple TCP sockets with modern servers supporting connections without TLS.

I ask today whether there are any good resources to learn low-level networking using PureBasic? IRC WebSockets Telnet SNMP and so on?
Using PB for these things is easy. It's following the relevant RFC that you need to focus on. Follow those and you should be good. It's all "send this" and "receive that" and know how to respond in a timely fashion.

maybe this will get you started?
irc http://forums.purebasic.com/english/vie ... =13&t=5539
telnet viewtopic.php?t=33819&sid=1a52eae426805 ... e46be4264a
snmp http://forums.purebasic.com/english/vie ... hp?t=77943

Re: TCP Sockets - IRC

Posted: Sun Jun 25, 2023 10:11 pm
by Jestr
Yeah with IRC it's very straightforward with a lot of it falling on the user at the client with commands like /join and back in the day before auto-login with /login . I'm looking for anyone that has implemented similar protocols to act as a good base to learn from. Like I said I have been having trouble finding good resources that are up to date enough to match the newer syntax. I'm looking for examples OpenNetworkConnection and SenNetworkData/String's usage.

Re: TCP Sockets - IRC

Posted: Thu Jun 29, 2023 9:40 pm
by RichAlgeni
Here are a couple of simple programs that communicate with each other. Take a look, try them out, then feel free to ask any questions. Run the test_server process first, and enter the port number you wish to use. Then run the test_client process, and do the same.

Code: Select all

; test_server.pb

EnableExplicit

Procedure ProcessRequest(connectNumber.i)

    Protected result.l
    Protected length.i
    Protected *memoryLocation
    Protected memLength.i    = 32767
    Protected lastRecv.i     = Date()
    Protected doNotExit.i    = #True
    Protected socketHandle.i = ConnectionID(connectNumber)

    PrintN("Client " + Str(connectNumber) + " connected")

    *memoryLocation = AllocateMemory(memLength)

; loop until we have received data, or our timeout has been exceeded

    While doNotExit
        result = ioctlsocket_(socketHandle, #FIONREAD, @length)
        If result = 0 And length > 0
            Debug "result = " + Str(result) + ", length received Data = " + Str(length)
            result = ReceiveNetworkData(connectNumber.i, *memoryLocation, memLength.i)
            Select result
            Case 1 To 32767
                PrintN("Client " + Str(connectNumber) + " received " + PeekS(*memoryLocation, result))
            Case 0
            Default
                PrintN("Client " + Str(connectNumber) + " received socket error:" + Str(result) + ", " + Str(WSAGetLastError_()))
                doNotExit = #False
            EndSelect

            If Date() - lastRecv > 5
                doNotExit = #False
            EndIf
        ElseIf result = 0 And length = 0
            Delay(100)
        Else
            PrintN("Client " + Str(connectNumber) + " received socket error:" + Str(result) + ", " + Str(WSAGetLastError_()))
            doNotExit = #False
        EndIf
    Wend

    FreeMemory(*memoryLocation)

EndProcedure

Define NSEvent.i
Define keyPressed.s
Define portNumber.i
Define portString.s
Define thisClient.i
Define serverNumber.i
Define socketHandle.i

OpenConsole("Network Server Tester, Build:" + #PB_Editor_BuildCount)

PrintN("")
Print("Enter the server port number you wish to spawn: ")
portString = Input()
If portString = ""
    CloseConsole()
    End
EndIf

portNumber = Val(portString)
If portNumber < 1 Or portNumber > 65535
    PrintN("Invalid port number entered: " + portString)
    Input()
    CloseConsole()
    End
EndIf

serverNumber = CreateNetworkServer(#PB_Any, portNumber)
If serverNumber < 1
    PrintN("Unable to spawn a server to port " + Str(portNumber))
    Input()
    End
EndIf

PrintN("Started Network Server on port " + Str(portNumber))

Repeat
    NSEvent = NetworkServerEvent()  ; if we receive data, it will be indicated here

    Select NSEvent
    Case #PB_NetworkEvent_Connect   ; a socket has connected
    Case #PB_NetworkEvent_Data      ; raw data has been received
        thisClient   = EventClient()  ; get the event client identifier
        socketHandle = ConnectionID(thisClient)
        PrintN("Received client connection from: " + IPString(GetClientIP(thisClient)))
        ProcessRequest(thisClient)  ; procedure to process incoming data
        Break
    Case #PB_NetworkEvent_Disconnect; a socket disconnected
    Default                         ; no server event occurred
        Delay(100)                  ; sleep so we don't hammer the processor
    EndSelect

    keyPressed = Inkey()
ForEver

PrintN("Exiting loop, will close the socket")
closesocket_(socketHandle)
PrintN("Returned from closing the socket, will attempt to close the server")
CloseNetworkServer(serverNumber)
PrintN("Returned from closing the server, will now end the progam")
CloseConsole()
Input()

End
; IDE Options = PureBasic 6.02 LTS (Windows - x64)
; ExecutableFormat = Console
; CursorPosition = 40
; FirstLine = 30
; Executable = test_server.exe
; DisableDebugger
; HideErrorLog
; CurrentDirectory = D:\dev\PureBasic\temp\
; CompileSourceDirectory
; EnableCompileCount = 1
; EnableBuildCount = 1
; EnableExeConstant

Code: Select all

; test_client.pb

EnableExplicit

Define length.i
Define result.i
Define errNumber.i
Define lenSendText.i
Define serverName.s
Define stringText.s
Define portNumber.i
Define portString.s
Define connectNumber.i
Define socketHandle.i
Define memLength.i = 10000
Define *memoryLocation = AllocateMemory(memLength + 1)

OpenConsole("Network Client Tester, Build:" + #PB_Editor_BuildCount)

PrintN("")
Print("Enter the IP Address or name of the server, or press <enter> for local host: ")
serverName = Input()
If  serverName = ""
    serverName = "localhost"
EndIf

Print("Enter the port number to connect to: ")
portString = Input()
If portString = ""
    CloseConsole()
    End
EndIf

portNumber = Val(portString)
If portNumber < 1 Or portNumber > 65535
    PrintN("Invalid port number entered: " + portString)
    Input()
    CloseConsole()
    End
EndIf

PrintN("Attempting to connect to Network Server at " + serverName + " on port " + Str(portNumber))

connectNumber = OpenNetworkConnection(serverName, portNumber)

If connectNumber < 1
    errNumber = WSAGetLastError_()
    PrintN("Unable to connect to localhost, port " + Str(portNumber))
    PrintN("Winsock error = " + Str(errNumber))
Else
    socketHandle = ConnectionID(connectNumber)

    Repeat
        result = ioctlsocket_(socketHandle, #FIONREAD, @length)
        Debug "result = " + Str(result) + ", length received Data = " + Str(length)
        If result = 0 And length > 0
            result = ReceiveNetworkData(connectNumber, *memoryLocation, memLength)
            If result > 0
                PrintN("Received: " + PeekS(*memoryLocation, result))
            ElseIf result < 0
                PrintN("Received error " + Str(result) + ", " + WSAGetLastError_())
                Break
            EndIf
        ElseIf result <> 0
            PrintN("Received error " + Str(result) + ", " + WSAGetLastError_())
            Break
        EndIf

        stringText  = Input()
        lenSendText = StringByteLength(stringText)
        If lenSendText
            stringText  + #CRLF$
            lenSendText + 2
            result = SendNetworkData(connectNumber, @stringText, lenSendText)
            If result <> lenSendText
                PrintN("Received error " + Str(result) + ", " + WSAGetLastError_())
                Break
            EndIf
        EndIf
        Debug "lenSendText = " + Str(lenSendText)
    ForEver

    CloseNetworkConnection(connectNumber)

    PrintN("Network sending complete, Press <enter> to exit")
EndIf

Input()

CloseConsole()

End
; IDE Options = PureBasic 6.02 LTS (Windows - x64)
; ExecutableFormat = Console
; CursorPosition = 69
; FirstLine = 18
; Executable = test_client.exe
; DisableDebugger
; HideErrorLog
; CurrentDirectory = \
; CompileSourceDirectory
; EnableCompileCount = 1
; EnableBuildCount = 1
; EnableExeConstant