
Hello, I am using boost asio in a cross platform project. The project consists of two libraries, having a C call API in between. Until now, each of those two libraries uses boost::asio internally. Each of these libraries have their own instance of boost::asio::io_service. I now need to implement a change, that requires to pass a connected socket from one library to the other one via the C call API: This is what I want to do it. * Lib1 calls new method connect() in lib2 * lib2::connect() creates a boost::asio::ip::tcp::socket * lib2::connect() connects to a service * lib2::connect() does some async communication with that service. * when the service is initialized, lib2::connect() shall pass the native handle back to its caller (Lib1). * Lib1 then creates a boost::asio::ip::tcp::socket from the native handle I have learned, that there is no way to destroy a boost::asio::ip::tcp::socket without closing the native handle. So, I have to dup() it. No problem on POSIX systems, on Windows I can use a combination of WSADuplicateSocket () and WSASocket () to achieve the same. Everything works fine on Linux, but on Windows, the parts do not work together :) The individual parts are working find. * I can use the boost::asio::ip::tcp::socket to communicate with the service. * I can use WSADuplicateSocket () and WSASocket () to get a 2nd, native handle to the socket * I can use the 2nd, native handle to communicate to the service, even after destroying the boost::asio::ip::tcp::socket instance. * I also can create a working boost::asio::ip::tcp::socket from a native socket handle, created with socket() and connected to a service with connect(). BUT: If I try to create a boost::asio::ip::tcp::socket on the socket created by the WSADuplicateSocket () and WSASocket () sequence, I get an exception. The call to CreateIoCompletionPort() in win_iocp_io_service.ipp, win_iocp_io_service::register_handle() fails with error 87 (Invalid Parameter). I have no idea, why CreateIoCompletionPort() is failing and how to avoid this. Here is a sample program demonstrating my problem. If BUG is #defined, the code fails with std::exception "assign: Falscher Parameter" (invalid parameter). #ifdef _WIN32 #include <winsock2.h> #include <ws2tcpip.h> #else #include <sys/socket.h> #endif #include <boost/asio.hpp> #define ADDR "127.0.0.1" #define PORT "7" /* echo */ #include <stdio.h> #ifndef _WIN32 inline int WSAGetLastError() { return errno; } #endif int main() { char Request[]="Hello"; char Buffer[256]; int n; try { #ifdef _WIN32 SOCKET s1 = INVALID_SOCKET; #else int s1=-1; #endif #ifdef BUG { printf("The programm does not work with this code on windows :-(\n"); boost::asio::io_service IoService; boost::asio::ip::tcp::resolver Resolver(IoService); boost::asio::ip::tcp::resolver::query Query(ADDR, PORT); boost::asio::ip::tcp::socket s(IoService); s.connect(*Resolver.resolve(Query)); printf("connected\n"); #ifdef _WIN32 WSAPROTOCOL_INFO ProtocolInfo; DWORD MyProcId = GetCurrentProcessId(); int x = WSADuplicateSocket((SOCKET)s.native_handle(), MyProcId, &ProtocolInfo); if (x) throw boost::system::error_code(WSAGetLastError(), boost::system::system_category()); s1 = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, &ProtocolInfo, 0, WSA_FLAG_OVERLAPPED); #else /* !_WIN32 */ s1=dup(s.native_handle()); #endif /* !_WIN32 */ if (s1<0) throw boost::system::error_code(WSAGetLastError(), boost::system::system_category()); } #else s1 = socket(PF_INET, SOCK_STREAM, 0); if (s1 < 0) throw boost::system::error_code(WSAGetLastError(), boost::system::system_category()); struct sockaddr_in Addr; Addr.sin_family = AF_INET; Addr.sin_port = htons(atoi(PORT)); inet_pton(AF_INET, ADDR, &Addr.sin_addr); if (connect(s1, (struct sockaddr*)&Addr, sizeof(Addr)) < 0) throw boost::system::error_code(WSAGetLastError(), boost::system::system_category()); #endif printf("s1=%d\n", s1); { boost::asio::io_service IoService; boost::asio::ip::tcp::socket s(IoService, boost::asio::ip::tcp::v4(), (boost::asio::ip::tcp::socket::native_handle_type)s1); n = s.write_some(boost::asio::buffer(&Request, sizeof(Request))); printf("write_some() returned %d\n", n); n = s.read_some(boost::asio::buffer(Buffer, sizeof(Buffer))); printf("read_some() returned %d\n", n); } return 0; } catch (boost::system::error_code &ec) { fprintf(stderr, "boost::system::error_code: %s\n", ec.message().c_str()); return -1; } catch (std::exception &e) { fprintf(stderr, "std::exception: %s\n", e.what()); return -1; } } Thanks in advance, Mario -- Mario Klebsch Actia I+ME GmbH Mario.klebsch@ime-actia.de<mailto:Mario.klebsch@ime-actia.de> Dresdenstrasse 17/18 Fon: +49 531 38 701 716 38124 Braunschweig Fax: +49 531 38 701 88 German