Opened 12 years ago

Last modified 12 years ago

#5157 new Bugs

Assign native socket problem

Reported by: a.pacek@… Owned by: chris_kohlhoff
Milestone: Component: asio
Version: Boost 1.45.0 Severity: Problem
Keywords: native socket assign Cc:

Description

Hi

I'm trying to duplicate accepted/opened socket and pass them to other process. It works fine under linux. But under Windows I can't assign this native socket to boost::asio::ip::tcp::socket. When I try to assign opened native socket to boost socket object s.assign(boost::asio::ip::tcp::v4(), socketDup) throws me exception: "The parameter is incorrect". Even if I try to duplicate socket and use them in the same process. I still got this exception.

The line inside boost throws this exception: boost_1_45_0\boost\asio\detail\impl\win_iocp_io_service.ipp:

boost::system::error_code win_iocp_io_service::register_handle(
    HANDLE handle, boost::system::error_code& ec)
{
  if (::CreateIoCompletionPort(handle, iocp_.handle, 0, 0) == 0)	//this function failed
  {
    DWORD last_error = ::GetLastError();
    ec = boost::system::error_code(last_error,
        boost::asio::error::get_system_category());
  }
  else
  {
    ec = boost::system::error_code();
  }
  return ec;
}

I'm using: VC++ 2008 / Win7

What am I doing wrong? How can I resolve this problem? Thanks for help.

Example code:

boost::asio::io_service io_service;
tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), m_nPort));

std::cout << "Waiting for connection..." << std::endl;

tcp::socket socket(io_service);
acceptor.accept(socket);
std::cout << "connection accepted" << std::endl;

#ifdef _WIN32
WSAPROTOCOL_INFO pi;
WSADuplicateSocket(socket.native(), get_current_process_id(), &pi);
SOCKET socketDup = WSASocket(pi.iAddressFamily/*AF_INET*/, pi.iSocketType/*SOCK_STREAM*/,
pi.iProtocol/*IPPROTO_TCP*/, &pi, 0, 0);
char sText[] = "I can use my duplicated socket via WinApi!\r\n";
int nRet = send(socketDup, sText, strlen(sText), 0);
#else
	//linux
	int socketDup = dup(socket.native());
#endif

try
{
	tcp::socket s(io_service);
	s.assign(boost::asio::ip::tcp::v4(), socketDup); //this throws exception under Windows
	//I can't use my socket via boost lib
	s.send(boost::asio::buffer("Not work\r\n"));
}
catch(std::exception &e)
{
	std::cerr << e.what() << std::endl; //"The parameter is incorrect" exception
}

Change History (1)

comment:1 by Ole Jak (aka Blender), 12 years ago

Hello my friends.

I loved this peace of code. I decided to help us all opensource programmers a bit and try to solve this problem.

I fixed code a bit and made it compilable.

I received exception described.

I addressed this question to community of Grate StackOverflow programmers.

Ben Voigt *(it seems a member of msmvps)provided a solution to this problem which was tested and that works.

here is final code I compiled and tested:

#include <iostream>

#ifdef _WIN32
#define BOOST_ASIO_DISABLE_IOCP 1
#endif

#include <boost/asio.hpp>

#ifdef _WIN32
#include "Windows.h"
#endif

using namespace boost::asio::ip;
using namespace std;

int main(){

        int m_nPort = 12345;
        boost::asio::io_service io_service;
        tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), m_nPort));

        cout << "Waiting for connection..." << endl;

        tcp::socket socket(io_service);
        acceptor.accept(socket);
        cout << "connection accepted" << endl;

#ifdef _WIN32
        WSAPROTOCOL_INFO pi;
        WSADuplicateSocket(socket.native(), GetCurrentProcessId(), &pi);
        SOCKET socketDup = WSASocket(pi.iAddressFamily/*AF_INET*/, pi.iSocketType/*SOCK_STREAM*/,
                pi.iProtocol/*IPPROTO_TCP*/, &pi, 0, 0);
        char sText[] = "I can use my duplicated socket via WinApi!\r\n";
        int nRet = send(socketDup, sText, strlen(sText), 0);
#else
        //linux
        int socketDup = dup(socket.native()); // tested on Linux, works!
#endif

        try
        {
                tcp::socket s(io_service);
                s.assign(tcp::v4(), socketDup); //this throws exception under Windows
                //I can't use my socket via boost lib
                s.send(boost::asio::buffer("Not work\r\n"));
                cout << "We do not get here!=(" << endl;
        }
        catch(exception &e)
        {
                cerr << e.what() << endl; //"The parameter is incorrect" exception
        }
        cin.get();
} 

Note: See TracTickets for help on using tickets.