Next: , Previous: , Up: Packages   [Contents][Index]

5.13 Sockets

These procedures (defined in socket.c) provide a Scheme interface to most of the C socket library. For more information on sockets, See Sockets in The GNU C Library Reference Manual.


5.13.1 Host and Other Inquiries

Constant: af_inet
Constant: af_unix

Integer family codes for Internet and Unix sockets, respectively.

Function: gethost host-spec
Function: gethost

Returns a vector of information for the entry for HOST-SPEC or the next entry if HOST-SPEC isn’t given. The information is:

  1. host name string
  2. list of host aliases strings
  3. integer address type (AF_INET)
  4. integer size of address entries (in bytes)
  5. list of integer addresses
Function: sethostent stay-open
Function: sethostent

Rewinds the host entry table back to the begining if given an argument. If the argument stay-open is #f queries will be be done using UDP datagrams. Otherwise, a connected TCP socket will be used. When called without an argument, the host table is closed.

Function: getnet name-or-number
Function: getnet

Returns a vector of information for the entry for name-or-number or the next entry if an argument isn’t given. The information is:

  1. official network name string
  2. list of network aliases strings
  3. integer network address type (AF_INET)
  4. integer network number
Function: setnetent stay-open
Function: setnetent

Rewinds the network entry table back to the begining if given an argument. If the argument stay-open is #f the table will be closed between calls to getnet. Otherwise, the table stays open. When called without an argument, the network table is closed.

Function: getproto name-or-number
Function: getproto

Returns a vector of information for the entry for name-or-number or the next entry if an argument isn’t given. The information is:

  1. official protocol name string
  2. list of protocol aliases strings
  3. integer protocol number
Function: setprotoent stay-open
Function: setprotoent

Rewinds the protocol entry table back to the begining if given an argument. If the argument stay-open is #f the table will be closed between calls to getproto. Otherwise, the table stays open. When called without an argument, the protocol table is closed.

Function: getserv name-or-port-number protocol
Function: getserv

Returns a vector of information for the entry for name-or-port-number and protocol or the next entry if arguments aren’t given. The information is:

  1. official service name string
  2. list of service aliases strings
  3. integer port number
  4. protocol
Function: setservent stay-open
Function: setservent

Rewinds the service entry table back to the begining if given an argument. If the argument stay-open is #f the table will be closed between calls to getserv. Otherwise, the table stays open. When called without an argument, the service table is closed.


Next: , Previous: , Up: Sockets   [Contents][Index]

5.13.2 Internet Addresses and Socket Names

Function: inet:string->address string

Returns the host address number (integer) for host string or #f if not found.

Function: inet:address->string address

Converts an internet (integer) address to a string in numbers and dots notation.

Function: inet:network address

Returns the network number (integer) specified from address or #f if not found.

Function: inet:local-network-address address

Returns the integer for the address of address within its local network or #f if not found.

Function: inet:make-address network local-address

Returns the Internet address of local-address in network.

The type socket-name is used for inquiries about open sockets in the following procedures:

Function: getsockname socket

Returns the socket-name of socket. Returns #f if unsuccessful or socket is closed.

Function: getpeername socket

Returns the socket-name of the socket connected to socket. Returns #f if unsuccessful or socket is closed.

Function: socket-name:family socket-name

Returns the integer code for the family of socket-name.

Function: socket-name:port-number socket-name

Returns the integer port number of socket-name.

Function: socket-name:address socket-name

Returns the integer Internet address for socket-name.


5.13.3 Socket

When a port is returned from one of these calls it is unbuffered. This allows both reading and writing to the same port to work. If you want buffered ports you can (assuming sock-port is a socket i/o port):

