CDE
This commit is contained in:
parent
518da4a923
commit
764da6cbbb
6144 changed files with 83610 additions and 11 deletions
5
Task/Echo-server/0DESCRIPTION
Normal file
5
Task/Echo-server/0DESCRIPTION
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
Create a network service that sits on TCP port <tt>12321</tt>, which accepts connections on that port, and which echoes complete lines (using a carriage-return/line-feed sequence as line separator) back to clients. No error handling is required. For the purposes of testing, it is only necessary to support connections from localhost (<tt>127.0.0.1</tt> or perhaps <tt>::1</tt>). Logging of connection information to standard output is recommended.
|
||||
|
||||
The implementation must be able to handle simultaneous connections from multiple clients. A multi-threaded or multi-process solution may be used. Each connection must be able to echo more than a single line.
|
||||
|
||||
The implementation must not stop responding to other clients if one client sends a partial line or stops reading responses.
|
||||
2
Task/Echo-server/1META.yaml
Normal file
2
Task/Echo-server/1META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
note: Networking and Web Interaction
|
||||
38
Task/Echo-server/Ada/echo-server.ada
Normal file
38
Task/Echo-server/Ada/echo-server.ada
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
with Ada.Text_IO;
|
||||
with Ada.IO_Exceptions;
|
||||
with GNAT.Sockets;
|
||||
procedure Echo_Server is
|
||||
Receiver : GNAT.Sockets.Socket_Type;
|
||||
Connection : GNAT.Sockets.Socket_Type;
|
||||
Client : GNAT.Sockets.Sock_Addr_Type;
|
||||
Channel : GNAT.Sockets.Stream_Access;
|
||||
begin
|
||||
GNAT.Sockets.Create_Socket (Socket => Receiver);
|
||||
GNAT.Sockets.Set_Socket_Option
|
||||
(Socket => Receiver,
|
||||
Option => (Name => GNAT.Sockets.Reuse_Address, Enabled => True));
|
||||
GNAT.Sockets.Bind_Socket
|
||||
(Socket => Receiver,
|
||||
Address => (Family => GNAT.Sockets.Family_Inet,
|
||||
Addr => GNAT.Sockets.Inet_Addr ("127.0.0.1"),
|
||||
Port => 12321));
|
||||
GNAT.Sockets.Listen_Socket (Socket => Receiver);
|
||||
loop
|
||||
GNAT.Sockets.Accept_Socket
|
||||
(Server => Receiver,
|
||||
Socket => Connection,
|
||||
Address => Client);
|
||||
Ada.Text_IO.Put_Line
|
||||
("Client connected from " & GNAT.Sockets.Image (Client));
|
||||
Channel := GNAT.Sockets.Stream (Connection);
|
||||
begin
|
||||
loop
|
||||
Character'Output (Channel, Character'Input (Channel));
|
||||
end loop;
|
||||
exception
|
||||
when Ada.IO_Exceptions.End_Error =>
|
||||
null;
|
||||
end;
|
||||
GNAT.Sockets.Close_Socket (Connection);
|
||||
end loop;
|
||||
end Echo_Server;
|
||||
200
Task/Echo-server/AutoHotkey/echo-server.ahk
Normal file
200
Task/Echo-server/AutoHotkey/echo-server.ahk
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
#SingleInstance Force
|
||||
Network_Port = 12321
|
||||
Network_Address = 127.0.0.1
|
||||
|
||||
NewData := false
|
||||
DataReceived =
|
||||
Gosub Connection_Init
|
||||
return
|
||||
|
||||
Connection_Init:
|
||||
OnExit, ExitSub
|
||||
socket := PrepareForIncomingConnection(Network_Address, Network_Port)
|
||||
if socket = -1
|
||||
ExitApp
|
||||
|
||||
Process, Exist
|
||||
DetectHiddenWindows On
|
||||
ScriptMainWindowId := WinExist("ahk_class AutoHotkey ahk_pid " . ErrorLevel)
|
||||
DetectHiddenWindows Off
|
||||
|
||||
NotificationMsg = 0x5555
|
||||
OnMessage(NotificationMsg, "ReceiveData")
|
||||
|
||||
ExitMsg = 0x6666
|
||||
OnMessage(ExitMsg, "ExitData")
|
||||
|
||||
FD_READ = 1
|
||||
FD_CLOSE = 32
|
||||
FD_CONNECT = 20
|
||||
|
||||
if DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket,
|
||||
"UInt", ScriptMainWindowId, "UInt", ExitMsg, "Int", FD_CLOSE)
|
||||
{
|
||||
msgbox, closed
|
||||
}
|
||||
|
||||
if DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket,
|
||||
"UInt", ScriptMainWindowId, "UInt", NotificationMsg, "Int",
|
||||
FD_READ|FD_CONNECT)
|
||||
{
|
||||
MsgBox % "WSAAsyncSelect() indicated Winsock error "
|
||||
. DllCall("Ws2_32\WSAGetLastError")
|
||||
DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket,
|
||||
"UInt", ScriptMainWindowId, "UInt", ExitMsg, "Int", FD_CLOSE)
|
||||
ExitApp
|
||||
}
|
||||
|
||||
SetTimer, NewConnectionCheck, 500
|
||||
return
|
||||
|
||||
PrepareForIncomingConnection(IPAddress, Port)
|
||||
{
|
||||
VarSetCapacity(wsaData, 32)
|
||||
result := DllCall("Ws2_32\WSAStartup", "UShort", 0x0002, "UInt", &wsaData)
|
||||
if ErrorLevel
|
||||
{
|
||||
MsgBox % "WSAStartup() could not be called due to error %ErrorLevel%. "
|
||||
. "Winsock 2.0 or higher is required."
|
||||
return -1
|
||||
}
|
||||
if result
|
||||
{
|
||||
MsgBox % "WSAStartup() indicated Winsock error "
|
||||
. DllCall("Ws2_32\WSAGetLastError")
|
||||
return -1
|
||||
}
|
||||
AF_INET = 2
|
||||
SOCK_STREAM = 1
|
||||
IPPROTO_TCP = 6
|
||||
socket := DllCall("Ws2_32\socket", "Int", AF_INET,
|
||||
"Int", SOCK_STREAM, "Int", IPPROTO_TCP)
|
||||
if socket = -1
|
||||
{
|
||||
MsgBox % "socket() indicated Winsock error "
|
||||
. DllCall("Ws2_32\WSAGetLastError")
|
||||
return -1
|
||||
}
|
||||
SizeOfSocketAddress = 16
|
||||
VarSetCapacity(SocketAddress, SizeOfSocketAddress)
|
||||
InsertInteger(2, SocketAddress, 0, AF_INET)
|
||||
InsertInteger(DllCall("Ws2_32\htons", "UShort", Port), SocketAddress, 2, 2)
|
||||
InsertInteger(DllCall("Ws2_32\inet_addr", "Str", IPAddress),
|
||||
SocketAddress, 4, 4)
|
||||
if DllCall("Ws2_32\bind", "UInt", socket,
|
||||
"UInt", &SocketAddress, "Int", SizeOfSocketAddress)
|
||||
{
|
||||
MsgBox % "bind() indicated Winsock error "
|
||||
. DllCall("Ws2_32\WSAGetLastError") . "?"
|
||||
return -1
|
||||
}
|
||||
if DllCall("Ws2_32\listen", "UInt", socket, "UInt", "SOMAXCONN")
|
||||
{
|
||||
MsgBox % "LISTEN() indicated Winsock error "
|
||||
. DllCall("Ws2_32\WSAGetLastError") . "?"
|
||||
return -1
|
||||
}
|
||||
return socket
|
||||
}
|
||||
|
||||
ReceiveData(wParam, lParam)
|
||||
{
|
||||
global DataReceived
|
||||
global NewData
|
||||
global mydata
|
||||
global ConnectionList
|
||||
socket := wParam
|
||||
ReceivedDataSize = 4096
|
||||
Loop
|
||||
{
|
||||
VarSetCapacity(ReceivedData, ReceivedDataSize, 0)
|
||||
ReceivedDataLength := DllCall("Ws2_32\recv", "UInt",
|
||||
socket, "Str", ReceivedData, "Int", ReceivedDataSize, "Int", 0)
|
||||
if ReceivedDataLength = 0
|
||||
{
|
||||
StringReplace, ConnectionList, ConnectionList, %socket%`n
|
||||
DllCall("Ws2_32\closesocket", "UInt", socket)
|
||||
}
|
||||
if ReceivedDataLength = -1
|
||||
{
|
||||
WinsockError := DllCall("Ws2_32\WSAGetLastError")
|
||||
if WinsockError = 10035
|
||||
{
|
||||
DataReceived = %TempDataReceived%
|
||||
NewData := true
|
||||
return 1
|
||||
}
|
||||
if WinsockError <> 10054
|
||||
{
|
||||
MsgBox % "recv() indicated Winsock error " . WinsockError
|
||||
StringReplace, ConnectionList, ConnectionList, %socket%`n
|
||||
DllCall("Ws2_32\closesocket", "UInt", socket)
|
||||
}
|
||||
}
|
||||
mydata := ReceivedData
|
||||
gosub myreceive
|
||||
if (A_Index = 1)
|
||||
TempDataReceived =
|
||||
TempDataReceived = %TempDataReceived%%ReceivedData%
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
ExitData(wParam, lParam)
|
||||
{
|
||||
global ConnectionList
|
||||
socket := wParam
|
||||
ReceivedDataSize = 16
|
||||
VarSetCapacity(ReceivedData, ReceivedDataSize, 0)
|
||||
ReceivedDataLength := DllCall("Ws2_32\recv", "UInt", socket,
|
||||
"Str", ReceivedData, "Int", ReceivedDataSize, "Int", 0)
|
||||
StringReplace, ConnectionList, ConnectionList, %socket%`n
|
||||
DllCall("Ws2_32\closesocket", "UInt", socket)
|
||||
return 1
|
||||
}
|
||||
|
||||
SendData(wParam,SendData)
|
||||
{
|
||||
SendDataSize := VarSetCapacity(SendData)
|
||||
SendDataSize += 1
|
||||
Loop, parse, wParam, `n
|
||||
{
|
||||
If A_LoopField =
|
||||
Continue
|
||||
socket := A_LoopField
|
||||
sendret := DllCall("Ws2_32\send", "UInt", socket,
|
||||
"Str", SendData, "Int", SendDatasize, "Int", 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
|
||||
{
|
||||
Loop %pSize%
|
||||
DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1,
|
||||
"UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF)
|
||||
}
|
||||
|
||||
NewConnectionCheck:
|
||||
ConnectionCheck := DllCall("Ws2_32\accept", "UInt", socket,
|
||||
"UInt", &SocketAddress, "Int", SizeOfSocketAddress)
|
||||
if ConnectionCheck > 1
|
||||
ConnectionList = %ConnectionList%%ConnectionCheck%`n
|
||||
Return
|
||||
|
||||
SendProcedure:
|
||||
If ConnectionList <>
|
||||
{
|
||||
SendText = %A_Hour%:%A_Min%:%A_Sec%
|
||||
SendData(ConnectionList,SendText)
|
||||
}
|
||||
Return
|
||||
|
||||
myreceive:
|
||||
TrayTip, server, %mydata%, ,16
|
||||
return
|
||||
|
||||
GuiClose:
|
||||
ExitSub:
|
||||
DllCall("Ws2_32\WSACleanup")
|
||||
ExitApp
|
||||
54
Task/Echo-server/BBC-BASIC/echo-server.bbc
Normal file
54
Task/Echo-server/BBC-BASIC/echo-server.bbc
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
INSTALL @lib$+"SOCKLIB"
|
||||
PROC_initsockets
|
||||
|
||||
maxSess% = 8
|
||||
DIM sock%(maxSess%-1), rcvd$(maxSess%-1), Buffer% 255
|
||||
|
||||
ON ERROR PRINT REPORT$ : PROC_exitsockets : END
|
||||
ON CLOSE PROC_exitsockets : QUIT
|
||||
|
||||
crlf$ = CHR$13 + CHR$10
|
||||
port$ = "12321"
|
||||
host$ = FN_gethostname
|
||||
PRINT "Host name is " host$
|
||||
|
||||
listen% = FN_tcplisten(host$, port$)
|
||||
PRINT "Listening on port ";port$
|
||||
|
||||
REPEAT
|
||||
socket% = FN_check_connection(listen%)
|
||||
IF socket% THEN
|
||||
FOR i% = 0 TO maxSess%-1
|
||||
IF sock%(i%) = 0 THEN
|
||||
sock%(i%) = socket%
|
||||
rcvd$(i%) = ""
|
||||
PRINT "Connection on socket "; sock%(i%) " opened"
|
||||
EXIT FOR
|
||||
ENDIF
|
||||
NEXT i%
|
||||
listen% = FN_tcplisten(host$, port$)
|
||||
ENDIF
|
||||
|
||||
FOR i% = 0 TO maxSess%-1
|
||||
IF sock%(i%) THEN
|
||||
res% = FN_readsocket(sock%(i%), Buffer%, 256)
|
||||
IF res% >= 0 THEN
|
||||
Buffer%?res% = 0
|
||||
rcvd$(i%) += $$Buffer%
|
||||
crlf% = INSTR(rcvd$(i%), crlf$)
|
||||
IF crlf% THEN
|
||||
echo$ = LEFT$(rcvd$(i%), crlf%-1)
|
||||
res% = FN_writelinesocket(sock%(i%), echo$)
|
||||
rcvd$(i%) = MID$(rcvd$(i%), crlf%+2)
|
||||
ENDIF
|
||||
ELSE
|
||||
PROC_closesocket(sock%(i%))
|
||||
PRINT "Connection on socket " ; sock%(i%) " closed"
|
||||
sock%(i%) = 0
|
||||
ENDIF
|
||||
ENDIF
|
||||
NEXT i%
|
||||
|
||||
WAIT 0
|
||||
UNTIL FALSE
|
||||
END
|
||||
118
Task/Echo-server/C/echo-server.c
Normal file
118
Task/Echo-server/C/echo-server.c
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define MAX_ENQUEUED 20
|
||||
#define BUF_LEN 256
|
||||
#define PORT_STR "12321"
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* How to clean up after dead child processes */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
void wait_for_zombie(int s)
|
||||
{
|
||||
while(waitpid(-1, NULL, WNOHANG) > 0) ;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* Core of implementation of a child process */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
void echo_lines(int csock)
|
||||
{
|
||||
char buf[BUF_LEN];
|
||||
int r;
|
||||
|
||||
while( (r = read(csock, buf, BUF_LEN)) > 0 ) {
|
||||
(void)write(csock, buf, r);
|
||||
}
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* Core of implementation of the parent process */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
void take_connections_forever(int ssock)
|
||||
{
|
||||
for(;;) {
|
||||
struct sockaddr addr;
|
||||
socklen_t addr_size = sizeof(addr);
|
||||
int csock;
|
||||
|
||||
/* Block until we take one connection to the server socket */
|
||||
csock = accept(ssock, &addr, &addr_size);
|
||||
|
||||
/* If it was a successful connection, spawn a worker process to service it */
|
||||
if ( csock == -1 ) {
|
||||
perror("accept");
|
||||
} else if ( fork() == 0 ) {
|
||||
close(ssock);
|
||||
echo_lines(csock);
|
||||
} else {
|
||||
close(csock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* The server process's one-off setup code */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
int main()
|
||||
{
|
||||
struct addrinfo hints, *res;
|
||||
struct sigaction sa;
|
||||
int sock;
|
||||
|
||||
/* Look up the address to bind to */
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
if ( getaddrinfo(NULL, PORT_STR, &hints, &res) != 0 ) {
|
||||
perror("getaddrinfo");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Make a socket */
|
||||
if ( (sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1 ) {
|
||||
perror("socket");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Arrange to clean up child processes (the workers) */
|
||||
sa.sa_handler = wait_for_zombie;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = SA_RESTART;
|
||||
if ( sigaction(SIGCHLD, &sa, NULL) == -1 ) {
|
||||
perror("sigaction");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Associate the socket with its address */
|
||||
if ( bind(sock, res->ai_addr, res->ai_addrlen) != 0 ) {
|
||||
perror("bind");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
|
||||
/* State that we've opened a server socket and are listening for connections */
|
||||
if ( listen(sock, MAX_ENQUEUED) != 0 ) {
|
||||
perror("listen");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Serve the listening socket until killed */
|
||||
take_connections_forever(sock);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
7
Task/Echo-server/Clojure/echo-server.clj
Normal file
7
Task/Echo-server/Clojure/echo-server.clj
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
(use '[clojure.contrib.server-socket :only (create-server)])
|
||||
(use '[clojure.contrib.duck-streams :only (read-lines write-lines)])
|
||||
|
||||
(defn echo [input output]
|
||||
(write-lines (java.io.PrintWriter. output true) (read-lines input)))
|
||||
|
||||
(create-server 12321 echo)
|
||||
17
Task/Echo-server/CoffeeScript/echo-server.coffee
Normal file
17
Task/Echo-server/CoffeeScript/echo-server.coffee
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
net = require("net")
|
||||
server = net.createServer (conn) ->
|
||||
console.log "Connection from #{conn.remoteAddress} on port #{conn.remotePort}"
|
||||
conn.setEncoding "utf8"
|
||||
buffer = ""
|
||||
conn.on "data", (data) ->
|
||||
i = 0
|
||||
|
||||
while i <= data.length
|
||||
char = data.charAt(i)
|
||||
buffer += char
|
||||
if char is "\n"
|
||||
conn.write buffer
|
||||
buffer = ""
|
||||
i++
|
||||
|
||||
server.listen 12321, "localhost"
|
||||
47
Task/Echo-server/Common-Lisp/echo-server-1.lisp
Normal file
47
Task/Echo-server/Common-Lisp/echo-server-1.lisp
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
(defvar *clients* '()
|
||||
"This is a list of (socket :input status) which is used with
|
||||
`socket:socket-status' to test for data ready on a socket.")
|
||||
|
||||
(defun echo-server (port)
|
||||
"Listen on `port' for new client connections and for data arriving on
|
||||
any existing client connections"
|
||||
(let ((server (socket:socket-server port)))
|
||||
(format t "Echo service listening on port ~a:~d~%"
|
||||
(socket:socket-server-host server)
|
||||
(socket:socket-server-port server))
|
||||
(unwind-protect
|
||||
(loop
|
||||
(when (socket:socket-status server 0 1)
|
||||
(echo-accept-client (socket:socket-accept server
|
||||
:external-format :dos
|
||||
:buffered t)))
|
||||
(when *clients*
|
||||
(socket:socket-status *clients* 0 1)
|
||||
(mapcar #'(lambda (client)
|
||||
(when (eq :input (cddr client))
|
||||
(echo-service-client (car client)))
|
||||
(when (eq :eof (cddr client))
|
||||
(echo-close-client (car client)))) *clients*)))
|
||||
(socket-server-close server))))
|
||||
|
||||
(defun echo-accept-client (socket)
|
||||
"Accept a new client connection and add it to the watch list."
|
||||
(multiple-value-bind
|
||||
(host port) (socket:socket-stream-peer socket)
|
||||
(format t "Connect from ~a:~d~%" host port))
|
||||
(push (list socket :input nil) *clients*))
|
||||
|
||||
(defun echo-service-client (socket)
|
||||
(let ((line (read-line socket nil nil)))
|
||||
(princ line socket)
|
||||
(finish-output socket)))
|
||||
|
||||
(defun echo-close-client (socket)
|
||||
"Close a client connection and remove it from the watch list."
|
||||
(multiple-value-bind
|
||||
(host port) (socket:socket-stream-peer socket)
|
||||
(format t "Closing connection from ~a:~d~%" host port))
|
||||
(close socket)
|
||||
(setq *clients* (remove socket *clients* :key #'car)))
|
||||
|
||||
(echo-server 12321)
|
||||
38
Task/Echo-server/Common-Lisp/echo-server-2.lisp
Normal file
38
Task/Echo-server/Common-Lisp/echo-server-2.lisp
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
(defpackage :echo
|
||||
(:use :cl :usocket :cl-actors)
|
||||
(:import-from :cl-actors #:self))
|
||||
(in-package :echo)
|
||||
|
||||
(defun read-line-no-hang (stream)
|
||||
"Reads a line from stream. Returns a partial line rather than hanging."
|
||||
(apply #'values
|
||||
(loop for char = (read-char-no-hang stream nil :eof)
|
||||
until (or (null char) (eq :eof char) (char= #\newline char))
|
||||
collect char into str
|
||||
finally (return (list (when str (coerce str 'string)) char)))))
|
||||
|
||||
(defactor tcp-server (server handler connections) (message)
|
||||
(loop for ready in (wait-for-input (cons server connections) :ready-only t)
|
||||
do (if (typep ready 'stream-server-usocket)
|
||||
(push (socket-accept server) connections)
|
||||
(multiple-value-bind (line last-char) (read-line-no-hang (socket-stream ready))
|
||||
(when (eq last-char :eof)
|
||||
(delete ready connections)
|
||||
(socket-close ready))
|
||||
(send handler ready line))))
|
||||
(send self nil)
|
||||
next)
|
||||
|
||||
(defactor echo-handler (stream) (socket input)
|
||||
(format stream "~a~%" input)
|
||||
(format (socket-stream socket) input)
|
||||
next)
|
||||
|
||||
(defparameter +port+ 12321)
|
||||
(defparameter *handler* (echo-handler :stream *standard-input*)
|
||||
"Accepts and deals with socket messages.")
|
||||
(defparameter *server*
|
||||
(tcp-server :server (socket-listen "127.0.0.1" +port+)
|
||||
:handler *handler*)
|
||||
"Listens on the specified address+port. Passes socket input to specified handler.")
|
||||
(send *server* :ping) ;; get the server started
|
||||
22
Task/Echo-server/Common-Lisp/echo-server-3.lisp
Normal file
22
Task/Echo-server/Common-Lisp/echo-server-3.lisp
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
(defactor tcp-naive-client (sock) (message)
|
||||
(format (socket-stream sock) message)
|
||||
(force-output (socket-stream sock))
|
||||
next)
|
||||
|
||||
(defparameter *client* (tcp-naive-client :sock (socket-connect "127.0.0.1" +port+)))
|
||||
|
||||
(send *client* "test~%test")
|
||||
;; should print
|
||||
;; test
|
||||
;; test
|
||||
|
||||
(send *client* "test")
|
||||
;; should print
|
||||
;; test
|
||||
|
||||
(defparameter *client2* (tcp-naive-client :sock (socket-connect "127.0.0.1" +port+)))
|
||||
|
||||
(send *client2* "woo!")
|
||||
;; should print
|
||||
;; woo!
|
||||
;; despite the fact that *client* isn't reading anything, and didn't terminate its last message with a newline
|
||||
20
Task/Echo-server/D/echo-server-1.d
Normal file
20
Task/Echo-server/D/echo-server-1.d
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import std.array, std.socket;
|
||||
|
||||
void main() {
|
||||
auto listener = new TcpSocket;
|
||||
assert(listener.isAlive);
|
||||
listener.bind(new InternetAddress(12321));
|
||||
listener.listen(10);
|
||||
|
||||
Socket currSock;
|
||||
uint bytesRead;
|
||||
ubyte[1] buff;
|
||||
|
||||
while (true) {
|
||||
currSock = listener.accept();
|
||||
while ((bytesRead = currSock.receive(buff)) > 0)
|
||||
currSock.send(buff);
|
||||
currSock.close();
|
||||
buff.clear();
|
||||
}
|
||||
}
|
||||
109
Task/Echo-server/D/echo-server-2.d
Normal file
109
Task/Echo-server/D/echo-server-2.d
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
import std.stdio, std.socket, std.array;
|
||||
|
||||
void main() {
|
||||
enum ushort port = 7;
|
||||
enum int backlog = 10;
|
||||
enum int max_connections = 60;
|
||||
enum BUFFER_SIZE = 16;
|
||||
|
||||
auto listener = new TcpSocket;
|
||||
assert(listener.isAlive);
|
||||
listener.bind(new InternetAddress(port));
|
||||
listener.listen(backlog);
|
||||
debug writeln("Listening on port ", port);
|
||||
|
||||
// Room for listener.
|
||||
auto sset = new SocketSet(max_connections + 1);
|
||||
|
||||
Socket[] sockets;
|
||||
char[BUFFER_SIZE] buf;
|
||||
|
||||
for (;; sset.reset()) {
|
||||
sset.add(listener);
|
||||
foreach (each; sockets)
|
||||
sset.add(each);
|
||||
|
||||
// Update socket set with only those sockets that have data
|
||||
// avaliable for reading. Options are for read, write,
|
||||
// and error.
|
||||
Socket.select(sset, null, null);
|
||||
|
||||
// Read the data from each socket remaining, and handle
|
||||
// the request.
|
||||
for (int i = 0; ; i++) {
|
||||
NEXT:
|
||||
if (i == sockets.length)
|
||||
break;
|
||||
if (sset.isSet(sockets[i])) {
|
||||
int read = sockets[i].receive(buf);
|
||||
if (Socket.ERROR == read) {
|
||||
debug writeln("Connection error.");
|
||||
goto SOCK_DOWN;
|
||||
} else if (read == 0) {
|
||||
debug {
|
||||
try {
|
||||
// If the connection closed due to an
|
||||
// error, remoteAddress() could fail.
|
||||
writefln("Connection from %s closed.",
|
||||
sockets[i].remoteAddress()
|
||||
.toString());
|
||||
} catch (SocketException) {
|
||||
writeln("Connection closed.");
|
||||
}
|
||||
}
|
||||
SOCK_DOWN:
|
||||
sockets[i].close(); //Release socket resources now.
|
||||
|
||||
// Remove from socket from sockets, and id from
|
||||
// threads.
|
||||
if (i != sockets.length - 1)
|
||||
sockets[i] = sockets.back;
|
||||
sockets.length--;
|
||||
debug writeln("\tTotal connections: ",
|
||||
sockets.length);
|
||||
goto NEXT; // -i- is still the NEXT index.
|
||||
} else {
|
||||
debug
|
||||
writefln("Received %d bytes from %s:"
|
||||
~ "\n-----\n%s\n-----",
|
||||
read,
|
||||
sockets[i].remoteAddress().toString(),
|
||||
buf[0 .. read]);
|
||||
|
||||
// Echo what was sent.
|
||||
sockets[i].send(buf[0 .. read]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Connection request.
|
||||
if (sset.isSet(listener)) {
|
||||
Socket sn;
|
||||
try {
|
||||
if (sockets.length < max_connections) {
|
||||
sn = listener.accept();
|
||||
debug writefln("Connection from %s established.",
|
||||
sn.remoteAddress().toString());
|
||||
assert(sn.isAlive);
|
||||
assert(listener.isAlive);
|
||||
sockets ~= sn;
|
||||
debug writefln("\tTotal connections: %d",
|
||||
sockets.length);
|
||||
} else {
|
||||
sn = listener.accept();
|
||||
debug writefln("Rejected connection from %s;"
|
||||
~ " too many connections.",
|
||||
sn.remoteAddress().toString());
|
||||
assert(sn.isAlive);
|
||||
sn.close();
|
||||
assert(!sn.isAlive);
|
||||
assert(listener.isAlive);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
debug writefln("Error accepting: %s", e.toString());
|
||||
if (sn)
|
||||
sn.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
58
Task/Echo-server/Delphi/echo-server.delphi
Normal file
58
Task/Echo-server/Delphi/echo-server.delphi
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
program EchoServer;
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
|
||||
uses SysUtils, IdContext, IdTCPServer;
|
||||
|
||||
type
|
||||
TEchoServer = class
|
||||
private
|
||||
FTCPServer: TIdTCPServer;
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
procedure TCPServerExecute(AContext: TIdContext);
|
||||
end;
|
||||
|
||||
constructor TEchoServer.Create;
|
||||
begin
|
||||
FTCPServer := TIdTCPServer.Create(nil);
|
||||
FTCPServer.DefaultPort := 12321;
|
||||
FTCPServer.OnExecute := TCPServerExecute;
|
||||
FTCPServer.Active := True;
|
||||
end;
|
||||
|
||||
destructor TEchoServer.Destroy;
|
||||
begin
|
||||
FTCPServer.Active := False;
|
||||
FTCPServer.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TEchoServer.TCPServerExecute(AContext: TIdContext);
|
||||
var
|
||||
lCmdLine: string;
|
||||
begin
|
||||
lCmdLine := AContext.Connection.IOHandler.ReadLn;
|
||||
Writeln('>' + lCmdLine);
|
||||
AContext.Connection.IOHandler.Writeln('>' + lCmdLine);
|
||||
|
||||
if SameText(lCmdLine, 'QUIT') then
|
||||
begin
|
||||
AContext.Connection.IOHandler.Writeln('Disconnecting');
|
||||
AContext.Connection.Disconnect;
|
||||
end;
|
||||
end;
|
||||
|
||||
var
|
||||
lEchoServer: TEchoServer;
|
||||
begin
|
||||
lEchoServer := TEchoServer.Create;
|
||||
try
|
||||
Writeln('Delphi Echo Server');
|
||||
Writeln('Press Enter to quit');
|
||||
Readln;
|
||||
finally
|
||||
lEchoServer.Free;
|
||||
end;
|
||||
end.
|
||||
23
Task/Echo-server/Erlang/echo-server.erl
Normal file
23
Task/Echo-server/Erlang/echo-server.erl
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
-module(echo).
|
||||
-export([start/0]).
|
||||
|
||||
start() ->
|
||||
spawn(fun () -> {ok, Sock} = gen_tcp:listen(12321, [{packet, line}]),
|
||||
echo_loop(Sock)
|
||||
end).
|
||||
|
||||
echo_loop(Sock) ->
|
||||
{ok, Conn} = gen_tcp:accept(Sock),
|
||||
io:format("Got connection: ~p~n", [Conn]),
|
||||
Handler = spawn(fun () -> handle(Conn) end),
|
||||
gen_tcp:controlling_process(Conn, Handler),
|
||||
echo_loop(Sock).
|
||||
|
||||
handle(Conn) ->
|
||||
receive
|
||||
{tcp, Conn, Data} ->
|
||||
gen_tcp:send(Conn, Data),
|
||||
handle(Conn);
|
||||
{tcp_closed, Conn} ->
|
||||
io:format("Connection closed: ~p~n", [Conn])
|
||||
end.
|
||||
30
Task/Echo-server/Forth/echo-server.fth
Normal file
30
Task/Echo-server/Forth/echo-server.fth
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
include unix/socket.fs
|
||||
|
||||
128 constant size
|
||||
|
||||
: (echo) ( sock buf -- sock buf )
|
||||
begin
|
||||
cr ." waiting..."
|
||||
2dup 2dup size read-socket nip
|
||||
dup 0>
|
||||
while
|
||||
." got: " 2dup type
|
||||
rot write-socket
|
||||
repeat
|
||||
drop drop drop ;
|
||||
|
||||
create buf size allot
|
||||
|
||||
: echo-server ( port -- )
|
||||
cr ." Listening on " dup .
|
||||
create-server
|
||||
dup 4 listen
|
||||
begin
|
||||
dup accept-socket
|
||||
cr ." Connection!"
|
||||
buf ['] (echo) catch
|
||||
cr ." Disconnected (" . ." )"
|
||||
drop close-socket
|
||||
again ;
|
||||
|
||||
12321 echo-server
|
||||
29
Task/Echo-server/Go/echo-server.go
Normal file
29
Task/Echo-server/Go/echo-server.go
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"bufio"
|
||||
)
|
||||
|
||||
func echo(s net.Conn, i int) {
|
||||
fmt.Printf("%d: %v <-> %v\n", i, s.LocalAddr(), s.RemoteAddr())
|
||||
b := bufio.NewReader(s)
|
||||
for {
|
||||
line, e := b.ReadBytes('\n')
|
||||
if e != nil {
|
||||
break
|
||||
}
|
||||
s.Write(line)
|
||||
}
|
||||
fmt.Printf("%d: closed\n", i)
|
||||
}
|
||||
|
||||
func main() {
|
||||
l, e := net.Listen("tcp", ":12321")
|
||||
for i := 0; e == nil; i++ {
|
||||
var s net.Conn
|
||||
s, e = l.Accept()
|
||||
go echo(s, i)
|
||||
}
|
||||
}
|
||||
25
Task/Echo-server/Haskell/echo-server.hs
Normal file
25
Task/Echo-server/Haskell/echo-server.hs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
module Main where
|
||||
import Network (withSocketsDo, accept, listenOn, sClose, PortID(PortNumber))
|
||||
import Control.Monad (forever)
|
||||
import System.IO (hGetLine, hPutStrLn, hFlush, hClose)
|
||||
import System.IO.Error (isEOFError)
|
||||
import Control.Concurrent (forkIO)
|
||||
import Control.Exception (bracket)
|
||||
|
||||
-- For convenience in testing, ensure that the listen socket is closed if the main loop is aborted
|
||||
withListenOn port body = bracket (listenOn port) sClose body
|
||||
|
||||
echo (handle, host, port) = catch (forever doOneLine) stop where
|
||||
doOneLine = do line <- hGetLine handle
|
||||
print (host, port, init line)
|
||||
hPutStrLn handle line
|
||||
hFlush handle
|
||||
stop error = do putStrLn $ "Closed connection from " ++ show (host, port) ++ " due to " ++ show error
|
||||
hClose handle
|
||||
|
||||
main = withSocketsDo $
|
||||
withListenOn (PortNumber 12321) $ \listener ->
|
||||
forever $ do
|
||||
acc@(_, host, port) <- accept listener
|
||||
putStrLn $ "Accepted connection from " ++ show (host, port)
|
||||
forkIO (echo acc)
|
||||
78
Task/Echo-server/Java/echo-server.java
Normal file
78
Task/Echo-server/Java/echo-server.java
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
|
||||
public class EchoServer {
|
||||
ServerSocket serverSocket;
|
||||
public EchoServer(){
|
||||
}
|
||||
|
||||
public void start() {
|
||||
try {
|
||||
serverSocket = new ServerSocket(12321);
|
||||
while(true){
|
||||
Thread clientThread = new Thread(new ClientHandler(serverSocket.accept()));
|
||||
clientThread.start();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
System.out.println("closing server socket");
|
||||
serverSocket.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
EchoServer es = new EchoServer();
|
||||
es.start();
|
||||
}
|
||||
}
|
||||
|
||||
class ClientHandler implements Runnable {
|
||||
private static int numConnections;
|
||||
private int connectionId = 0;
|
||||
Socket clientSocket;
|
||||
|
||||
public ClientHandler(Socket s) {
|
||||
connectionId = numConnections++;
|
||||
System.out.println("handling connection, #" + connectionId);
|
||||
clientSocket = s;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
PrintWriter out = null;
|
||||
BufferedReader in = null;
|
||||
try {
|
||||
out = new PrintWriter(clientSocket.getOutputStream(), true);
|
||||
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
|
||||
String inputLine, outputLine;
|
||||
while((inputLine = in.readLine()) != null){
|
||||
outputLine = inputLine;
|
||||
System.out.println("recieved: " + outputLine);
|
||||
out.write(outputLine+"\n");
|
||||
out.flush();
|
||||
if (outputLine.equals("exit"))
|
||||
break;
|
||||
}
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
out.close();
|
||||
try {
|
||||
in.close();
|
||||
clientSocket.close();
|
||||
System.out.println("closing connection, #" + connectionId);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
20
Task/Echo-server/JavaScript/echo-server.js
Normal file
20
Task/Echo-server/JavaScript/echo-server.js
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
var net = require('net');
|
||||
|
||||
var server = net.createServer(function(conn) {
|
||||
console.log("Connection from " + conn.remoteAddress + " on port " + conn.remotePort);
|
||||
conn.setEncoding("utf8");
|
||||
var buffer = "";
|
||||
|
||||
conn.on("data", function(data) {
|
||||
for(var i = 0; i <= data.length; i++) {
|
||||
var char = data.charAt(i);
|
||||
buffer += char;
|
||||
if(char == "\n") {
|
||||
conn.write(buffer);
|
||||
buffer = "";
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
server.listen(12321, "localhost");
|
||||
31
Task/Echo-server/PHP/echo-server.php
Normal file
31
Task/Echo-server/PHP/echo-server.php
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
$socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
|
||||
socket_bind($socket, '127.0.0.1', 12321);
|
||||
socket_listen($socket);
|
||||
|
||||
$client_count = 0;
|
||||
while (true){
|
||||
if (($client = socket_accept($socket)) === false) continue;
|
||||
$client_count++;
|
||||
|
||||
$client_name = 'Unknown';
|
||||
socket_getpeername($client, $client_name);
|
||||
echo "Client {$client_count} ({$client_name}) connected\n";
|
||||
$pid = pcntl_fork();
|
||||
if($pid == -1) die('Could not fork');
|
||||
if($pid){
|
||||
pcntl_waitpid(-1, $status, WNOHANG);
|
||||
continue;
|
||||
}
|
||||
|
||||
//In a child process
|
||||
while(true){
|
||||
if($input = socket_read($client, 1024)){
|
||||
socket_write($client, $input);
|
||||
} else {
|
||||
socket_shutdown($client);
|
||||
socket_close($client);
|
||||
echo "Client {$client_count} ({$client_name}) disconnected\n";
|
||||
exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
29
Task/Echo-server/Perl/echo-server-1.pl
Normal file
29
Task/Echo-server/Perl/echo-server-1.pl
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
use IO::Socket;
|
||||
my $use_fork = 1;
|
||||
|
||||
my $sock = new IO::Socket::INET (
|
||||
LocalHost => '127.0.0.1',
|
||||
LocalPort => '12321',
|
||||
Proto => 'tcp',
|
||||
Listen => 1, # maximum queued connections
|
||||
Reuse => 1,
|
||||
)
|
||||
or die "socket: $!"; # no newline, so perl appends stuff
|
||||
|
||||
$SIG{CHLD} = 'IGNORE' if $use_fork; # let perl deal with zombies
|
||||
|
||||
print "listening...\n";
|
||||
while (1) {
|
||||
# declare $con 'my' so it's closed by parent every loop
|
||||
my $con = $sock->accept()
|
||||
or die "accept: $!";
|
||||
fork and next if $use_fork; # following are for child only
|
||||
|
||||
print "incoming..\n";
|
||||
print $con $_ while(<$con>); # read each line and write back
|
||||
print "done\n";
|
||||
|
||||
last if $use_fork; # if not forking, loop
|
||||
}
|
||||
|
||||
# child will reach here and close its copy of $sock before exit
|
||||
6
Task/Echo-server/Perl/echo-server-2.pl
Normal file
6
Task/Echo-server/Perl/echo-server-2.pl
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
package Echo;
|
||||
use base 'Net::Server::Fork';
|
||||
sub process_request {
|
||||
print while <STDIN>;
|
||||
}
|
||||
Echo->run(port => 12321, log_level => 3);
|
||||
6
Task/Echo-server/Perl/echo-server-3.pl
Normal file
6
Task/Echo-server/Perl/echo-server-3.pl
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
package Echo;
|
||||
use base 'Net::Server::PreFork';
|
||||
sub process_request {
|
||||
print while <STDIN>;
|
||||
}
|
||||
Echo->run(port => 12321, log_level => 3);
|
||||
16
Task/Echo-server/PicoLisp/echo-server.l
Normal file
16
Task/Echo-server/PicoLisp/echo-server.l
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
(setq Port (port 12321))
|
||||
|
||||
(loop
|
||||
(setq Sock (listen Port)) # Listen
|
||||
(NIL (fork) (close Port)) # Accepted
|
||||
(close Sock) ) # Parent: Close socket and continue
|
||||
|
||||
# Child:
|
||||
(prinl (stamp) " -- (Pid " *Pid ") Client connected from " *Adr)
|
||||
|
||||
(in Sock
|
||||
(until (eof) # Echo lines
|
||||
(out Sock (prinl (line))) ) )
|
||||
|
||||
(prinl (stamp) " -- (Pid " *Pid ") Client disconnected")
|
||||
(bye) # Terminate child
|
||||
33
Task/Echo-server/Python/echo-server.py
Normal file
33
Task/Echo-server/Python/echo-server.py
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import SocketServer
|
||||
|
||||
HOST = "localhost"
|
||||
PORT = 12321
|
||||
|
||||
# this server uses ThreadingMixIn - one thread per connection
|
||||
# replace with ForkMixIn to spawn a new process per connection
|
||||
|
||||
class EchoServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
|
||||
# no need to override anything - default behavior is just fine
|
||||
pass
|
||||
|
||||
class EchoRequestHandler(SocketServer.StreamRequestHandler):
|
||||
"""
|
||||
Handles one connection to the client.
|
||||
"""
|
||||
def handle(self):
|
||||
print "connection from %s" % self.client_address[0]
|
||||
while True:
|
||||
line = self.rfile.readline()
|
||||
if not line: break
|
||||
print "%s wrote: %s" % (self.client_address[0], line.rstrip())
|
||||
self.wfile.write(line)
|
||||
print "%s disconnected" % self.client_address[0]
|
||||
|
||||
|
||||
# Create the server
|
||||
server = EchoServer((HOST, PORT), EchoRequestHandler)
|
||||
|
||||
# Activate the server; this will keep running until you
|
||||
# interrupt the program with Ctrl-C
|
||||
print "server listening on %s:%s" % server.server_address
|
||||
server.serve_forever()
|
||||
8
Task/Echo-server/Racket/echo-server.rkt
Normal file
8
Task/Echo-server/Racket/echo-server.rkt
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#lang racket
|
||||
|
||||
(define listener (tcp-listen 12321))
|
||||
(let echo-server ()
|
||||
(define-values (in out) (tcp-accept listener))
|
||||
(thread (λ () (copy-port in out)
|
||||
(close-output-port out)))
|
||||
(echo-server))
|
||||
20
Task/Echo-server/Ruby/echo-server-1.rb
Normal file
20
Task/Echo-server/Ruby/echo-server-1.rb
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
require 'socket'
|
||||
server = TCPServer.new(12321)
|
||||
|
||||
while (connection = server.accept)
|
||||
Thread.new(connection) do |conn|
|
||||
port, host = conn.peeraddr[1,2]
|
||||
client = "#{host}:#{port}"
|
||||
puts "#{client} is connected"
|
||||
begin
|
||||
loop do
|
||||
line = conn.readline
|
||||
puts "#{client} says: #{line}"
|
||||
conn.puts(line)
|
||||
end
|
||||
rescue EOFError
|
||||
conn.close
|
||||
puts "#{client} has disconnected"
|
||||
end
|
||||
end
|
||||
end
|
||||
18
Task/Echo-server/Ruby/echo-server-2.rb
Normal file
18
Task/Echo-server/Ruby/echo-server-2.rb
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
require 'socket'
|
||||
|
||||
Socket.tcp_server_loop(12321) do |conn, addr|
|
||||
Thread.new do
|
||||
client = "#{addr.ip_address}:#{addr.ip_port}"
|
||||
puts "#{client} is connected"
|
||||
begin
|
||||
loop do
|
||||
line = conn.readline
|
||||
puts "#{client} says: #{line}"
|
||||
conn.puts(line)
|
||||
end
|
||||
rescue EOFError
|
||||
conn.close
|
||||
puts "#{client} has disconnected"
|
||||
end
|
||||
end
|
||||
end
|
||||
41
Task/Echo-server/Scheme/echo-server.ss
Normal file
41
Task/Echo-server/Scheme/echo-server.ss
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
; Needed in Guile for read-line
|
||||
(use-modules (ice-9 rdelim))
|
||||
|
||||
; Variable used to hold child PID returned from forking
|
||||
(define child #f)
|
||||
|
||||
; Start listening on port 12321 for connections from any address
|
||||
(let ((s (socket PF_INET SOCK_STREAM 0)))
|
||||
(setsockopt s SOL_SOCKET SO_REUSEADDR 1)
|
||||
(bind s AF_INET INADDR_ANY 12321)
|
||||
(listen s 5) ; Queue size of 5
|
||||
|
||||
(simple-format #t "Listening for clients in pid: ~S" (getpid))
|
||||
(newline)
|
||||
|
||||
; Wait for connections forever
|
||||
(while #t
|
||||
(let* ((client-connection (accept s))
|
||||
(client-details (cdr client-connection))
|
||||
(client (car client-connection)))
|
||||
; Once something connects fork
|
||||
(set! child (primitive-fork))
|
||||
(if (zero? child)
|
||||
(begin
|
||||
; Then have child fork to avoid zombie children (grandchildren aren't our responsibility)
|
||||
(set! child (primitive-fork))
|
||||
(if (zero? child)
|
||||
(begin
|
||||
; Display some connection details
|
||||
(simple-format #t "Got new client connection: ~S" client-details)
|
||||
(newline)
|
||||
(simple-format #t "Client address: ~S"
|
||||
(gethostbyaddr (sockaddr:addr client-details)))
|
||||
(newline)
|
||||
; Wait for input from client and then echo the input back forever (or until client quits)
|
||||
(do ((line (read-line client)(read-line client))) ((zero? 1))
|
||||
(display line client)(newline client))))
|
||||
; Child exits after spawning grandchild.
|
||||
(primitive-exit))
|
||||
; Parent waits for child to finish spawning grandchild
|
||||
(waitpid child)))))
|
||||
21
Task/Echo-server/Tcl/echo-server-1.tcl
Normal file
21
Task/Echo-server/Tcl/echo-server-1.tcl
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# How to handle an incoming new connection
|
||||
proc acceptEcho {chan host port} {
|
||||
puts "opened connection from $host:$port"
|
||||
fconfigure $chan -blocking 0 -buffering line -translation crlf
|
||||
fileevent $chan readable [list echo $chan $host $port]
|
||||
}
|
||||
|
||||
# How to handle an incoming message on a connection
|
||||
proc echo {chan host port} {
|
||||
if {[gets $chan line] >= 0} {
|
||||
puts $chan $line
|
||||
} elseif {[eof $chan]} {
|
||||
close $chan
|
||||
puts "closed connection from $host:$port"
|
||||
}
|
||||
# Other conditions causing a short read need no action
|
||||
}
|
||||
|
||||
# Make the server socket and wait for connections
|
||||
socket -server acceptEcho -myaddr localhost 12321
|
||||
vwait forever
|
||||
16
Task/Echo-server/Tcl/echo-server-2.tcl
Normal file
16
Task/Echo-server/Tcl/echo-server-2.tcl
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# How to handle an incoming new connection
|
||||
proc acceptEcho {chan host port} {
|
||||
puts "opened connection from $host:$port"
|
||||
fconfigure $chan -translation binary -buffering none
|
||||
fcopy $chan $chan -command [list done $chan $host $port]
|
||||
}
|
||||
|
||||
# Called to finalize the connection
|
||||
proc done {chan host port args} {
|
||||
puts "closed connection from $host:$port"
|
||||
close $chan
|
||||
}
|
||||
|
||||
# Make the server socket and wait for connections
|
||||
socket -server acceptEcho -myaddr localhost 12321
|
||||
vwait forever
|
||||
Loading…
Add table
Add a link
Reference in a new issue