Hello world/Web server

From Rosetta Code
Revision as of 08:43, 30 October 2011 by Rdm (talk | contribs) (J draft)
Task
Hello world/Web server
You are encouraged to solve this task according to the task description, using any language you may know.

The browser is the new GUI!

The task is to serve our standard text "Goodbye, World!" to http://localhost:8080/ so that it can be viewed with a web browser. The provided solution must start or implement a server that accepts multiple client connections and serves text as requested.

Note that starting a web browser or opening a new window with this URL is not part of the task. Additionally, it is permissible to serve the provided page as a plain text file (there is no requirement to serve properly formatted HTML here). The browser will generally do the right thing with simple text like this.

C

This is, um, slightly longer than what other languages would be. <lang C>#include <stdio.h>

  1. include <stdlib.h>
  2. include <unistd.h>
  3. include <sys/types.h>
  4. include <sys/socket.h>
  5. include <netinet/in.h>
  6. include <netdb.h>
  7. include <arpa/inet.h>
  8. include <err.h>

char response[] = "HTTP/1.1 200 OK\r\n" "Content-Type: text/html; charset=UTF-8\r\n\r\n" "<doctype !html><html><head><title>Bye-bye baby bye-bye</title>" "<style>body { background-color: #111 }" "h1 { font-size:4cm; text-align: center; color: black;" " text-shadow: 0 0 2mm red}</style></head>"

"<body>

Goodbye, world!

</body></html>\r\n";

int main() { int one = 1, client_fd; struct sockaddr_in svr_addr, cli_addr; socklen_t sin_len = sizeof(cli_addr);

int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) err(1, "can't open socket");

setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));

int port = 8080; svr_addr.sin_family = AF_INET; svr_addr.sin_addr.s_addr = INADDR_ANY; svr_addr.sin_port = htons(port);

if (bind(sock, (struct sockaddr *) &svr_addr, sizeof(svr_addr)) == -1) { close(sock); err(1, "Can't bind"); }

listen(sock, 5); while (1) { client_fd = accept(sock, (struct sockaddr *) &cli_addr, &sin_len); printf("got connection\n");

if (client_fd == -1) { perror("Can't accept"); continue; }

write(client_fd, response, sizeof(response) - 1); /*-1:'\0'*/ close(client_fd); } }</lang>

C#

<lang CSharp>using System.Text; using System.Net.Sockets; using System.Net;

namespace WebServer {

   class GoodByeWorld
   {        
       static void Main(string[] args)
       {
           const string msg = "<html>\n<body>\nGoodbye, world!\n</body>\n</html>\n";        
           const int port = 8080;
           bool serverRunning = true;
           TcpListener tcpListener = new TcpListener(IPAddress.Any, port);
           tcpListener.Start();
           while (serverRunning)
           {
               Socket socketConnection = tcpListener.AcceptSocket();
               byte[] bMsg = Encoding.ASCII.GetBytes(msg.ToCharArray(), 0, (int)msg.Length);
               socketConnection.Send(bMsg);
               socketConnection.Disconnect(true);
           }
       }
   }

}</lang>

Delphi

<lang Delphi>program HelloWorldWebServer;

{$APPTYPE CONSOLE}

uses SysUtils, IdContext, IdCustomHTTPServer, IdHTTPServer;

type

 TWebServer = class
 private
   FHTTPServer: TIdHTTPServer;
 public
   constructor Create;
   destructor Destroy; override;
   procedure HTTPServerCommandGet(AContext: TIdContext;
     ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
 end;

constructor TWebServer.Create; begin

 FHTTPServer := TIdHTTPServer.Create(nil);
 FHTTPServer.DefaultPort := 8080;
 FHTTPServer.OnCommandGet := HTTPServerCommandGet;
 FHTTPServer.Active := True;

end;

destructor TWebServer.Destroy; begin

 FHTTPServer.Active := False;
 FHTTPServer.Free;
 inherited Destroy;

end;

procedure TWebServer.HTTPServerCommandGet(AContext: TIdContext;

 ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);

begin

 AResponseInfo.ContentText := 'Goodbye, World!';

end;

var

 lWebServer: TWebServer;

begin

 lWebServer := TWebServer.Create;
 try
   Writeln('Delphi Hello world/Web server ');
   Writeln('Press Enter to quit');
   Readln;
 finally
   lWebServer.Free;
 end;

end.</lang>

Fantom

<lang fantom> using web using wisp

const class HelloMod : WebMod // provides the content {

 override Void onGet ()
 {
   res.headers["Content-Type"] = "text/plain; charset=utf-8"
   res.out.print ("Goodbye, World!")
 }

}

class HelloWeb {

 Void main ()
 {
   WispService // creates the web service
   {
     port = 8080
     root = HelloMod()
   }.start
   while (true) {} // stay running
 }

} </lang>

Go

<lang go>package main

import (

   "http"
   "fmt"

)

func main() {

   http.HandleFunc("/",
       func(w http.ResponseWriter, req *http.Request) {
           fmt.Fprintln(w, "Goodbye, World!")
       })
   if err := http.ListenAndServe(":8080", nil); err != nil {
       fmt.Println(err)
   }

}</lang>

J

If the desire is to use the browser as a gui, the easiest thing to do would be to download j7, edit the jhs script to start on port 8080, start jhs, visit http://127.0.0.1:8080/jijx then enter the text:

<lang j>'Goodbye, World!'</lang>

This will compute the desired result and display it (actually, it will be displayed twice since the original string will also be displayed). This would be even simpler if you could just use the default jhs port (65001)... Alternatively, a jhs form could be used (but this would not have the exact url structure specified).

However, if the desire is to implement the task exactly, any of approaches at j:JWebServer might be used.

For example, here is a web server which ignores the client's response and always returns Goodbye, Worl:

<lang j>hello=: verb define

8080 webserver0 y. NB. try to use port 8080 by default
port=: x.
require 'socket'
coinsert 'jsocket'
sdclose ; sdcheck sdgetsockets 
server=: {. ; sdcheck sdsocket 
sdcheck sdbind server; AF_INET; ; port
sdcheck sdlisten server, 1
while. 1 do.
 while. 
   server e. ready=: >{. sdcheck sdselect (sdcheck sdgetsockets ),;;<1e3
 do. 
   sdcheck sdaccept server
 end.
 for_socket. ready do.
  request=: ; sdcheck sdrecv socket, 65536 0
  sdcheck (socket responseFor request) sdsend socket, 0
  sdcheck sdclose socket
 end.
end.

)

responseFor=: dyad define

'HTTP/1.0 200 OK',CRLF,'Content-Type: text/plain',CRLF,CRLF,'Goodbye, World!',CRLF

)</lang>

To deploy this server, once it has been defined, run

<lang j>hello</lang>


Java

Multiple requests will be served in the order that they reach the server, with a queue size limit of 50 waiting requests imposed by default in the ServerSocket class (may be changed by adding a second positive integer argument to the ServerSocket constructor). <lang java>import java.io.IOException; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket;

public class HelloWorld{ public static void main(String[] args) throws IOException{ ServerSocket listener = new ServerSocket(8080); while(true){ Socket sock = listener.accept(); new PrintWriter(sock.getOutputStream(), true). println("Goodbye, World!"); sock.close(); } } }</lang>

OCaml

This code is derived from this ocaml-unix documentation.

<lang ocaml>let try_finalise f x finally y =

 let res = try f x with e -> finally y; raise e in
 finally y;
 res

let rec restart_on_EINTR f x =

 try f x with Unix.Unix_error (Unix.EINTR, _, _) -> restart_on_EINTR f x

let double_fork_treatment server service (client_descr, _ as client) =

 let treat () =
   match Unix.fork () with
   | 0 ->
       if Unix.fork () <> 0 then exit 0;
       Unix.close server; service client; exit 0
   | k ->
       ignore (restart_on_EINTR (Unix.waitpid []) k)
 in
 try_finalise treat () Unix.close client_descr

let install_tcp_server_socket addr =

 let s = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
 try
   Unix.bind s addr;
   Unix.listen s 10;
   s
 with e -> Unix.close s; raise e

let tcp_server treat_connection addr =

 ignore (Sys.signal Sys.sigpipe Sys.Signal_ignore);
 let server_sock = install_tcp_server_socket addr in
 while true do
   let client = restart_on_EINTR Unix.accept server_sock in 
   treat_connection server_sock client 
 done

let server () =

 let port = 8080 in
 let host = (Unix.gethostbyname (Unix.gethostname())).Unix.h_addr_list.(0) in 
 let addr = Unix.ADDR_INET (host, port) in
 let treat sock (client_sock, client_addr as client) =
   let service (s, _) =
     let response = "\
       HTTP/1.1 200 OK\r\n\
       Content-Type: text/html; charset=UTF-8\r\n\r\n\
       <html><head><title>Goodbye, world!</title>\
       <style>body { background-color: #0FF }\
       h1 { font-size:3em; color: black; }</style></head>\

<body>

Goodbye, world!

</body></html>\r\n"

     in
     Unix.write s response 0 (String.length response);
   in
   double_fork_treatment sock service client
 in
 tcp_server treat addr

let _ =

 Unix.handle_unix_error server ()</lang>

Perl

<lang Perl>use Socket;

my $port = 8080; my $protocol = getprotobyname( "tcp" );

socket( SOCK, PF_INET, SOCK_STREAM, $protocol ) or die "couldn't open a socket: $!";

 # PF_INET to indicate that this socket will connect to the internet domain
 # SOCK_STREAM indicates a TCP stream, SOCK_DGRAM would indicate UDP communication
 

