Already answered in 2021 on french forum.
Small IRC server and Client.
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)
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) =
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 ! )