Index: /trunk/include/iprt/socket.h
===================================================================
--- /trunk/include/iprt/socket.h	(revision 30269)
+++ /trunk/include/iprt/socket.h	(revision 30270)
@@ -31,4 +31,5 @@
 #include <iprt/thread.h>
 #include <iprt/net.h>
+#include <iprt/sg.h>
 
 #ifdef IN_RING0
@@ -176,4 +177,15 @@
 RTDECL(int) RTSocketGetPeerAddress(RTSOCKET hSocket, PRTNETADDR pAddr);
 
+/**
+ * Send data from a scatter/gather buffer to a socket.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_INTERRUPTED if interrupted before anything was written.
+ *
+ * @param   hSocket         The socket handle.
+ * @param   pSgBuf          Scatter/gather buffer to write data to socket.
+ */
+RTDECL(int) RTSocketSgWrite(RTSOCKET hSocket, PCRTSGBUF pSgBuf);
+
 /** @} */
 RT_C_DECLS_END
Index: /trunk/include/iprt/tcp.h
===================================================================
--- /trunk/include/iprt/tcp.h	(revision 30269)
+++ /trunk/include/iprt/tcp.h	(revision 30270)
@@ -4,5 +4,5 @@
 
 /*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2010 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -31,4 +31,5 @@
 #include <iprt/thread.h>
 #include <iprt/net.h>
+#include <iprt/sg.h>
 
 #ifdef IN_RING0
@@ -216,5 +217,5 @@
 
 /**
- * Enables or disable delaying sends to coalesce packets.
+ * Enables or disables delaying sends to coalesce packets.
  *
  * The TCP/IP stack usually uses the Nagle algorithm (RFC 896) to implement the
@@ -223,4 +224,5 @@
  * @returns iprt status code.
  * @param   Sock        Socket descriptor.
+ * @param   fEnable     When set to true enables coalescing.
  */
 RTR3DECL(int)  RTTcpSetSendCoalescing(RTSOCKET Sock, bool fEnable);
@@ -279,4 +281,15 @@
 RTR3DECL(int) RTTcpGetPeerAddress(RTSOCKET Sock, PRTNETADDR pAddr);
 
+/**
+ * Send data from a scatter/gather buffer to a socket.
+ *
+ * @returns iprt status code.
+ * @retval  VERR_INTERRUPTED if interrupted before anything was written.
+ *
+ * @param   Sock        Socket descriptor.
+ * @param   pSgBuf      Scatter/gather buffer to write data to socket.
+ */
+RTR3DECL(int)  RTTcpSgWrite(RTSOCKET Sock, PCRTSGBUF pSgBuf);
+
 /** @} */
 RT_C_DECLS_END
Index: /trunk/src/VBox/Runtime/r3/socket.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/socket.cpp	(revision 30269)
+++ /trunk/src/VBox/Runtime/r3/socket.cpp	(revision 30270)
@@ -45,4 +45,5 @@
 # include <unistd.h>
 # include <fcntl.h>
+# include <sys/uio.h>
 #endif /* !RT_OS_WINDOWS */
 #include <limits.h>
@@ -59,4 +60,6 @@
 #include <iprt/thread.h>
 #include <iprt/time.h>
+#include <iprt/mem.h>
+#include <iprt/sg.h>
 
 #include "internal/magics.h"
@@ -574,4 +577,82 @@
 
 
+RTDECL(int) RTSocketSgWrite(RTSOCKET hSocket, PCRTSGBUF pSgBuf)
+{
+    /*
+     * Validate input.
+     */
+    RTSOCKETINT *pThis = hSocket;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
+    AssertPtrReturn(pSgBuf, VERR_INVALID_PARAMETER);
+    AssertReturn(pSgBuf->cSeg > 0, VERR_INVALID_PARAMETER);
+    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
+
+    /*
+     * Construct message descriptor (translate pSgBuf) and send it.
+     */
+    int rc = VINF_SUCCESS;
+    do
+    {
+#ifdef RT_OS_WINDOWS
+        AssertCompileSize(WSABUF, sizeof(RTSGSEG));
+        AssertCompileMemberSize(WSABUF, buf, RT_SIZEOFMEMB(RTSGSEG, pvSeg));
+        AssertCompileMemberSize(WSABUF, len, RT_SIZEOFMEMB(RTSGSEG, cbSeg));
+
+        LPWSABUF *paMsg = (LPWSABUF)RTMemTmpAllocZ(pSgBuf->cSeg * sizeof(WSABUF));
+        AssertPtrBreakStmt(paMsg, rc = VERR_NO_MEMORY);
+        for (unsigned i = 0; i < pSgBuf->cSeg; i++)
+        {
+            paMsg[i].buf = pSgBuf->pcaSeg[i].pvSeg;
+            paMsg[i].len = pSgBuf->pcaSeg[i].cbSeg;
+        }
+
+        WSAMSG msgHdr;
+        DWORD dwSent;
+        memset(&msgHdr, '\0', sizeof(msgHdr));
+        msgHdr.lpBuffers = paMsg;
+        msgHdr.dwBufferCount = pSgBuf->cSeg;
+        int hrc = WSASendMsg(pThis->hNative, &msgHdr, MSG_NOSIGNAL, &dwSent,
+                             NULL, NULL);
+        ssize_t cbWritten;
+        if (!hrc)
+        {
+            /* avoid overflowing ssize_t, the exact value isn't important */
+            cbWritten = RT_MIN(dwSent, INT_MAX);
+        }
+        else
+            cbWritten = -1;
+#else
+        AssertCompileSize(struct iovec, sizeof(RTSGSEG));
+        AssertCompileMemberSize(struct iovec, iov_base, RT_SIZEOFMEMB(RTSGSEG, pvSeg));
+        AssertCompileMemberSize(struct iovec, iov_len, RT_SIZEOFMEMB(RTSGSEG, cbSeg));
+
+        struct iovec *paMsg = (struct iovec *)RTMemTmpAllocZ(pSgBuf->cSeg * sizeof(struct iovec));
+        AssertPtrBreakStmt(paMsg, rc = VERR_NO_MEMORY);
+        for (unsigned i = 0; i < pSgBuf->cSeg; i++)
+        {
+            paMsg[i].iov_base = pSgBuf->pcaSeg[i].pvSeg;
+            paMsg[i].iov_len = pSgBuf->pcaSeg[i].cbSeg;
+        }
+
+        struct msghdr msgHdr;
+        memset(&msgHdr, '\0', sizeof(msgHdr));
+        msgHdr.msg_iov = paMsg;
+        msgHdr.msg_iovlen = pSgBuf->cSeg;
+        ssize_t cbWritten = sendmsg(pThis->hNative, &msgHdr, MSG_NOSIGNAL);
+#endif
+
+        RTMemTmpFree(paMsg);
+        if (RT_LIKELY(cbWritten >= 0))
+            rc = VINF_SUCCESS;
+        else
+            rc = rtSocketError();
+    } while (0);
+
+    rtSocketUnlock(pThis);
+    return rc;
+}
+
+
 RTDECL(int) RTSocketSelectOne(RTSOCKET hSocket, RTMSINTERVAL cMillies)
 {
Index: /trunk/src/VBox/Runtime/r3/tcp.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/tcp.cpp	(revision 30269)
+++ /trunk/src/VBox/Runtime/r3/tcp.cpp	(revision 30270)
@@ -1014,2 +1014,8 @@
 }
 
+
+RTR3DECL(int)  RTTcpSgWrite(RTSOCKET Sock, PCRTSGBUF pSgBuf)
+{
+    return RTSocketSgWrite(Sock, pSgBuf);
+}
+
