From: Tor L. <tm...@ik...> - 2007-06-15 19:14:46
|
Vincent Torri writes: > I've seen that select() is available in winsock2.h, but for sockets True. Sockets only. Not pipes or other file descriptors, which are C library objects. > Is it possible to create 2 sockets (named fd1 and fd2, to fix ideas), the > former for l1, the latter for l2, to link them (like pipe() does), You mean a so called socket pair. Yes. I should have code to create a connected TCP socket pair somewhere, lemme see.... Here: int fake_socketpair(int *fds) { SOCKET temp, socket1 = -1, socket2 = -1; struct sockaddr_in saddr; int len; u_long arg; fd_set read_set, write_set; struct timeval tv; temp = socket (AF_INET, SOCK_STREAM, 0); if (temp == INVALID_SOCKET) { goto out0; } arg = 1; if (ioctlsocket (temp, FIONBIO, &arg) == SOCKET_ERROR) { goto out0; } memset (&saddr, 0, sizeof (saddr)); saddr.sin_family = AF_INET; saddr.sin_port = 0; saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); if (bind (temp, (struct sockaddr *)&saddr, sizeof (saddr))) { goto out0; } if (listen (temp, 1) == SOCKET_ERROR) { goto out0; } len = sizeof (saddr); if (getsockname (temp, (struct sockaddr *)&saddr, &len)) { goto out0; } socket1 = socket (AF_INET, SOCK_STREAM, 0); if (socket1 == INVALID_SOCKET) { goto out0; } arg = 1; if (ioctlsocket (socket1, FIONBIO, &arg) == SOCKET_ERROR) { goto out1; } if (connect (socket1, (struct sockaddr *)&saddr, len) != SOCKET_ERROR || WSAGetLastError () != WSAEWOULDBLOCK) { goto out1; } FD_ZERO (&read_set); FD_SET (temp, &read_set); tv.tv_sec = 0; tv.tv_usec = 0; if (select (0, &read_set, NULL, NULL, NULL) == SOCKET_ERROR) { goto out1; } if (!FD_ISSET (temp, &read_set)) { goto out1; } socket2 = accept (temp, (struct sockaddr *) &saddr, &len); if (socket2 == INVALID_SOCKET) { goto out1; } FD_ZERO (&write_set); FD_SET (socket1, &write_set); tv.tv_sec = 0; tv.tv_usec = 0; if (select (0, NULL, &write_set, NULL, NULL) == SOCKET_ERROR) { goto out2; } if (!FD_ISSET (socket1, &write_set)) { goto out2; } arg = 0; if (ioctlsocket (socket1, FIONBIO, &arg) == SOCKET_ERROR) { goto out2; } arg = 0; if (ioctlsocket (socket2, FIONBIO, &arg) == SOCKET_ERROR) { goto out2; } fds[0] = socket1; fds[1] = socket2; closesocket (temp); return 0; out2: closesocket (socket2); out1: closesocket (socket1); out0: closesocket (temp); errno = EMFILE; /* FIXME: use the real syscall errno? */ fds[0] = -1; fds[1] = -1; return -1; } I think that code works... No guarantees, it's been a while since I wrote it, and I don't recall how much testing that function actually got. --tml |