mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
Core/Socket: Unix domain socket (AF_UNIX) support for Windows (#328)
Refactor UnixSocket.cpp with error handling Updated UnixSocket.cpp to include error handling and platform-specific path definitions. UnixSocketClient: Update socket path for cross-platform compatibility UnixSocketServer: Update socket path for Windows and Unix platforms Core: UnixSocket example code, socket path fixed autotest/UnixSocket: path correction and unlink.
This commit is contained in:
parent
5124794175
commit
e038550cb2
6 changed files with 167 additions and 122 deletions
|
|
@ -2,50 +2,63 @@
|
||||||
|
|
||||||
using namespace Upp;
|
using namespace Upp;
|
||||||
|
|
||||||
|
String GetSocketPath()
|
||||||
|
{
|
||||||
|
String temp;
|
||||||
|
#ifdef PLATFORM_WIN32
|
||||||
|
temp = GetEnv("TEMP");
|
||||||
|
#else
|
||||||
|
temp = GetTempPath();
|
||||||
|
#endif
|
||||||
|
return AppendFileName(temp, "upp-unixsocket.socket");
|
||||||
|
}
|
||||||
|
|
||||||
CONSOLE_APP_MAIN
|
CONSOLE_APP_MAIN
|
||||||
{
|
{
|
||||||
#ifdef PLATFORM_POSIX
|
|
||||||
|
|
||||||
StdLogSetup(LOG_COUT|LOG_FILE);
|
StdLogSetup(LOG_COUT|LOG_FILE);
|
||||||
|
|
||||||
String path = Format("/tmp/upp-unixsocket-test-%d", getpid());
|
String path = GetSocketPath();
|
||||||
|
|
||||||
Socket server, client;
|
|
||||||
|
|
||||||
// Test server listen
|
|
||||||
if(!server.ListenFileSystem(path)) {
|
|
||||||
LOG("Server listen failed: " << server.GetErrorDesc());
|
|
||||||
Exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test client connect
|
|
||||||
if(!client.ConnectFileSystem(path)) {
|
|
||||||
LOG("Client connect failed: " << client.GetErrorDesc());
|
|
||||||
Exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test data exchange
|
|
||||||
String test_data = "Hello, world!";
|
|
||||||
client.Put(test_data + "\n");
|
|
||||||
|
|
||||||
Socket accepted;
|
|
||||||
if(!accepted.Accept(server)) {
|
|
||||||
LOG("Accept failed: " << accepted.GetErrorDesc());
|
|
||||||
Exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
String received = accepted.GetLine();
|
|
||||||
DUMP(received);
|
|
||||||
|
|
||||||
ASSERT(received == test_data);
|
|
||||||
|
|
||||||
// Test peer PID (on supported platforms)
|
|
||||||
int pid = accepted.GetPeerPid();
|
|
||||||
DUMP(pid);
|
|
||||||
if(pid != -1)
|
|
||||||
ASSERT(pid == getpid()); // Should be our own process in this test
|
|
||||||
|
|
||||||
LOG("=========== OK");
|
try {
|
||||||
|
Socket server, client;
|
||||||
|
|
||||||
#endif
|
DeleteFile(path); // "unlink" existing FS socket if possible
|
||||||
}
|
|
||||||
|
// Test server listen
|
||||||
|
if(!server.ListenFileSystem(path, 5, false)) {
|
||||||
|
throw Exc("Server listen failed: " << server.GetErrorDesc());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test client connect
|
||||||
|
if(!client.ConnectFileSystem(path)) {
|
||||||
|
throw Exc("Client connect failed: " << client.GetErrorDesc());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test data exchange
|
||||||
|
String test_data = "Hello, world!";
|
||||||
|
client.Put(test_data + "\n");
|
||||||
|
|
||||||
|
Socket accepted;
|
||||||
|
if(!accepted.Accept(server)) {
|
||||||
|
throw Exc("Accept failed: " << accepted.GetErrorDesc());
|
||||||
|
}
|
||||||
|
|
||||||
|
String received = accepted.GetLine();
|
||||||
|
DUMP(received);
|
||||||
|
|
||||||
|
ASSERT(received == test_data);
|
||||||
|
|
||||||
|
// Test peer PID (on supported platforms)
|
||||||
|
int pid = accepted.GetPeerPid();
|
||||||
|
DUMP(pid);
|
||||||
|
if(pid != -1)
|
||||||
|
ASSERT(pid == getpid()); // Should be our own process in this test
|
||||||
|
|
||||||
|
LOG("=========== OK");
|
||||||
|
}
|
||||||
|
catch(const Exc& e)
|
||||||
|
{
|
||||||
|
LOG(e);
|
||||||
|
SetExitCode(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,26 +3,31 @@
|
||||||
using namespace Upp;
|
using namespace Upp;
|
||||||
|
|
||||||
// Start reference/UnixSocketServer before starting this program
|
// Start reference/UnixSocketServer before starting this program
|
||||||
|
String GetSocketPath()
|
||||||
|
{
|
||||||
|
String temp;
|
||||||
|
#ifdef PLATFORM_WIN32
|
||||||
|
temp = GetEnv("TEMP");
|
||||||
|
#else
|
||||||
|
temp = GetTempPath();
|
||||||
|
#endif
|
||||||
|
return AppendFileName(temp, "upp-unixsocket.socket");
|
||||||
|
}
|
||||||
|
|
||||||
|
String Request(const String r)
|
||||||
|
{
|
||||||
|
Socket s;
|
||||||
|
if(!s.ConnectFileSystem(GetSocketPath())) {
|
||||||
|
Cout() << "Unable to connect to server!\n";
|
||||||
|
SetExitCode(1);
|
||||||
|
return String();
|
||||||
|
}
|
||||||
|
s.Put(r + '\n');
|
||||||
|
return s.GetLine();
|
||||||
|
}
|
||||||
|
|
||||||
CONSOLE_APP_MAIN
|
CONSOLE_APP_MAIN
|
||||||
{
|
{
|
||||||
#ifdef PLATFORM_POSIX
|
|
||||||
auto Request = [](const String& r)
|
|
||||||
{
|
|
||||||
Socket s;
|
|
||||||
if(!s.ConnectFileSystem("/tmp/upp-unixsocket.sock")) {
|
|
||||||
Cout() << "Unable to connect to server!\n";
|
|
||||||
SetExitCode(1);
|
|
||||||
return String();
|
|
||||||
}
|
|
||||||
s.Put(r + '\n');
|
|
||||||
return s.GetLine();
|
|
||||||
};
|
|
||||||
|
|
||||||
Cout() << Request("time") << '\n';
|
Cout() << Request("time") << '\n';
|
||||||
Cout() << Request("33") << '\n';
|
Cout() << Request("33") << '\n';
|
||||||
#else
|
|
||||||
Cout() << "This example requires a POSIX compliant operating system...\r\n"
|
|
||||||
SetExitCode(1);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,23 @@
|
||||||
|
|
||||||
using namespace Upp;
|
using namespace Upp;
|
||||||
|
|
||||||
|
String GetSocketPath()
|
||||||
|
{
|
||||||
|
String temp;
|
||||||
|
#ifdef PLATFORM_WIN32
|
||||||
|
temp = GetEnv("TEMP");
|
||||||
|
#else
|
||||||
|
temp = GetTempPath();
|
||||||
|
#endif
|
||||||
|
return AppendFileName(temp, "upp-unixsocket.socket");
|
||||||
|
}
|
||||||
|
|
||||||
CONSOLE_APP_MAIN
|
CONSOLE_APP_MAIN
|
||||||
{
|
{
|
||||||
#ifdef PLATFORM_POSIX
|
|
||||||
const String& path = "/tmp/upp-unixsocket.sock";
|
|
||||||
|
|
||||||
Socket server;
|
Socket server;
|
||||||
if(!server.ListenFileSystem(path, 5)) {
|
String path = GetSocketPath();
|
||||||
|
DeleteFile(path); // "unlink" existing file system socket
|
||||||
|
if(!server.ListenFileSystem(path, 5, false)) { // Reuse option is not available on Windows
|
||||||
Cout() << "Unable to initialize server socket!\n";
|
Cout() << "Unable to initialize server socket!\n";
|
||||||
SetExitCode(1);
|
SetExitCode(1);
|
||||||
return;
|
return;
|
||||||
|
|
@ -26,8 +36,4 @@ CONSOLE_APP_MAIN
|
||||||
s.Put("\n");
|
s.Put("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
Cout() << "This example requires a POSIX compliant operating system...\r\n"
|
|
||||||
SetExitCode(1);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -171,11 +171,10 @@ class Socket : NoCopy {
|
||||||
|
|
||||||
static int GetErrorCode();
|
static int GetErrorCode();
|
||||||
static void Init();
|
static void Init();
|
||||||
|
|
||||||
#ifdef PLATFORM_POSIX // Unix domain socket support
|
// Unix domain socket support
|
||||||
bool NixConnect(const String& path, bool abstract);
|
bool NixConnect(const String& path, bool abstract);
|
||||||
bool NixListen(const String& path, int n, bool reuse, bool abstract);
|
bool NixListen(const String& path, int n, bool reuse, bool abstract);
|
||||||
#endif
|
|
||||||
|
|
||||||
Socket(const Socket&);
|
Socket(const Socket&);
|
||||||
|
|
||||||
|
|
@ -217,13 +216,11 @@ public:
|
||||||
void Close();
|
void Close();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
#ifdef PLATFORM_POSIX
|
|
||||||
int GetPeerPid() const;
|
int GetPeerPid() const;
|
||||||
bool ConnectFileSystem(const String& path);
|
bool ConnectFileSystem(const String& path);
|
||||||
bool ConnectAbstract(const String& path);
|
bool ConnectAbstract(const String& path);
|
||||||
bool ListenFileSystem(const String& path, int listen_count = 5, bool reuse = true);
|
bool ListenFileSystem(const String& path, int listen_count = 5, bool reuse = true);
|
||||||
bool ListenAbstract(const String& path, int listen_count = 5, bool reuse = true);
|
bool ListenAbstract(const String& path, int listen_count = 5, bool reuse = true);
|
||||||
#endif
|
|
||||||
|
|
||||||
void NoDelay();
|
void NoDelay();
|
||||||
void Linger(int msecs);
|
void Linger(int msecs);
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,11 @@
|
||||||
#ifdef PLATFORM_WIN32
|
#ifdef PLATFORM_WIN32
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
|
#ifdef AF_UNIX // Unix domain (AF_UNIX) socket support, Windows 10+
|
||||||
|
#include <afunix.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef PLATFORM_POSIX
|
#ifdef PLATFORM_POSIX
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
@ -984,40 +988,43 @@ void Socket::Clear()
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PLATFORM_POSIX
|
static socklen_t sSetUnixSockType(Socket& s, const String& path, sockaddr_un& addr, bool abstract)
|
||||||
|
|
||||||
static bool sSetUnixSockType(Socket& s, const String& path, sockaddr_un& addr, bool abstract)
|
|
||||||
{
|
{
|
||||||
memset(&addr, 0, sizeof(addr));
|
#ifdef AF_UNIX
|
||||||
addr.sun_family = AF_UNIX;
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sun_family = AF_UNIX;
|
||||||
#ifndef PLATFORM_LINUX
|
#ifndef PLATFORM_LINUX
|
||||||
if(abstract) {
|
if(abstract) {
|
||||||
s.SetSockError("SetUnixSockType",
|
s.SetSockError("SetUnixSockType",
|
||||||
-1, "Abstract socket is not supported on this platform");
|
-1, "Abstract socket is not supported on this platform");
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
const int len = path.GetLength();
|
||||||
|
|
||||||
if(abstract) {
|
if(abstract) {
|
||||||
addr.sun_path[0] = '\0';
|
if(len <= 0 || len > int(sizeof(addr.sun_path) - 1)) {
|
||||||
if(path.GetLength() > 0) {
|
s.SetSockError("SetUnixSockType", -1, "Abstract socket name too long");
|
||||||
ASSERT(path.GetLength() < sizeof(addr.sun_path) - 1);
|
return 0;
|
||||||
strncpy(addr.sun_path + 1, ~path, sizeof(addr.sun_path) - 2);
|
}
|
||||||
return true;
|
addr.sun_path[0] = '\0';
|
||||||
}
|
memcpy(addr.sun_path + 1, ~path, len);
|
||||||
}
|
return offsetof(sockaddr_un, sun_path) + 1 + len;
|
||||||
else {
|
}
|
||||||
if(path.GetLength() > 0) {
|
else {
|
||||||
ASSERT(path.GetLength() < sizeof(addr.sun_path));
|
if(len <= 0 || len >= int(sizeof(addr.sun_path))) {
|
||||||
strncpy(addr.sun_path, ~path, sizeof(addr.sun_path) - 1);
|
s.SetSockError("SetUnixSockType", -1, "Unix socket path too long");
|
||||||
addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
|
return 0;
|
||||||
return true;
|
}
|
||||||
}
|
memcpy(addr.sun_path, ~path, len);
|
||||||
}
|
addr.sun_path[len] = '\0';
|
||||||
s.SetSockError("SetUnixSockType",
|
return offsetof(sockaddr_un, sun_path) + len + 1;
|
||||||
-1, "Failed to set unix domain socket type");
|
}
|
||||||
return false;
|
#else
|
||||||
|
s.SetSockError("SetUnixSockType",
|
||||||
|
-1, "Unix domain socket is not supported on this platform");
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Socket::GetPeerPid() const
|
int Socket::GetPeerPid() const
|
||||||
|
|
@ -1048,21 +1055,27 @@ bool Socket::NixConnect(const String& path, bool abstract)
|
||||||
Init();
|
Init();
|
||||||
Reset();
|
Reset();
|
||||||
|
|
||||||
|
#ifdef AF_UNIX
|
||||||
if(!Open(AF_UNIX, SOCK_STREAM, 0))
|
if(!Open(AF_UNIX, SOCK_STREAM, 0))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
struct sockaddr_un addr;
|
struct sockaddr_un addr;
|
||||||
if(!sSetUnixSockType(*this, path, addr, abstract))
|
socklen_t addrlen = 0;
|
||||||
|
if((addrlen = sSetUnixSockType(*this, path, addr, abstract)) == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(connect(socket, (sockaddr *) &addr, sizeof(addr)) == 0 ||
|
if(connect(socket, (sockaddr *) &addr, addrlen) == 0 ||
|
||||||
GetErrorCode() == EINPROGRESS || GetErrorCode() == EWOULDBLOCK) {
|
findarg(GetErrorCode(), SOCKERR(EINPROGRESS), SOCKERR(EWOULDBLOCK)) >= 0) {
|
||||||
mode = Socket::CONNECT;
|
mode = Socket::CONNECT;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetSockError("connect", -1, strerror(GetErrorCode()));
|
SetSockError("connect", -1, strerror(GetErrorCode()));
|
||||||
Close();
|
Close();
|
||||||
|
#else
|
||||||
|
SetSockError("NixConnect",
|
||||||
|
-1, "Unix domain socket is not supported on this platform");
|
||||||
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1082,11 +1095,13 @@ bool Socket::NixListen(const String& path, int n, bool reuse, bool abstract)
|
||||||
Init();
|
Init();
|
||||||
Reset();
|
Reset();
|
||||||
|
|
||||||
|
#ifdef AF_UNIX
|
||||||
if(!Open(AF_UNIX, SOCK_STREAM, 0))
|
if(!Open(AF_UNIX, SOCK_STREAM, 0))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
struct sockaddr_un addr;
|
struct sockaddr_un addr;
|
||||||
if(!sSetUnixSockType(*this, path, addr, abstract))
|
socklen_t addrlen = 0;
|
||||||
|
if((addrlen = sSetUnixSockType(*this, path, addr, abstract)) == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(reuse) {
|
if(reuse) {
|
||||||
|
|
@ -1094,7 +1109,7 @@ bool Socket::NixListen(const String& path, int n, bool reuse, bool abstract)
|
||||||
setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval));
|
setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bind(socket, (const sockaddr *) &addr, sizeof(addr))) {
|
if(bind(socket, (const sockaddr *) &addr, addrlen)) {
|
||||||
SetSockError(Format("bind(path=%s)", path));
|
SetSockError(Format("bind(path=%s)", path));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -1105,6 +1120,12 @@ bool Socket::NixListen(const String& path, int n, bool reuse, bool abstract)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
#else
|
||||||
|
SetSockError("NixListen",
|
||||||
|
-1, "Unix domain socket is not supported on this platform");
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Socket::ListenFileSystem(const String& path, int listen_count, bool reuse)
|
bool Socket::ListenFileSystem(const String& path, int listen_count, bool reuse)
|
||||||
|
|
@ -1117,9 +1138,6 @@ bool Socket::ListenAbstract(const String& path, int listen_count, bool reuse)
|
||||||
return NixListen(path, listen_count, reuse, true);
|
return NixListen(path, listen_count, reuse, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
int SocketWaitEvent::Wait(int timeout)
|
int SocketWaitEvent::Wait(int timeout)
|
||||||
{
|
{
|
||||||
FD_ZERO(read);
|
FD_ZERO(read);
|
||||||
|
|
|
||||||
|
|
@ -34,11 +34,10 @@ tring]_[* GetHostName]()&]
|
||||||
[s4; &]
|
[s4; &]
|
||||||
[s5;:Socket`:`:GetPeerPid`(`)const: [@(0.0.255) int] [* GetPeerPid]()
|
[s5;:Socket`:`:GetPeerPid`(`)const: [@(0.0.255) int] [* GetPeerPid]()
|
||||||
[@(0.0.255) const]&]
|
[@(0.0.255) const]&]
|
||||||
[s6; POSIX only&]
|
|
||||||
[s2;%% Returns the process ID (pid) of the peer on success, `-1 on
|
[s2;%% Returns the process ID (pid) of the peer on success, `-1 on
|
||||||
failure. On non`-blocking mode, make sure that socket is actually
|
failure. On non`-blocking mode, make sure that socket is actually
|
||||||
connected or accepted. This is only available on unix domain
|
connected or accepted. This is only available on unix domain
|
||||||
(local) sockets.&]
|
(local) sockets and will fail with return code `-1 on Windows.&]
|
||||||
[s3; &]
|
[s3; &]
|
||||||
[s4; &]
|
[s4; &]
|
||||||
[s5;:Socket`:`:GetDone`(`)const: [@(0.0.255) int]_[* GetDone]()_[@(0.0.255) const]&]
|
[s5;:Socket`:`:GetDone`(`)const: [@(0.0.255) int]_[* GetDone]()_[@(0.0.255) const]&]
|
||||||
|
|
@ -120,8 +119,7 @@ pAddrInfo][@(0.0.255) `&]_[*@3 info])&]
|
||||||
[s3;%% &]
|
[s3;%% &]
|
||||||
[s4; &]
|
[s4; &]
|
||||||
[s5;:Upp`:`:Socket`:`:ConnectFileSystem`(const String`&`): [@(0.0.255) bool]
|
[s5;:Upp`:`:Socket`:`:ConnectFileSystem`(const String`&`): [@(0.0.255) bool]
|
||||||
[* ConnectFileSystem]([@(0.0.255) const] String[@(0.0.255) `&] [*@3 path])&]
|
[* ConnectFileSystem]([@(0.0.255) const] String[@(0.0.255) `&] [@3 path])&]
|
||||||
[s6;%% POSIX only&]
|
|
||||||
[s2;%% Connects socket to a Unix domain server bound at the given
|
[s2;%% Connects socket to a Unix domain server bound at the given
|
||||||
file system [%-*@3 path]. The path must exist on the file system.
|
file system [%-*@3 path]. The path must exist on the file system.
|
||||||
Returns true if connection is successful (blocking mode) or connection
|
Returns true if connection is successful (blocking mode) or connection
|
||||||
|
|
@ -138,8 +136,8 @@ and does not correspond to a file system path. Returns true if
|
||||||
connection is successful (blocking mode) or connection is in
|
connection is successful (blocking mode) or connection is in
|
||||||
progress (non blocking mode). Abstract sockets exist only in
|
progress (non blocking mode). Abstract sockets exist only in
|
||||||
kernel memory and disappear when processes exit. On non`-Linux
|
kernel memory and disappear when processes exit. On non`-Linux
|
||||||
POSIX systems, this function will fail and set the socket into
|
systems, this function will fail and set the socket into error
|
||||||
error state. &]
|
state. &]
|
||||||
[s3; &]
|
[s3; &]
|
||||||
[s4; &]
|
[s4; &]
|
||||||
[s5;:Socket`:`:WaitConnect`(`): [@(0.0.255) bool]_[* WaitConnect]()&]
|
[s5;:Socket`:`:WaitConnect`(`): [@(0.0.255) bool]_[* WaitConnect]()&]
|
||||||
|
|
@ -169,15 +167,23 @@ for ipv6`=`=true.&]
|
||||||
[s3;%% &]
|
[s3;%% &]
|
||||||
[s4; &]
|
[s4; &]
|
||||||
[s5;:Upp`:`:Socket`:`:ListenFileSystem`(const String`&`,int`,bool`): [@(0.0.255) bool]
|
[s5;:Upp`:`:Socket`:`:ListenFileSystem`(const String`&`,int`,bool`): [@(0.0.255) bool]
|
||||||
[* ListenFileSystem]([@(0.0.255) const ]String[@(0.0.255) `&] [*@3 path],
|
[* ListenFileSystem(][*@(0.0.255) const ][* String][*@(0.0.255) `&][*
|
||||||
[@(0.0.255) int] [*@3 listen`_count] [@(0.0.255) `=] [@3 5], [@(0.0.255) bool]
|
][*@3 path][* , ][*@(0.0.255) int][* ][*@3 listen`_count][* ][*@(0.0.255) `=][*
|
||||||
[*@3 reuse] [@(0.0.255) `=] [@(0.0.255) true])&]
|
][*@3 5][* , ][*@(0.0.255) bool][* ][*@3 reuse][* ][*@(0.0.255) `=][* ][*@(0.0.255) true][* )]&]
|
||||||
[s6; POSIX only&]
|
|
||||||
[s2;%% Creates a Unix domain server socket bound to the given file
|
[s2;%% Creates a Unix domain server socket bound to the given file
|
||||||
system [%-*@3 path]. [%-*@3 listen`_count] specifies the maximum
|
system [%-*@3 path]. [%-*@3 listen`_count] specifies the maximum
|
||||||
number of pending connections in the queue. [%-*@3 reuse] indicates
|
number of pending connections in the queue. [%-*@3 reuse] indicates
|
||||||
whether the socket should allow reuse of the address if it already
|
whether the socket should allow reuse of the address if it already
|
||||||
exists. returns true if the listen is successful.&]
|
exists. returns true if the listen is successful. &]
|
||||||
|
[s2;%% &]
|
||||||
|
[s2;%% Notes:&]
|
||||||
|
[s2;i150;O0;%% [%-*@3 reuse] option is not supported on Windows and
|
||||||
|
if specified the listen will fail and set the socket into error
|
||||||
|
state. &]
|
||||||
|
[s2;i150;O0;%% Client code is responsible for the socket [%-*@3 path]’s
|
||||||
|
lifetime. For filesystem`-based Unix domain sockets, the pathname
|
||||||
|
must be unlinked explicitly after shutdown, as it is not removed
|
||||||
|
automatically when the socket is closed.&]
|
||||||
[s3; &]
|
[s3; &]
|
||||||
[s4; &]
|
[s4; &]
|
||||||
[s5;:Upp`:`:Socket`:`:ListenAbstract`(const String`&`,int`,bool`): [@(0.0.255) bool]
|
[s5;:Upp`:`:Socket`:`:ListenAbstract`(const String`&`,int`,bool`): [@(0.0.255) bool]
|
||||||
|
|
@ -191,8 +197,8 @@ not correspond to a file system path). [%-*@3 listen`_count] specifies
|
||||||
the maximum number of pending connections. [%-*@3 reuse] indicates
|
the maximum number of pending connections. [%-*@3 reuse] indicates
|
||||||
whether the abstract socket name can be reused. Abstract sockets
|
whether the abstract socket name can be reused. Abstract sockets
|
||||||
exist only in kernel memory and disappear when processes exit.
|
exist only in kernel memory and disappear when processes exit.
|
||||||
On non`-Linux POSIX systems, this method will fail and set the
|
On non`-Linux systems, this method will fail and set the socket
|
||||||
socket into error state.&]
|
into error state.&]
|
||||||
[s3; &]
|
[s3; &]
|
||||||
[s4;%% &]
|
[s4;%% &]
|
||||||
[s5;:Socket`:`:Accept`(Socket`&`): [@(0.0.255) bool]_[* Accept]([_^topic`:`/`/Core`/src`/TcpSocket`$en`-us`#TcpSocket`:`:class^ S
|
[s5;:Socket`:`:Accept`(Socket`&`): [@(0.0.255) bool]_[* Accept]([_^topic`:`/`/Core`/src`/TcpSocket`$en`-us`#TcpSocket`:`:class^ S
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue