A chat in PureBasic

Just starting out? Need help? Post your questions and find answers here.
User avatar
SPH
Enthusiast
Enthusiast
Posts: 596
Joined: Tue Jan 04, 2011 6:21 pm

A chat in PureBasic

Post by SPH »

Hi all,

I would like to talk to you about network communication. I know that PB comes with examples and indeed, there is an example of a network client and an example of a network server. But I can't combine them to create a single code that would serve as a client/server to create a chat.
Do you have such a code please??

Thank you lot :!:

!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Portable LENOVO ideapad 110-17ACL 64 bits
Version de PB : 6.12LTS - 64 bits
User avatar
SPH
Enthusiast
Enthusiast
Posts: 596
Joined: Tue Jan 04, 2011 6:21 pm

Re: A chat in PureBasic

Post by SPH »

Or better: do you have a chat code?
Thank you lot

!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Portable LENOVO ideapad 110-17ACL 64 bits
Version de PB : 6.12LTS - 64 bits
infratec
Always Here
Always Here
Posts: 7664
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: A chat in PureBasic

Post by infratec »

What do you mean with 'chat' :?:

XMPP ?

There is no direct imlementation of XMPP in PB.
But of course you can send text from one program to an other.
You only need t to start a server. The sever can also answer to clients.

Look also here:
https://www.purebasic.fr/english/viewtopic.php?t=73882
User avatar
SPH
Enthusiast
Enthusiast
Posts: 596
Joined: Tue Jan 04, 2011 6:21 pm

Re: A chat in PureBasic

Post by SPH »

chat = a message exchange
i'm french, i'm sorry :idea:

!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Portable LENOVO ideapad 110-17ACL 64 bits
Version de PB : 6.12LTS - 64 bits
User avatar
idle
Always Here
Always Here
Posts: 6040
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: A chat in PureBasic

Post by idle »

A message exchange over the lan or over the internet. over the internet you will need a publicly reachable server, you can either relay messages through a web server use php sql or pb or forward a port to a server running on your desktop to serve as relay for the messages or you want p2p you need to hole punch to establish a p2p connection which requires a public facing server for ip discovery.

There's a number of choices to consider and it depends on your goal there is also authentication and encryption to consider so it can turn into 1000's of lines of code for something you could do in a couple of lines....

You really need to define what you want to achieve and how you want to use it.
Marc56us
Addict
Addict
Posts: 1600
Joined: Sat Feb 08, 2014 3:26 pm

Re: A chat in PureBasic

Post by Marc56us »

SPH wrote: Mon Dec 18, 2023 11:47 pm Hi all,

I would like to talk to you about network communication. I know that PB comes with examples and indeed, there is an example of a network client and an example of a network server. But I can't combine them to create a single code that would serve as a client/server to create a chat.
Do you have such a code please??

Thank you lot :!:
Hi SPH,

Already answered in 2021 on french forum. :wink:

Small IRC server and Client.
IRC_Server.pb Launch only one on any PC. change IP and #Port

Code: Select all

; PB small IRC Server
; Marc56(us) and french forum users. Based on PureBasic samples
; https://www.purebasic.fr/french/viewtopic.php?p=212218#p212218
; Created  : 2021/11/21
; Modified : 2023/12/20

OnErrorGoto(?Global_Error)

Enumeration FormWindow
  #Win_Server
EndEnumeration

Enumeration FormGadget
  #Log
EndEnumeration

Enumeration FormFont
  #Font_Win_Server_0
EndEnumeration