setsockopt( SOCK, SOL_SOCKET, SO_REUSEADDR, 1 ) or die "couldn't set socket options: $!";

 # SOL_SOCKET to indicate that we are setting an option on the socket instead of the protocol
 # mark the socket reusable

bind( SOCK, sockaddr_in($port, INADDR_ANY) ) or die "couldn't bind socket to port $port: $!";

 # bind our socket to $port, allowing any IP to connect

listen( SOCK, SOMAXCONN ) or die "couldn't listen to port $port: $!";

 # start listening for incoming connections

while( accept(CLIENT, SOCK) ){

 print CLIENT "HTTP/1.1 200 OK\r\n" .
              "Content-Type: text/html; charset=UTF-8\r\n\r\n" .
              "<html><head><title>Goodbye, world!</title></head><body>Goodbye, world!</body></html>\r\n";
 close CLIENT;

}</lang>

Various modules exist for using sockets, including the popular IO::Socket which provides a simpler and more friendly OO interface for the socket layer. Here is the solution using this module:

<lang Perl>use IO::Socket::INET;

my $sock = new IO::Socket::INET ( LocalHost => "127.0.0.1",

                                 LocalPort => "8080",
                                 Proto     => "tcp",
                                 Listen    => 1,
                                 Reuse     => 1, ) or die "Could not create socket: $!";

while( my $client = $sock->accept() ){

 print $client "HTTP/1.1 200 OK\r\n" .
               "Content-Type: text/html; charset=UTF-8\r\n\r\n" .
               "<html><head><title>Goodbye, world!</title></head><body>Goodbye, world!</body></html>\r\n";
 close $client;

}</lang>

Using Perl's glue power, provide a suicide note with visitor counter via netcat:<lang Perl>while (++(our $vn)) { open NC, "|-", qw(nc -l -p 8080 -q 1); print NC "HTTP/1.0 200 OK\xd\xa", "Content-type: text/plain; charset=utf-8\xd\xa\xd\xa", "Goodbye, World! (hello, visitor No. $vn!)\xd\xa"; }</lang>

PicoLisp

Contents of the file "goodbye.l": <lang PicoLisp>(html 0 "Bye" NIL NIL

  "Goodbye, World!" )</lang>

Start server:

$ pil @lib/http.l @lib/xhtml.l -'server 8080 "goodbye.l"' -wait

PureBasic

<lang PureBasic> If InitNetwork() = 0 MessageRequester("Error", "Can't initialize the network !") End EndIf

Port = 8080

If CreateNetworkServer(0, Port) Repeat Delay(1) SEvent = NetworkServerEvent() If SEvent ClientID = EventClient() Select SEvent Case #PB_NetworkEvent_Data SendNetworkData(ClientID,@"Goodbye, World!",Len("Goodbye, World!")) CloseNetworkConnection(ClientID) EndSelect EndIf ForEver Else MessageRequester("Error", "Can't create the server (port in use ?).") EndIf </lang>

PHP

<lang PHP><?php

                    // AF_INET6 for IPv6  // IP

$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die('Failed to create socket!');

                 // '127.0.0.1' to limit only to localhost // Port

socket_bind($socket, 0, 8080); socket_listen($socket);

$msg = '<html><head><title>Goodbye, world!</title></head><body>Goodbye, world!</body></html>';

for (;;) {

   // @ is used to stop PHP from spamming with error messages if there is no connection
   if ($client = @socket_accept($socket)) {
       socket_write($client, "HTTP/1.1 200 OK\r\n" .
              "Content-length: " . strlen($msg) . "\r\n" .
              "Content-Type: text/html; charset=UTF-8\r\n\r\n" .
              $msg);
   }
   usleep(100000); // limits CPU usage by sleeping after doing every request

}</lang>

Python

<lang Python>def app(environ, start_response):

   start_response('200 OK', [])
   yield "Goodbye, World!"

if __name__ == '__main__':

   from wsgiref.simple_server import make_server
   server = make_server('127.0.0.1', 8080, app)
   server.serve_forever()</lang>

Ruby

Using the WEBrick module from Ruby's standard library.

<lang ruby>require 'webrick' server = WEBrick::HTTPServer.new(:Port => 8080) server.mount_proc('/') {|request, response| response.body = "Goodbye, World!"} trap("INT") {server.shutdown} server.start</lang>

Tcl

This version is adapted from the Tcler's Wiki. <lang tcl>proc accept {chan addr port} {

   while {[gets $chan] ne ""} {}
   puts $chan "HTTP/1.1 200 OK\nConnection: close\nContent-Type: text/plain\n"
   puts $chan "Goodbye, World!"
   close $chan

} socket -server accept 8080 vwait forever</lang>