Index: package.lisp
===================================================================
--- package.lisp	(revision 322)
+++ package.lisp	(working copy)
@@ -15,6 +15,8 @@
              #:socket-listen
              #:socket-accept
              #:socket-close
+             #:socket-send
+             #:socket-receive
              #:wait-for-input
              #:get-local-address
              #:get-peer-address
Index: backend/lispworks.lisp
===================================================================
--- backend/lispworks.lisp	(revision 322)
+++ backend/lispworks.lisp	(working copy)
@@ -19,6 +19,48 @@
       #+win32 :module
       #+win32 "ws2_32")
 
+(defconstant *socket_sock_dgram* 2)
+(defconstant *sockopt_so_rcvtimeo* #x1006)
+(defparameter *max-udp-message-size* 65536)
+
+;;; ssize_t
+;;; recvfrom(int socket, void *restrict buffer, size_t length, int flags,
+;;;          struct sockaddr *restrict address, socklen_t *restrict address_len);
+(fli:define-foreign-function (%recvfrom "recvfrom" :source)
+    ((socket :int)
+     (buffer (:pointer :unsigned-byte))
+     (length :int)
+     (flags :int)
+     (address (:pointer (:struct comm::sockaddr)))
+     (address-len (:pointer :int)))
+  :result-type :int)
+
+;;; ssize_t
+;;; sendto(int socket, const void *buffer, size_t length, int flags,
+;;;        const struct sockaddr *dest_addr, socklen_t dest_len);
+(fli:define-foreign-function (%sendto "sendto" :source)
+    ((socket :int)
+     (buffer (:pointer :unsigned-byte))
+     (length :int)
+     (flags :int)
+     (address (:pointer (:struct comm::sockaddr)))
+     (address-len :int))
+  :result-type :int)
+
+(fli:define-c-struct timeval (tv-sec :long) (tv-usec :long))
+
+(defun set-socket-receive-timeout (socket-fd sec &optional (usec 0))
+  "Set socket option: RCVTIMEO"
+  (declare (type integer socket-fd sec usec))
+  (fli:with-dynamic-foreign-objects ((timeout (:struct timeval)))
+    (fli:with-foreign-slots (tv-sec tv-usec) timeout
+      (setf tv-sec sec tv-usec usec))
+    (comm::setsockopt socket-fd
+                      comm::*sockopt_sol_socket*
+                      *sockopt_so_rcvtimeo*
+                      timeout
+                      (fli:size-of '(:struct timeval)))))
+
 (defun get-host-name ()
   (multiple-value-bind (retcode name)
       (get-host-name-internal)
@@ -123,6 +165,67 @@
   (with-mapped-conditions (usocket)
      (comm::close-socket (socket usocket))))
 
+(deftype datagram () `(simple-array (unsigned-byte 8) (*)))
+
+(defun socket-send (usocket data &optional address port &key (buffer-size *max-udp-message-size*))
+  (declare (type datagram data))
+  (let ((message (make-array buffer-size
+                             :element-type '(unsigned-byte 8)
+                             :initial-element 0
+                             :allocation :static))
+        (socket (socket usocket))
+        (proto (if (datagram-usocket-p usocket) "udp" "tcp")))
+    (fli:with-dynamic-foreign-objects ((client-addr (:struct comm::sockaddr_in))
+                                       (len :int
+                                            #+(and lispworks5 (not lispworks5.0))
+                                            :initial-element
+                                            (fli:size-of '(:struct comm::sockaddr_in))))
+      (if (connected-p usocket)
+        (if (and address port)
+          (error "EISCONN")
+          (comm::initialize-sockaddr_in client-addr comm::*socket_af_inet* nil nil proto))
+        (if (and address port)
+          (comm::initialize-sockaddr_in client-addr comm::*socket_af_inet* address port proto)
+          (error "EDESTADDRREQ")))
+      (fli:with-dynamic-lisp-array-pointer (ptr message :type :unsigned-byte)
+        (replace message data)
+        (%sendto socket ptr (min (length data) buffer-size) 0
+                 (fli:copy-pointer client-addr :type '(:struct comm::sockaddr))
+                 (fli:dereference len))))))
+
+(defun socket-receive (usocket &key timeout (buffer-size *max-udp-message-size*))
+  (let ((message (make-array buffer-size
+                             :element-type '(unsigned-byte 8)
+                             :initial-element 0
+                             :allocation :static))
+        (socket (socket usocket)))
+    (fli:with-dynamic-foreign-objects ((client-addr (:struct comm::sockaddr_in))
+                                       (len :int
+                                            #+(and lispworks5 (not lispworks5.0))
+                                            :initial-element
+                                            (fli:size-of '(:struct comm::sockaddr_in))))
+      (fli:with-dynamic-lisp-array-pointer (ptr message :type :unsigned-byte)
+        (when timeout (set-socket-receive-timeout socket timeout))
+        (let ((n (%recvfrom socket ptr buffer-size 0
+                            (fli:copy-pointer client-addr :type '(:struct comm::sockaddr))
+                            len)))
+          (if (plusp n)
+            (values (the datagram (subseq message 0 n))
+                    (let ((address (comm:ip-address-string
+                                    (comm::ntohl
+                                     (fli:foreign-slot-value
+                                      (fli:foreign-slot-value client-addr 'comm::sin_addr
+                                                              :object-type '(:struct comm::sockaddr_in)
+                                                              :type '(:struct comm::in_addr)
+                                                              :copy-foreign-object nil)
+                                      'comm::s_addr
+                                      :object-type '(:struct comm::in_addr)))))
+                          (port (comm::ntohl
+                                 (fli:foreign-slot-value client-addr 'comm::sin_port
+                                                         :object-type '(:struct comm::sockaddr_in)))))
+                      (list address port)))
+            (values nil nil)))))))
+
 (defmethod get-local-name ((usocket usocket))
   (multiple-value-bind
       (address port)
