This commit is contained in:
Ingy döt Net 2013-04-10 16:57:12 -07:00
parent 518da4a923
commit 764da6cbbb
6144 changed files with 83610 additions and 11 deletions

View 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.

View file

@ -0,0 +1,2 @@
---
note: Networking and Web Interaction

View 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;

View 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

View 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

View 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;
}

View 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)

View 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"

View 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)

View 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

View 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

View 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();
}
}

View 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();
}
}
}
}

View 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.

View 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.

View 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

View 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)
}
}

View 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)

View 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();
}
}
}
}

View 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");

View 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();
}
}
}

View 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

View 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);

View 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);

View 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

View 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()

View 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))

View 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

View 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

View 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)))))

View 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

View 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