(require 'i/o-extensions)
(define i-port (duplicate-port sock-port "r"))
(define o-port (duplicate-port sock-port "w"))
Function: make-stream-socket family
Function: make-stream-socket family protocol

Returns a SOCK_STREAM socket of type family using protocol. If family has the value AF_INET, SO_REUSEADDR will be set. The integer argument protocol corresponds to the integer protocol numbers returned (as vector elements) from (getproto). If the protocol argument is not supplied, the default (0) for the specified family is used. SCM sockets look like ports opened for neither reading nor writing.

Function: make-stream-socketpair family
Function: make-stream-socketpair family protocol

Returns a pair (cons) of connected SOCK_STREAM (socket) ports of type family using protocol. Many systems support only socketpairs of the af-unix family. The integer argument protocol corresponds to the integer protocol numbers returned (as vector elements) from (getproto). If the protocol argument is not supplied, the default (0) for the specified family is used.

Function: socket:shutdown socket how

Makes socket no longer respond to some or all operations depending on the integer argument how:

  1. Further input is disallowed.
  2. Further output is disallowed.
  3. Further input or output is disallowed.

Socket:shutdown returns socket if successful, #f if not.

Function: socket:connect inet-socket host-number port-number
Function: socket:connect unix-socket pathname

Returns socket (changed to a read/write port) connected to the Internet socket on host host-number, port port-number or the Unix socket specified by pathname. Returns #f if not successful.

Function: socket:bind inet-socket port-number
Function: socket:bind unix-socket pathname

Returns inet-socket bound to the integer port-number or the unix-socket bound to new socket in the file system at location pathname. Returns #f if not successful. Binding a unix-socket creates a socket in the file system that must be deleted by the caller when it is no longer needed (using delete-file).

Function: socket:listen socket backlog

The bound (see bind) socket is readied to accept connections. The positive integer backlog specifies how many pending connections will be allowed before further connection requests are refused. Returns socket (changed to a read-only port) if successful, #f if not.

Function: char-ready? listen-socket

The input port returned by a successful call to socket:listen can be polled for connections by char-ready? (see char-ready?). This avoids blocking on connections by socket:accept.

Function: socket:accept socket

Accepts a connection on a bound, listening socket. Returns an input/output port for the connection.

The following example is not too complicated, yet shows the use of sockets for multiple connections without input blocking.

;;;; Scheme chat server

;;; This program implements a simple `chat' server which accepts
;;; connections from multiple clients, and sends to all clients any
;;; characters received from any client.

;;; To connect to chat `telnet localhost 8001'

(require 'socket)
(require 'i/o-extensions)

(let ((listener-socket (socket:bind (make-stream-socket af_inet) 8001))
      (connections '()))
  (socket:listen listener-socket 5)
  (do () (#f)
    (let ((actives (or (apply wait-for-input 5 listener-socket connections)
                       '())))
      (cond ((null? actives))
            ((memq listener-socket actives)
             (set! actives (cdr (memq listener-socket actives)))
             (let ((con (socket:accept listener-socket)))
               (display "accepting connection from ")
               (display (getpeername con))
               (newline)
               (set! connections (cons con connections))
               (display "connected" con)
               (newline con))))
      (set! connections
            (let next ((con-list connections))
              (cond ((null? con-list) '())
                    (else
                     (let ((con (car con-list)))
                       (cond ((memq con actives)
                              (let ((c (read-char con)))
                                (cond ((eof-object? c)
                                       (display "closing connection from ")
                                       (display (getpeername con))
                                       (newline)
                                       (close-port con)
                                       (next (cdr con-list)))
                                      (else
                                       (for-each (lambda (con)
                                                   (file-position con 0)
                                                   (write-char c con)
                                                   (file-position con 0))
                                                 connections)
                                       (cons con (next (cdr con-list)))))))
                             (else (cons con (next (cdr con-list)))))))))))))

You can use ‘telnet localhost 8001’ to connect to the chat server, or you can use a client written in scheme:

;;;; Scheme chat client

;;; this program connects to socket 8001.  It then sends all
;;; characters from current-input-port to the socket and sends all
;;; characters from the socket to current-output-port.

(require 'socket)
(require 'i/o-extensions)

(define con (make-stream-socket af_inet))
(set! con (socket:connect con (inet:string->address "localhost") 8001))

(define (go)
  (define actives (wait-for-input (* 30 60) con (current-input-port)))
  (let ((cs (and actives (memq con actives) (read-char con)))
        (ct (and actives (memq (current-input-port) actives) (read-char))))
    (cond ((or (eof-object? cs) (eof-object? ct)) (close-port con))
          (else (cond (cs (display cs)))
                (cond (ct (file-position con 0)
                          (display ct con)
                          (file-position con 0)))
                (go)))))
(cond (con (display "Connecting to ")
           (display (getpeername con))
           (newline)
           (go))
      (else (display "Server not listening on port 8001")
            (newline)))

Next: , Previous: , Up: Packages   [Contents][Index]