LoadFont(#Font_Win_Server_0,"Consolas", 10)

Declare ResizeGadgetsWin_Server()

Procedure OpenWin_Server(x = 10, y = 10, width = 300, height = 500)
  OpenWindow(#Win_Server, x, y, width, height, "PB IRCd", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_SizeGadget)
  CreateStatusBar(0, WindowID(#Win_Server))
  AddStatusBarField(300)
  StatusBarText(0, 0, "PB IRCd - v0.1")
  ListViewGadget(#Log, 5, 5, 290, 465)
  SetGadgetColor(#Log, #PB_Gadget_FrontColor,RGB(128,128,128))
  SetGadgetColor(#Log, #PB_Gadget_BackColor,RGB(255,255,255))
  SetGadgetFont(#Log, FontID(#Font_Win_Server_0))
EndProcedure

Procedure ResizeGadgetsWin_Server()
  Protected FormWindowWidth, FormWindowHeight
  FormWindowWidth = WindowWidth(#Win_Server)
  FormWindowHeight = WindowHeight(#Win_Server)
  ResizeGadget(#Log, 5, 5, FormWindowWidth - 10, FormWindowHeight - StatusBarHeight(0) - 12)
EndProcedure

Structure sClient
    ID.i
    Name$
    Connected.i
EndStructure
Global NewList Client.sClient()
Global Receive_Txt$

Procedure Monitor(Message$)
    ; Display on server
    AddGadgetItem(#Log, -1, Message$)
    ; todo: Log file
EndProcedure

Procedure Send_All(Message$)
    If Message$ <> "" : Receive_Txt$ = Message$ : EndIf
    ForEach Client()
        If Client()\Connected = 1
            SendNetworkString(Client()\ID, Receive_Txt$, #PB_UTF8)
        EndIf
    Next    
EndProcedure

OpenWin_Server()
Monitor("Starting IRC Server...")

If CountProgramParameters() 
    Port = Val(ProgramParameter(0))
Else
    Port = 6832
EndIf
*Buffer = AllocateMemory(1000)

If Not CreateNetworkServer(0, Port)
    Monitor("Error - Can't create the server (port in use ?).")
EndIf

Monitor("Listening on port: " + Str(Port))
SetWindowTitle(#Win_Server, "PB IRCd - Running...")

Repeat
    Win_Event = WaitWindowEvent(1)
    Net_Event = NetworkServerEvent() 
    
    Select Win_Event
        Case #PB_Event_CloseWindow
            Monitor("Close connection(s)")
            CloseNetworkServer(0)
            End
            
        Case #PB_Event_SizeWindow
            ResizeGadgetsWin_Server()
    EndSelect
    
    ID_Client = EventClient() 
    If NickName$ = "" :
        NickName$ = LSet(Str(ID_Client), 8, " ") 
    EndIf
    Select Net_Event
            
        Case #PB_NetworkEvent_Connect
            Monitor(NickName$ + " : Connected.")
            AddElement(Client()) 
            With Client()
                \ID     = ID_Client
                \Name$  = NickName$
                \Connected = 1
            EndWith
            
        Case #PB_NetworkEvent_Data
            FillMemory(*Buffer, 1000)
            Nb_Octets = ReceiveNetworkData(ID_Client, *Buffer, 1000)
            Receive_Txt$ = PeekS(*Buffer, Nb_Octets, #PB_UTF8)
            If Left(Receive_Txt$, 5) = "/nick"
                NickName$ = Mid(Receive_Txt$, 6, 10)
                Client()\Name$ = NickName$
            Else
                Monitor(Receive_Txt$)
 
            EndIf
            Send_All("")
            
        Case #PB_NetworkEvent_Disconnect
            Monitor(LTrim(NickName$) + " : has quit.")
            Client()\Connected = 0
            
    EndSelect
Until Quit = 1  
Monitor("Server - Close connection")
CloseNetworkServer(0)

End   

Global_Error:
MessageRequester("Error", ErrorMessage(), 16)

Small IRC Client
IRC_Client.pb Launch in client PC. Change IP and #Port to server address

Code: Select all

; PB small IRC Client
; Marc56(us) and french forum users. Based on PureBasic samples
; https://www.purebasic.fr/french/viewtopic.php?p=212218#p212218
; Created  : 2021/11/21
; Modified : 2023/12/20

OnErrorGoto(?Global_Error)

Enumeration FormWindow
    #Win
EndEnumeration

Enumeration FormGadget
    #Dialog
    #Txt
    #Btn_Send
    #Btn_Connect
    #Btn_Quit
    #Str_Name
    #Btn_Name
    #Str_IP
    #Str_Port
    #Txt_Alias
EndEnumeration

Enumeration FormFont
    #Font_Win_0
EndEnumeration

LoadFont(#Font_Win_0,"Consolas", 10)

Declare ResizeGadgetsWin()

Procedure OpenWin(x = 0, y = 0, width = 300, height = 500)
    OpenWindow(#Win, x, y, width, height, "PB IRC", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget | #PB_Window_ScreenCentered)
    CreateStatusBar(0, WindowID(#Win))
    AddStatusBarField(300)
    StatusBarText(0, 0, "Ready.")
    ListViewGadget(#Dialog, 5, 65, 290, 380)
    SetGadgetFont(#Dialog, FontID(#Font_Win_0))
    StringGadget(#Txt, 5, 447, 215, 25, "")
    SetGadgetFont(#Txt, FontID(#Font_Win_0))
    ButtonGadget(#Btn_Send, 225, 447, 70, 25, "Send", #PB_Button_Default)
    SetGadgetFont(#Btn_Send, FontID(#Font_Win_0))
    DisableGadget(#Btn_Send, 1)
    ButtonGadget(#Btn_Connect, 155, 5, 75, 25, "Connect")
    ButtonGadget(#Btn_Quit, 235, 5, 60, 25, "Quit")
    StringGadget(#Str_Name, 55, 35, 95, 25, "")
    SetGadgetFont(#Str_Name, FontID(#Font_Win_0))
    ButtonGadget(#Btn_Name, 155, 35, 75, 25, "Change ")
    StringGadget(#Str_IP, 5, 5, 95, 25, "127.0.0.1")
    SetGadgetFont(#Str_IP, FontID(#Font_Win_0))
    StringGadget(#Str_Port, 105, 5, 40, 25, "6832", #PB_String_Numeric)
    SetGadgetFont(#Str_Port, FontID(#Font_Win_0))
    TextGadget(#Txt_Alias, 10, 40, 40, 20, "Alias")
    SetGadgetFont(#Txt_Alias, FontID(#Font_Win_0))
    DisableGadget(#Txt, 1)
EndProcedure

Procedure ResizeGadgetsWin()
    Protected FormWindowWidth, FormWindowHeight
    FormWindowWidth = WindowWidth(#Win)
    FormWindowHeight = WindowHeight(#Win)
    ResizeGadget(#Dialog, 5, 65, FormWindowWidth - 10, FormWindowHeight - StatusBarHeight(0) - 97)
    ResizeGadget(#Txt, 5, FormWindowHeight - 53, FormWindowWidth - 85, 25)
    ResizeGadget(#Btn_Send, FormWindowWidth - 75, FormWindowHeight - 53, 70, 25)
    ResizeGadget(#Btn_Connect, FormWindowWidth - 145, 5, 75, 25)
    ResizeGadget(#Btn_Quit, FormWindowWidth - 65, 5, 60, 25)
    ResizeGadget(#Btn_Name, 155, FormWindowHeight - 465, FormWindowWidth - 225, 25)
EndProcedure

Enumeration FormWindow
    #Refresh    
EndEnumeration

OpenWin() 
AddKeyboardShortcut(#Win, #PB_Shortcut_Return, 13)
AddWindowTimer(#Win, #Refresh, 1000)

Global Name$ = LSet("ID_" + Str(Random(99, 1)), 8, " ")
SetGadgetText(#Str_Name, Name$)

Global IP$ = "127.0.0.1"
Global Port = 6832
Global ID_Cnx
Global *Buffer = AllocateMemory(1000)


Declare Disconnect()

Procedure Connect()
    IP$     = GetGadgetText(#Str_IP)
    Port    = Val(GetGadgetText(#Str_Port))
    If GetGadgetText(#Btn_Connect) = "Disconnect"
        Disconnect()
        ProcedureReturn 
    EndIf
    ID_Cnx = OpenNetworkConnection(IP$, Port)
    If ID_Cnx
        AddGadgetItem(#Dialog, -1, "Connect to " + IP$) 
        AddGadgetItem(#Dialog, -1, "ID connection " + Str(ID_Cnx)) 
        StatusBarText(0, 0, "Connected to " + IP$ + ":" + Port) 
        StatusBarText(0, 0, "Port: " + Str(Port))
        DisableGadget(#Txt, 0)
        DisableGadget(#Btn_Send, 0)
        SetGadgetText(#Btn_Connect, "Disconnect")
        Name$ = RSet(GetGadgetText(#Str_Name), 8, " ")
        SendNetworkString(ID_Cnx, "/New " + Name$, #PB_UTF8)
    Else
        AddGadgetItem(#Dialog, -1, "Can't connect to Server") 
        MessageRequester("Error", "Can't connect to Server", #PB_MessageRequester_Error) : End
    EndIf
EndProcedure

Procedure Disconnect()
    AddGadgetItem(#Dialog, -1, "End of Connection")
    ;CloseNetworkServer(0)
    If ID_Cnx = 0 : ProcedureReturn : EndIf
    SendNetworkString(ID_Cnx, "EOT " + Name$, #PB_UTF8)
    CloseNetworkConnection(ID_Cnx)
    StatusBarText(0, 0, "Disconnected From " + IP$) ;   
    DisableGadget(#Btn_Send, 1)
    Name$ = "ID_" + Str(Random(99, 1))
    SetGadgetText(#Btn_Connect, "Connecter")
EndProcedure


Procedure Send_Txt()
    TxtToSend$ = Name$ + " | " + GetGadgetText(#txt)
    Nb = SendNetworkString(ID_Cnx, TxtToSend$, #PB_UTF8)
    TxtToSend$ = ""
    SetGadgetText(#txt, "")
EndProcedure

Procedure Change_Name()
    Protected Old_Name$ = Name$
    Name$ = LSet(GetGadgetText(#Str_Name), 8, " ")
    AddGadgetItem(#Dialog, -1, Old_Name$ + " is now named: " + Name$)
    SendNetworkString(ID_Cnx, "/Change " + Name$, #PB_UTF8)
EndProcedure

; Connect()

Repeat 
    Win_Event = WaitWindowEvent()
    
    ; Events WINDOWS
    Select Win_Event
        Case #PB_Event_CloseWindow
            End
            
        Case #PB_Event_Menu
            If EventMenu() = 13
                Send_Txt()          
            EndIf
            
        Case #PB_Event_SizeWindow
            ResizeGadgetsWin()
            
        Case #PB_Event_Timer
            If EventTimer() = #Refresh
                While WindowEvent() : Wend
            EndIf
            
        Case #PB_Event_Gadget
            Select EventGadget()   
                    
                Case #Btn_Connect
                    Connect()  
                    
                Case #Btn_Quit
                    Disconnect()
                    End
                    
                Case #Btn_Send
                    If ID_Cnx
                        Send_Txt()
                    Else
                        AddGadgetItem(#Dialog, -1, "Connection Lost")
                    EndIf
                    
                Case #Btn_Name
                    Change_Name()
                    
            EndSelect
    EndSelect ; (Win_Event)
    
    If GetGadgetText(#Btn_Connect) = "Disconnect"
        Net_Event = NetworkClientEvent(ID_Cnx) 
    EndIf
    
    Select Net_Event
            
        Case #PB_NetworkEvent_Data
            ;While WindowEvent() : Wend
            FillMemory(*Buffer, 1000)
            ReceiveNetworkData(ID_Cnx, *Buffer, 1000)
            Received_Txt$ = PeekS(*Buffer, -1, #PB_UTF8)
            AddGadgetItem(#Dialog, -1, LTrim(Received_Txt$))
            Received_Txt$ = ""
            
    EndSelect
    
Until Quit = 1  

AddGadgetItem(#Dialog, -1, "End of Connection")
CloseNetworkConnection(ID_Client)
End

Global_Error:
MessageRequester("Error", ErrorMessage(), 16)
PS. Chat (in french) = Instant messaging (IM) = Internet Relay Chat Often based on IRC protocol.
Young people have never experienced browser-independent IRC (Internet Relay Chat) applications (IRCd, mIRC etc). No need for bloatware languages (Java, Python) or scripting languages in browser either; just a few lines in any basic language that support network communication. PureBasic ! )
"Small is beautifull"
Enjoy :wink:
Oso
Enthusiast
Enthusiast
Posts: 595
Joined: Wed Jul 20, 2022 10:09 am

Re: A chat in PureBasic

Post by Oso »

Marc56us wrote: Wed Dec 20, 2023 8:50 am Small IRC Client
IRC_Client.pb Launch in client PC. Change IP and #Port to server address
Sorry Marc56us :D There is a bug in the client-side code. If you disconnect in the client and then exit, it crashes...

Image

The disconnect has already been done, so the Disconnect() is not necessary and if the user hasn't already disconnected then that is fine too, because the connection will be lost on close.

Code: Select all

                Case #Btn_Quit
                    ; Disconnect()
                    End
1. Click Connect
2. Enter Hello, Click Send
3. Click Disconnect
4. Click Quit
User avatar
SPH
Enthusiast
Enthusiast
Posts: 596
Joined: Tue Jan 04, 2011 6:21 pm

Re: A chat in PureBasic

Post by SPH »

hooo, thank you marc !
It's a very good base for me.
:arrow:
OSO : an error ?
Marc : have you seen an error on your code ?

!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Portable LENOVO ideapad 110-17ACL 64 bits
Version de PB : 6.12LTS - 64 bits
Oso
Enthusiast
Enthusiast
Posts: 595
Joined: Wed Jul 20, 2022 10:09 am

Re: A chat in PureBasic

Post by Oso »

SPH wrote: Thu Dec 21, 2023 10:57 pm OSO : an error ?
If you just remove that commented line I've shown, it's then fine SPH :)
User avatar
SPH
Enthusiast
Enthusiast
Posts: 596
Joined: Tue Jan 04, 2011 6:21 pm

Re: A chat in PureBasic

Post by SPH »

Oso wrote: Thu Dec 21, 2023 11:07 pm
SPH wrote: Thu Dec 21, 2023 10:57 pm OSO : an error ?
If you just remove that commented line I've shown, it's then fine SPH :)
Ok, i see that tomorrow :idea:

!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Portable LENOVO ideapad 110-17ACL 64 bits
Version de PB : 6.12LTS - 64 bits
User avatar
SPH
Enthusiast
Enthusiast
Posts: 596
Joined: Tue Jan 04, 2011 6:21 pm

Re: A chat in PureBasic

Post by SPH »

Oso wrote: Thu Dec 21, 2023 11:07 pm
SPH wrote: Thu Dec 21, 2023 10:57 pm OSO : an error ?
If you just remove that commented line I've shown, it's then fine SPH :)
That's right now ok :arrow: :idea:

!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Portable LENOVO ideapad 110-17ACL 64 bits
Version de PB : 6.12LTS - 64 bits
Post Reply