Skip to content

carpentry-org/sockets

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

socket

A networking library for Carp with TCP, UDP, Unix domain sockets, buffered I/O, and I/O multiplexing.

Installation

(load "git@github.com:carpentry-org/socket@0.1.0")

Usage

TCP Server

(match (TcpListener.bind "0.0.0.0" 8080)
  (Result.Success listener)
    (do
      (TcpListener.while-accept &listener client
        (match (TcpStream.read &client)
          (Result.Success msg) (ignore (TcpStream.send &client &msg))
          _ ()))
      (TcpListener.close listener))
  (Result.Error e) (IO.errorln &e))

TCP Client

(match (TcpStream.connect "example.com" 80)
  (Result.Success s)
    (do
      (ignore (TcpStream.send &s "GET / HTTP/1.0\r\n\r\n"))
      (match (TcpStream.read &s)
        (Result.Success data) (println* &data)
        _ ())
      (TcpStream.close s))
  (Result.Error e) (IO.errorln &e))

Buffered I/O

Wrap any TcpStream in a BufReader for line-oriented reading:

(match (TcpStream.connect "example.com" 80)
  (Result.Success s)
    (let [br (TcpStream.buffered s)]
      (do
        (BufReader.write &br "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n")
        (ignore (BufReader.flush &br))
        (match (BufReader.read-line &br)
          (Result.Success line) (println* &line)
          _ ())
        (BufReader.delete br)))
  _ ())

UDP

(match (UdpSocket.bind "0.0.0.0" 9999)
  (Result.Success sock)
    (do
      (ignore (UdpSocket.send-to &sock "127.0.0.1" 9999 &data))
      (match (UdpSocket.recv-from &sock)
        (Result.Success p)
          (println* "from " (Pair.b &p) ": " (Array.length (Pair.a &p)) " bytes")
        _ ())
      (UdpSocket.close sock))
  _ ())

Unix Domain Sockets

(match (UnixListener.bind "/tmp/my.sock")
  (Result.Success listener)
    (do
      (UnixListener.while-accept &listener client
        (ignore (UnixStream.send &client "hello")))
      (UnixListener.close listener))
  _ ())

I/O Multiplexing

Monitor multiple sockets for readiness using kqueue (macOS) or epoll (Linux):

(match (Poll.create)
  (Result.Success poll)
    (do
      (ignore (Poll.add-read &poll &listener))
      (match (Poll.wait &poll 1000)
        (Result.Success events)
          (for [i 0 (Array.length &events)]
            (let [e (Array.unsafe-nth &events i)]
              (when (PollEvent.readable e)
                (println* "fd " (PollEvent.fd e) " is readable"))))
        _ ())
      (Poll.close poll))
  _ ())

Types

Type Purpose
TcpListener Bind, listen, accept TCP connections
TcpStream Connected TCP socket (send, read, keep-alive)
UdpSocket UDP datagram socket (send-to, recv-from)
UnixListener Unix domain socket server
UnixStream Unix domain socket connection
Poll I/O multiplexer (kqueue/epoll)
PollEvent Readiness notification from Poll
BufReader Buffered I/O (from the bufio library)

All fallible operations return (Result T String).

Socket Options

(TcpStream.set-nodelay &s)         ; disable Nagle's algorithm
(TcpStream.set-keepalive &s 1)     ; enable TCP keep-alive
(TcpStream.set-timeout &s 30)      ; read/write timeout in seconds
(TcpStream.set-linger &s 5)        ; linger on close for 5 seconds
(TcpStream.set-send-buffer &s 65536)
(TcpStream.set-recv-buffer &s 65536)
(TcpStream.connect-timeout "host" 80 5) ; connect with 5s timeout

Testing

carp -x test/tcp_test.carp
carp -x test/unix_test.carp
carp -x test/poll_test.carp

Have fun!

About

A simple socket API for Carp

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages