Echo server: Difference between revisions
m
→{{header|Wren}}: Minor tidy
(Added Wren) |
m (→{{header|Wren}}: Minor tidy) |
||
(4 intermediate revisions by 4 users not shown) | |||
Line 11:
single-threaded, one client served at a time.
<
with Ada.IO_Exceptions;
with GNAT.Sockets;
Line 49:
GNAT.Sockets.Close_Socket (Connection);
end loop;
end Echo_Server;</
Multi-threaded, multiple clients served. On OS X 10.10.5 with gcc 4.9.1, serves a maximum of about 2000 threads (communication tasks) per process.
<syntaxhighlight lang="ada">
with Ada.Text_IO;
with Ada.IO_Exceptions;
Line 198:
end echo_server_multi;
</syntaxhighlight>
=={{header|Aime}}==
<
readc(dispatch w, file i, file o, data b)
{
Line 251:
0;
}</
=={{header|AutoHotkey}}==
<tt>echoserver.ahk</tt>, modified from
[http://www.autohotkey.com/forum/topic13829.html script] by zed gecko.
<
Network_Port = 12321
Network_Address = 127.0.0.1
Line 455:
ExitSub:
DllCall("Ws2_32\WSACleanup")
ExitApp</
A [[/AutoHotkey Client|client]] is also available for testing this code.
=={{header|
==={{header|BaCon}}===
<syntaxhighlight lang="bacon">OPEN "localhost:12321" FOR SERVER AS echo
WHILE TRUE
fd = ACCEPT(echo)
Line 466 ⟶ 467:
SEND data$ & CR$ & NL$ TO fd
CLOSE SERVER fd
WEND</
Input from other terminal:
<pre># echo "Hello world" | netcat 127.0.0.1 12321
Line 485 ⟶ 486:
Incoming connection from: 127.0.0.1:36784</pre>
==={{header|BBC BASIC}}===
{{works with|BBC BASIC for Windows}}
<
PROC_initsockets
Line 540 ⟶ 541:
WAIT 0
UNTIL FALSE
END</
'''Sample output:'''
<pre>
Line 552 ⟶ 553:
Connection on socket 1012 closed
</pre>
==={{header|PureBasic}}===
<syntaxhighlight lang="purebasic">NewMap RecData.s()
OpenWindow(0, 100, 200, 200, 100, "Echo Server", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget )
InitNetwork()
CreateNetworkServer(1, 12321)
Repeat
Event = NetworkServerEvent()
ClientID = EventClient()
If Event = #PB_NetworkEvent_Connect ; When a new client has been connected...
AddMapElement(RecData(), Str(ClientID))
ElseIf Event = #PB_NetworkEvent_Data
*Buffer = AllocateMemory(20000)
count = ReceiveNetworkData(ClientID, *Buffer, 20000)
For i = 1 To count
RecData(Str(ClientID)) + Mid( PeekS(*Buffer, count), i , 1)
If Right( RecData(Str(ClientID)), 2) = #CRLF$
SendNetworkString (ClientID, RecData(Str(ClientID)))
Debug IPString(GetClientIP(ClientID)) + ":" + Str(GetClientPort(ClientID)) + " " + RecData(Str(ClientID))
RecData(Str(ClientID)) = ""
EndIf
Next
FreeMemory(*Buffer)
ElseIf Event = #PB_NetworkEvent_Disconnect ; When a client has closed the connection...
DeleteMapElement(RecData(), Str(ClientID))
EndIf
Event = WaitWindowEvent(10)
Until Event = #PB_Event_CloseWindow</syntaxhighlight>
==={{header|REALbasic}}===
This example uses the built-in ServerSocket class to handle multiple users.
<syntaxhighlight lang="vb">
Class EchoSocket
Inherits TCPSocket
Sub DataAvailable()
If Instr(Me.LookAhead, EndofLine.Windows) > 0 Then
Dim data As String = Me.ReadAll
Dim lines() As String = Split(data, EndofLine.Windows)
For i As Integer = 0 To Ubound(lines)
Me.Write(lines(i) + EndOfLine.Windows)
Print(lines(i))
Next
End If
End Sub
End Class
Class EchoServer
Inherits ServerSocket
Function AddSocket() As TCPSocket
Return New EchoSocket
End Function
End Class
Class App
Inherits ConsoleApplication
Function Run(args() As String) As Integer
Listener = New EchoServer
Listener.Port = 12321
Listener.Listen()
While True
DoEvents() 'pump the event loop
Wend
End Function
Private Listener As EchoServer
End Class
</syntaxhighlight>
=={{header|C}}==
Line 557 ⟶ 629:
This is a rather standard code (details apart); the reference guide for such a code is the [http://beej.us/guide/bgnet Beej's Guide to Network programming]. The dependency from POSIX is mainly in the use of the <tt>read</tt> and <tt>write</tt> functions, (using the socket as a file descriptor sometimes make things simpler).
<
#include <stdlib.h>
#include <string.h>
Line 674 ⟶ 746:
take_connections_forever(sock);
return EXIT_SUCCESS;
}</
=={{header|C sharp|C#}}==
<
using System.Threading;
Line 739 ⟶ 811:
}
}
}</
=={{header|Clojure}}==
<
(use '[clojure.contrib.duck-streams :only (read-lines write-lines)])
Line 748 ⟶ 820:
(write-lines (java.io.PrintWriter. output true) (read-lines input)))
(create-server 12321 echo)</
Note here that an auto-flushing PrintWriter needs to be created, otherwise 'output' could simply be passed to write-lines.
Line 755 ⟶ 827:
{{trans|JavaScript}}
{{works with|node.js}}
<
net = require("net")
server = net.createServer (conn) ->
Line 773 ⟶ 845:
server.listen 12321, "localhost"
</syntaxhighlight>
=={{header|Common Lisp}}==
Line 779 ⟶ 851:
Here is a basic [http://common-lisp.net/project/usocket/ :usocket] example (it should work with any Common Lisp):
<
(defpackage :echo (:use :cl :usocket))
(in-package :echo)
Line 803 ⟶ 875:
(echo-server 12321)
</syntaxhighlight>
It's single threaded, so you can't REPL around with a running server. You'll need to start a second Lisp prompt, load the above and
<
(with-client-socket (sock str "127.0.0.1" port)
(write-string message str)
Line 815 ⟶ 887:
(echo-send "Hello echo!" 12321)
</syntaxhighlight>
The return value of that call should be "You said: Hello echo!".
Line 822 ⟶ 894:
The usocket library notwithstanding, sockets are not a standard part of Common Lisp, but many implementations provide them. Here is a CLISP-specific example: {{works with|CLISP}}
<
"This is a list of (socket :input status) which is used with
`socket:socket-status' to test for data ready on a socket.")
Line 868 ⟶ 940:
(setq *clients* (remove socket *clients* :key #'car)))
(echo-server 12321)</
=={{header|D}}==
This is a very basic server that processes the buffers one character at a time. In a real-world application, the buffers would be larger. More seriously, it processes one listener at a time. If the <code>currSock.receive()</code> blocks, the loop will not process other clients. This opens the door for a trivial denial-of-service attack. A realistic echo service must multiplex clients.
<
void main() {
Line 891 ⟶ 963:
buff.clear();
}
}</
This example will handle many connections.
<
void main() {
Line 1,002 ⟶ 1,074:
}
}
}</
=={{header|Delphi}}==
<
{$APPTYPE CONSOLE}
Line 1,062 ⟶ 1,134:
lEchoServer.Free;
end;
end.</
=={{header|Erlang}}==
<
-export([start/0]).
Line 1,087 ⟶ 1,159:
{tcp_closed, Conn} ->
io:format("Connection closed: ~p~n", [Conn])
end.</
=={{header|Elixir}}==
Line 1,117 ⟶ 1,189:
=={{header|F Sharp|F#}}==
<
open System.Net
open System.Net.Sockets
Line 1,146 ⟶ 1,218:
let main _ =
EchoService
0</
=={{header|Factor}}==
Connections get logged to <code>/place-where-factor-is/logs/echo-server</code>.
<
IN: rosetta.echo
Line 1,166 ⟶ 1,238:
: start-echo-server ( -- )
<echo-server> [ start-server ] in-thread start-server drop ;
</syntaxhighlight>
=={{header|Forth}}==
{{works with|GNU Forth|0.7.0}}
<
128 constant size
Line 1,199 ⟶ 1,271:
again ;
12321 echo-server</
''TODO: use tasker.fs and non-blocking semantics to handle mutliple connections''
=={{header|Go}}==
<
import (
Line 1,233 ⟶ 1,305:
go echo(s, i)
}
}</
=={{header|Haskell}}==
<
import Network (withSocketsDo, accept, listenOn, sClose, PortID(PortNumber))
import Control.Monad (forever)
Line 1,261 ⟶ 1,333:
acc@(_, host, port) <- accept listener
putStrLn $ "Accepted connection from " ++ show (host, port)
forkIO (echo acc)</
==Icon and {{header|Unicon}}==
The following is Unicon-specific:
<
procedure main()
Line 1,283 ⟶ 1,355:
critical mlck: nCons -:= 1
}
end</
=={{header|Java}}==
<
import java.io.IOException;
import java.io.InputStreamReader;
Line 1,327 ⟶ 1,399:
}
}
}</
=={{header|JavaScript}}==
{{works with|Node.js}}
<
function handleClient(conn) {
Line 1,354 ⟶ 1,426:
}
net.createServer(handleClient).listen(12321, 'localhost');</
=={{header|Julia}}==
<
using Sockets # for version 1.0
println("Echo server on port 12321")
Line 1,381 ⟶ 1,453:
println("Caught exception: $y")
end
</syntaxhighlight>
=={{header|Kotlin}}==
{{trans|Java}}
<
import java.net.Socket
Line 1,410 ⟶ 1,482:
}
}
</syntaxhighlight>
{{out}}
Line 1,425 ⟶ 1,497:
Paste into the LFE REPL:
<
(defun start ()
(spawn (lambda ()
Line 1,444 ⟶ 1,516:
(`#(tcp_closed ,conn)
(lfe_io:format "Connection closed: ~p~n" (list conn)))))
</syntaxhighlight>
Usage:
Line 1,461 ⟶ 1,533:
{{libheader|LuaSocket}}
<
local function has_value(tab, value)
Line 1,498 ⟶ 1,570:
end
end
end</
----
The following implementation uses tiny delays rather than socket.select. It uses a table of not-quite-non-blocking socket client objects (they block for 4 milliseconds), which is iterated over to check on whether each one has either a line to echo or an error to warrant deletion. Without the millisecond delays, the whole thing would become one 'hot' loop and eat all the CPU time for one core. With them, it uses close to zero percent.
<
function checkOn (client)
Line 1,532 ⟶ 1,604:
print(tostring(newClient) .. " connected")
table.insert(connections, newClient)
end</
----
{{works with|Luvit}}
<syntaxhighlight lang="lua">local http = require("http")
http.createServer(function(req, res)
print(("Connection from %s"):format(req.socket:address().ip))
local chunks = {}
local function dumpChunks()
for i=1,#chunks do
res:write(table.remove(chunks, 1))
end
end
req:on("data", function(data)
for line, nl in data:gmatch("([^\n]+)(\n?)") do
if nl == "\n" then
dumpChunks()
res:write(line)
res:write("\n")
else
table.insert(chunks, line)
end
end
end)
req:on("end", function()
dumpChunks()
res:finish()
end)
end):listen(12321, "127.0.0.1")
print("Server running at http://127.0.0.1:12321/")</syntaxhighlight>
=={{header|Mathematica}}/{{header|Wolfram Language}}==
This will be able to handle multiple connections and multiple echoes:
<
SocketListen[server, Function[{assoc},
With[{client = assoc["SourceSocket"], input = assoc["Data"]},
WriteString[client, ByteArrayToString[input]];
]
]]</
=={{header|Nim}}==
<
proc processClient(client: AsyncSocket) {.async.} =
Line 1,562 ⟶ 1,669:
discard serve()
runForever()</
=={{header|Objeck}}==
<
use Net;
use Concurrency;
Line 1,602 ⟶ 1,709:
}
}
</syntaxhighlight>
=={{header|Ol}}==
<
(define (timestamp) (syscall 201 "%c"))
Line 1,648 ⟶ 1,755:
(run 12321)
</syntaxhighlight>
=={{header|Oz}}==
<
ServerSocket = {New Open.socket init}
Line 1,686 ⟶ 1,793:
{ClientSocket close}
end
end</
Client test code:
<
Socket = {New class $ from Open.socket Open.text end init}
in
Line 1,695 ⟶ 1,802:
{Socket write(vs:"Hello\n")}
{System.showInfo "Client received: "#{Socket getS($)}}
{Socket close}</
Example session:
Line 1,711 ⟶ 1,818:
This is an example using the [http://search.cpan.org/perldoc?IO::Socket IO::Socket] module:
<
my $use_fork = 1;
Line 1,739 ⟶ 1,846:
}
# child will reach here and close its copy of $sock before exit</
This is an equivalent program using the [http://search.cpan.org/perldoc?Net::Server Net::Server] module:
<
use base 'Net::Server::Fork';
sub process_request {
print while <STDIN>;
}
Echo->run(port => 12321, log_level => 3);</
It also prints the IP address and port number of every connection.
This is a more complicated example using preforking:
<
use base 'Net::Server::PreFork';
sub process_request {
print while <STDIN>;
}
Echo->run(port => 12321, log_level => 3);</
By default it spawns 5 child processes at startup, makes sure there are always at least 2 and at most 10 spare children available for new requests, each of which will be killed after processing 1000 requests and new ones will take their place.
=={{header|Phix}}==
<!--<
<span style="color: #000080;font-style:italic;">-- demo\rosetta\EchoServer.exw</span>
<span style="color: #008080;">
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">\</span><span style="color: #000000;">sockets</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">ESCAPE</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">#1B</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">echo</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">sockd</span><span style="color: #0000FF;">)</span>
Line 1,772 ⟶ 1,880:
<span style="color: #0000FF;">{</span><span style="color: #004080;">integer</span> <span style="color: #000000;">len</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">recv</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sockd</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">len</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">first</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">bytes_sent</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">send</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sockd</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- partial echo, see note</span>
Line 1,801 ⟶ 1,908:
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #000000;">list_s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">closesocket</span><span style="color: #0000FF;">(</span><span style="color: #000000;">list_s</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">WSACleanup</span><span style="color: #0000FF;">()</span>
<!--</
Tested using telnet [-e q] localhost 12321<br>
Note: on windows, keying "abc" did not echo anything until the first return, so I added a partial echo: remove if not needed/wanted.
=={{header|PHP}}==
<
socket_bind($socket, '127.0.0.1', 12321);
socket_listen($socket);
Line 1,838 ⟶ 1,945:
}
}
}</
=={{header|PicoLisp}}==
<
(loop
Line 1,856 ⟶ 1,963:
(prinl (stamp) " -- (Pid " *Pid ") Client disconnected")
(bye) # Terminate child</
=={{header|Python}}==
{{works with|Python|2.3 or above}}
<
HOST = "localhost"
Line 1,925 ⟶ 1,999:
# interrupt the program with Ctrl-C
print "server listening on %s:%s" % server.server_address
server.serve_forever()</
{{works with|Python|3.5 or above}}
<
#!/usr/bin/env python
# $ printf 'echo\r\n' | nc localhost 12321
Line 1,963 ⟶ 2,037:
loop.run_until_complete(server.wait_closed())
loop.close()
</syntaxhighlight>
{{works with|Python|2 and 3}}
Using only the low-level socket and threading modules. Supports timing out inactive clients
<
#!usr/bin/env python
import socket
Line 2,032 ⟶ 2,106:
print('exiting')
pass
</syntaxhighlight>
=={{header|Racket}}==
An example echo server from the front page of the Racket website:
<
#lang racket
(define listener (tcp-listen 12321))
Line 2,044 ⟶ 2,118:
(thread (λ() (copy-port I O) (close-output-port O)))
(echo-server))
</syntaxhighlight>
=={{header|Raku}}==
(formerly Perl 6)
{{Works with|rakudo|2018.03}}
<syntaxhighlight lang="raku"
:localhost<localhost>,
:localport<12321>,
Line 2,063 ⟶ 2,137:
$conn.close;
}
}</
Async version:
<syntaxhighlight lang="raku"
whenever IO::Socket::Async.listen('0.0.0.0', 12321) -> $conn {
whenever $conn.Supply.lines -> $line {
Line 2,073 ⟶ 2,147:
}
}
</syntaxhighlight>
=={{header|REBOL}}==
<
forever [
connection-port: first server-port
Line 2,124 ⟶ 2,159:
close connection-port
]
close server-port</
=={{header|Ruby}}==
<
server = TCPServer.new(12321)
Line 2,146 ⟶ 2,181:
end
end
end</
Ruby 1.9.2 introduced an alternate method to create TCP server sockets. The <code>Socket.tcp_server_loop</code> method encapsulates the guts of the server into a block.
{{works with|Ruby|1.9.2}}
<
Socket.tcp_server_loop(12321) do |conn, addr|
Line 2,167 ⟶ 2,202:
end
end
end</
=={{header|Rust}}==
<
use std::net::{TcpListener, TcpStream};
use std::io::{BufReader, BufRead, Write};
Line 2,198 ⟶ 2,233:
}
}
</syntaxhighlight>
=={{header|Scala}}==
<
import java.net.{ServerSocket, Socket}
Line 2,230 ⟶ 2,265:
while (true) new Thread(new ClientHandler(serverSocket.accept())).start()
}</
=={{header|Scheme}}==
{{works with|Guile}}
Based on the [[Guile]] [http://www.gnu.org/software/guile/manual/html_node/Internet-Socket-Examples.html Internet Socket Server Example].
<
(use-modules (ice-9 rdelim))
Line 2,275 ⟶ 2,310:
(primitive-exit))
; Parent waits for child to finish spawning grandchild
(waitpid child)))))</
=={{header|Seed7}}==
Line 2,282 ⟶ 2,317:
requests from new and existing connections.
<
include "socket.s7i";
include "listener.s7i";
Line 2,310 ⟶ 2,345:
end if;
end while;
end func;</
=={{header|Tcl}}==
This code is single-threaded. It uses non-blocking I/O to perform the transfers, sitting on top of the event multiplexer system call (e.g., <code>select()</code> on Unix) to decide when to take new connections or service a particular socket. This makes this into a very lightweight echo server in terms of overall system resources.
<
proc acceptEcho {chan host port} {
puts "opened connection from $host:$port"
Line 2,335 ⟶ 2,370:
# Make the server socket and wait for connections
socket -server acceptEcho -myaddr localhost 12321
vwait forever</
===Alternative version===
A more succinct version (though one harder to adapt to other kinds of services, but closer to the standard unix echo daemon since it has no line-buffering) is to use an asynchronous binary copy.
<
proc acceptEcho {chan host port} {
puts "opened connection from $host:$port"
Line 2,353 ⟶ 2,388:
# Make the server socket and wait for connections
socket -server acceptEcho -myaddr localhost 12321
vwait forever</
=={{header|X86 Assembly}}==
<
; x86_64 Linux NASM
Line 2,536 ⟶ 2,571:
xor rdi, rdi
syscall
</syntaxhighlight>
=={{header|Wren}}==
{{trans|C}}
An embedded program so we can ask the C host to call the relevant library functions for us and also handle simultaneous connections from multiple clients using a multi-process approach.
<
var MAX_ENQUEUED = 20
Line 2,679 ⟶ 2,714:
/* Serve the listening socket until killed */
takeConnectionsForever.call(sock)</
<br>
which we now embed in the following C program, build and run:
<
#include <stdio.h>
Line 2,965 ⟶ 3,000:
WrenVM* vm = wrenNewVM(&config);
const char* module = "main";
const char* fileName = "
char *script = readFile(fileName);
WrenInterpretResult result = wrenInterpret(vm, module, script);
Line 2,981 ⟶ 3,016:
free(script);
return 0;
}</
{{out}}
Line 2,987 ⟶ 3,022:
<pre>
/* start server on terminal 1 */
$ ./
/* start telnet on terminal 2 and type 'hello' */
Line 3,005 ⟶ 3,040:
=={{header|zkl}}==
<
pipe:=Thread.Pipe(); // how server tells thread to connect to user
Line 3,020 ⟶ 3,055:
server:=Network.TCPServerSocket.open(PORT);
println("Listening on %s:%s".fmt(server.hostname,server.port));
server.listen(echo.launch); // Main event loop</
{{out}}
The next three windows overlap in time
Line 3,057 ⟶ 3,092:
{{omit from|M4}}
{{omit from|Maxima}}
{{omit from|Minimal BASIC}}
{{omit from|ML/I}}
{{omit from|Palo Alto Tiny BASIC}}
{{omit from|PARI/GP}}
{{omit from|PL/0}}
{{omit from|Retro|No concurrency support}}
{{omit from|SNUSP|No networking.}}
{{omit from|Tiny BASIC}}
{{omit from|Unlambda|Does not have network access.}}
{{omit from|Commodore BASIC}}
|