Chat server: Difference between revisions

m
m (Automated syntax highlighting fixup (second round - minor fixes))
m (→‎{{header|Wren}}: Minor tidy)
 
(One intermediate revision by one other user not shown)
Line 94:
end loop;
end Chat_Server;</syntaxhighlight>
 
=={{header|BaCon}}==
=={{header|BASIC}}==
==={{header|BaCon}}===
Requires BaCon 4.2 or higher. Clients have to login with an alias and can use the commands 'say' or 'quit'. Notifications are submitted when users enter the chat or leave the chat.
<syntaxhighlight lang="text">DECLARE user$ ASSOC STRING
Line 131 ⟶ 133:
ENDIF
WEND</syntaxhighlight>
 
==={{header|Visual Basic .NET}}===
{{trans|C#}}
<syntaxhighlight lang="vbnet">Imports System.Net.Sockets
Imports System.Text
Imports System.Threading
 
Module Module1
 
Class State
Private ReadOnly client As TcpClient
Private ReadOnly sb As New StringBuilder
 
Public Sub New(name As String, client As TcpClient)
Me.Name = name
Me.client = client
End Sub
 
Public ReadOnly Property Name As String
 
Public Sub Send(text As String)
Dim bytes = Encoding.ASCII.GetBytes(String.Format("{0}" & vbCrLf, text))
client.GetStream().Write(bytes, 0, bytes.Length)
End Sub
End Class
 
ReadOnly connections As New Dictionary(Of Integer, State)
Dim listen As TcpListener
Dim serverThread As Thread
 
Sub Main()
listen = New TcpListener(Net.IPAddress.Parse("127.0.0.1"), 4004)
serverThread = New Thread(New ThreadStart(AddressOf DoListen))
serverThread.Start()
End Sub
 
Private Sub DoListen()
listen.Start()
Console.WriteLine("Server: Started server")
 
Do
Console.Write("Server: Waiting...")
Dim client = listen.AcceptTcpClient()
Console.WriteLine(" Connected")
 
' New thread with client
Dim clientThread As New Thread(New ParameterizedThreadStart(AddressOf DoClient))
 
clientThread.Start(client)
Loop
End Sub
 
Private Sub DoClient(client As TcpClient)
Console.WriteLine("Client (Thread: {0}): Connected!", Thread.CurrentThread.ManagedThreadId)
Dim bytes = Encoding.ASCII.GetBytes("Enter name: ")
client.GetStream().Write(bytes, 0, bytes.Length)
 
Dim done As Boolean
Dim name As String
Do
If Not client.Connected Then
Console.WriteLine("Client (Thread: {0}): Terminated!", Thread.CurrentThread.ManagedThreadId)
client.Close()
Thread.CurrentThread.Abort() ' Kill thread
End If
 
name = Receive(client)
done = True
 
For Each cl In connections
Dim state = cl.Value
If state.Name = name Then
bytes = Encoding.ASCII.GetBytes("Name already registered. Please enter your name: ")
client.GetStream().Write(bytes, 0, bytes.Length)
done = False
End If
Next
Loop While Not done
 
connections.Add(Thread.CurrentThread.ManagedThreadId, New State(name, client))
Console.WriteLine(vbTab & "Total connections: {0}", connections.Count)
Broadcast(String.Format("+++ {0} arrived +++", name))
 
Do
Dim text = Receive(client)
If text = "/quit" Then
Broadcast(String.Format("Connection from {0} closed.", name))
connections.Remove(Thread.CurrentThread.ManagedThreadId)
Console.WriteLine(vbTab & "Total connections: {0}", connections.Count)
Exit Do
End If
 
If Not client.Connected Then
Exit Do
End If
 
Broadcast(String.Format("{0}> {1}", name, text))
Loop
 
Console.WriteLine("Client (Thread: {0}): Terminated!", Thread.CurrentThread.ManagedThreadId)
client.Close()
Thread.CurrentThread.Abort()
End Sub
 
Private Function Receive(client As TcpClient) As String
Dim sb As New StringBuilder
Do
If client.Available > 0 Then
While client.Available > 0
Dim ch = Chr(client.GetStream.ReadByte())
If ch = vbCr Then
' ignore
Continue While
End If
If ch = vbLf Then
Return sb.ToString()
End If
sb.Append(ch)
End While
 
' pause
Thread.Sleep(100)
End If
Loop
End Function
 
Private Sub Broadcast(text As String)
Console.WriteLine(text)
For Each client In connections
If client.Key <> Thread.CurrentThread.ManagedThreadId Then
Dim state = client.Value
state.Send(text)
End If
Next
End Sub
 
End Module</syntaxhighlight>
 
=={{header|C}}==
C has no built-in networking functions, but the POSIX library does provide some low-level networking functions. The functions of interest relating to sockets include ''bind'', ''listen'', ''select'', ''accept'', ''read'', ''write'' and ''close''.
Line 3,659 ⟶ 3,799:
set ::cmap {}; # Dictionary mapping nicks to channels
vwait forever; # Run event loop</syntaxhighlight>
=={{header|Visual Basic .NET}}==
{{trans|C#}}
<syntaxhighlight lang="vbnet">Imports System.Net.Sockets
Imports System.Text
Imports System.Threading
 
Module Module1
 
Class State
Private ReadOnly client As TcpClient
Private ReadOnly sb As New StringBuilder
 
Public Sub New(name As String, client As TcpClient)
Me.Name = name
Me.client = client
End Sub
 
Public ReadOnly Property Name As String
 
Public Sub Send(text As String)
Dim bytes = Encoding.ASCII.GetBytes(String.Format("{0}" & vbCrLf, text))
client.GetStream().Write(bytes, 0, bytes.Length)
End Sub
End Class
 
ReadOnly connections As New Dictionary(Of Integer, State)
Dim listen As TcpListener
Dim serverThread As Thread
 
Sub Main()
listen = New TcpListener(Net.IPAddress.Parse("127.0.0.1"), 4004)
serverThread = New Thread(New ThreadStart(AddressOf DoListen))
serverThread.Start()
End Sub
 
Private Sub DoListen()
listen.Start()
Console.WriteLine("Server: Started server")
 
Do
Console.Write("Server: Waiting...")
Dim client = listen.AcceptTcpClient()
Console.WriteLine(" Connected")
 
' New thread with client
Dim clientThread As New Thread(New ParameterizedThreadStart(AddressOf DoClient))
 
clientThread.Start(client)
Loop
End Sub
 
Private Sub DoClient(client As TcpClient)
Console.WriteLine("Client (Thread: {0}): Connected!", Thread.CurrentThread.ManagedThreadId)
Dim bytes = Encoding.ASCII.GetBytes("Enter name: ")
client.GetStream().Write(bytes, 0, bytes.Length)
 
Dim done As Boolean
Dim name As String
Do
If Not client.Connected Then
Console.WriteLine("Client (Thread: {0}): Terminated!", Thread.CurrentThread.ManagedThreadId)
client.Close()
Thread.CurrentThread.Abort() ' Kill thread
End If
 
name = Receive(client)
done = True
 
For Each cl In connections
Dim state = cl.Value
If state.Name = name Then
bytes = Encoding.ASCII.GetBytes("Name already registered. Please enter your name: ")
client.GetStream().Write(bytes, 0, bytes.Length)
done = False
End If
Next
Loop While Not done
 
connections.Add(Thread.CurrentThread.ManagedThreadId, New State(name, client))
Console.WriteLine(vbTab & "Total connections: {0}", connections.Count)
Broadcast(String.Format("+++ {0} arrived +++", name))
 
Do
Dim text = Receive(client)
If text = "/quit" Then
Broadcast(String.Format("Connection from {0} closed.", name))
connections.Remove(Thread.CurrentThread.ManagedThreadId)
Console.WriteLine(vbTab & "Total connections: {0}", connections.Count)
Exit Do
End If
 
If Not client.Connected Then
Exit Do
End If
 
Broadcast(String.Format("{0}> {1}", name, text))
Loop
 
Console.WriteLine("Client (Thread: {0}): Terminated!", Thread.CurrentThread.ManagedThreadId)
client.Close()
Thread.CurrentThread.Abort()
End Sub
 
Private Function Receive(client As TcpClient) As String
Dim sb As New StringBuilder
Do
If client.Available > 0 Then
While client.Available > 0
Dim ch = Chr(client.GetStream.ReadByte())
If ch = vbCr Then
' ignore
Continue While
End If
If ch = vbLf Then
Return sb.ToString()
End If
sb.Append(ch)
End While
 
' pause
Thread.Sleep(100)
End If
Loop
End Function
 
Private Sub Broadcast(text As String)
Console.WriteLine(text)
For Each client In connections
If client.Key <> Thread.CurrentThread.ManagedThreadId Then
Dim state = client.Value
state.Send(text)
End If
Next
End Sub
 
End Module</syntaxhighlight>
=={{header|Wren}}==
An embedded solution using a C host since Wren has no built in support for either networking or multi-threading.
Line 3,801 ⟶ 3,806:
 
As Wren's VM is single threaded we create separate VMs to service each potential client connection (limited to 10) which run in their own thread. As the only way for the VMs to share mutable state is to use global variables within the host, synchronization is needed when accessing such variables.
<syntaxhighlight lang="ecmascriptwren">/* chat_serverChat_server.wren */
 
class Clients {
Line 4,002 ⟶ 4,007:
<br>
We now embed this in the following C program, build and run it to start the server. To end the server, just press control-C. For testing purposes, clients can use telnet from separate terminals to connect to the server on port 5000.
<syntaxhighlight lang="c">/* gcc chat_serverChat_server.c -o chat_serverChat_server -lpthread -lwren -lm */
 
#include <sys/socket.h>
Line 4,282 ⟶ 4,287:
config.bindForeignMethodFn = &bindForeignMethod;
const char* module = "main";
const char* fileName = "chat_serverChat_server.wren";
script = readFile(fileName);
 
Line 4,355 ⟶ 4,360:
return 0;
}</syntaxhighlight>
 
=={{header|zkl}}==
{{trans|Python}}
9,476

edits