2016-07-25 75 views
0

我需要创建进程并将连接的套接字传递给新创建的进程,并且套接字上的进一步操作将在新进程中发生。我已经使用了下面的代码。一切工作,但是当我尝试所做的工作后关闭子进程,它抛出的线路访问冲突,C++ - 每个TCP连接的进程

return InterlockedCompareExchangePointer(dest, exch, cmp); 

在文件“win_iocp_socket_service_base.ipp”,这是在路径“助推\ ASIO \ detail \ impl“

以下是我的代码。

#include <iostream> 
#include <tchar.h> 
#define BOOST_ASIO_DISABLE_IOCP 1 
#include <boost/thread/thread.hpp> 
#include <boost/asio.hpp> 
#include <boost/date_time/posix_time/posix_time_io.hpp> 
#include <boost/date_time/gregorian/gregorian.hpp> 
#include <boost/date_time.hpp> 

#ifdef _WIN32 
#include "Windows.h" 
#endif 
#include <string> 

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

int main(int argc, char* argv[]){ 
    cout << "Current Process Id...." << GetCurrentProcessId() << endl; 
    cout << "Argument count..." << argc << endl; 
    if (3 == argc){ 
     boost::this_thread::sleep(boost::posix_time::seconds(15)); 
     ostringstream ss; 
     ss << argv[2]; 
     if (ss.str() == "CHILD"){ 
      cout << "Message To child...." << ss.str() << endl; 
      try 
      { 
       SOCKET Sock; 
       if (2 < argc){ 
        Sock = atoi(argv[1]); // use Sock 
       } 
       boost::asio::io_service io_service2; 
       tcp::socket s(io_service2); 
       s.assign(tcp::v4(), Sock); 
       s.send(boost::asio::buffer("Message to client\r\n")); 
       s.close(); 
       return 0; 
      } 
      catch (exception &e) 
      { 
       cerr << e.what() << endl; //"The parameter is incorrect" exception 
      } 
      return 0; 
     } 
    } 

    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); 
#else 
    //linux 
    int socketDup = dup(socket.native()); // tested on Linux, works! 
#endif 

    { 
     STARTUPINFO si; 
     PROCESS_INFORMATION pi; 
     TCHAR argbuf[256]; 

     memset(&si, 0, sizeof(si)); 
     wsprintf(argbuf, _T("Server.exe %d %s"), socketDup, _T("\"CHILD\"")); 
     if (!CreateProcess(NULL, argbuf, NULL, NULL, 
      TRUE, // inherit handles 
      0, NULL, NULL, &si, &pi)){ 
      fprintf(stderr, "createprocess failed %d\n", GetLastError()); 
      return -1; 
     }   
     WaitForSingleObject(pi.hProcess, INFINITE); 
    } 
    socket.close(); 
    cin.get(); 
} 

我发现,错误是由该"#define BOOST_ASIO_DISABLE_IOCP 1"

引起的,但如果没有这个,我不能在这个行复制插座,s.assign(tcp::v4(), Sock);

我怎么能解决这个问题,请帮帮我。

+0

对不起,我把它看作是传递给线程而不是进程。 WSADuplicateSocket是正确的方法。关闭孩子时,是否关闭父进程上的套接字? –

+0

为什么?这就是20世纪80年代套接字的编程方式。 Thees days你会使用一个线程。 – EJP

回答

0

最后我得到了解决方案。

1.comment线

#define BOOST_ASIO_DISABLE_IOCP 1 

2.Change插座到共享指针。 - 谢谢你@Samer Tufail共享指针建议

我的工作代码。

#include <iostream> 
#include <tchar.h> 
#include <boost/thread/thread.hpp> 
#include <boost/asio.hpp> 
#include <boost/date_time/posix_time/posix_time_io.hpp> 
#include <boost/date_time/gregorian/gregorian.hpp> 
#include <boost/date_time.hpp> 

#ifdef _WIN32 
#include "Windows.h" 
#endif 
#include <string> 

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

int main(int argc, char* argv[]){ 
    cout << "Current Process Id...." << GetCurrentProcessId() << endl; 
    cout << "Argument count..." << argc << endl; 
    if (3 == argc){ 
     boost::this_thread::sleep(boost::posix_time::seconds(15)); 
     ostringstream ss; 
     ss << argv[2]; 
     if (ss.str() == "CHILD"){ 
      cout << "Message To child...." << ss.str() << endl; 
      try 
      { 
       SOCKET Sock; 
       if (2 < argc){ 
        Sock = atoi(argv[1]); // use Sock 
       } 
       boost::asio::io_service io_service2; 
       tcp::socket s(io_service2); 
       io_service2.run(); 
       s.assign(tcp::v4(), Sock); 
       s.send(boost::asio::buffer("Message to client\r\n")); 
       s.close(); 
       return 0; 
      } 
      catch (exception &e) 
      { 
       cerr << e.what() << endl; 
      } 
      return 0; 
     } 
    } 

    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; 

    boost::shared_ptr<tcp::socket> socket(new tcp::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); 
#else 
    //linux 
    int socketDup = dup(socket.native()); // tested on Linux, works! 
#endif 

    { 
     STARTUPINFO si; 
     PROCESS_INFORMATION pi; 
     TCHAR argbuf[256]; 

     memset(&si, 0, sizeof(si)); 
     wsprintf(argbuf, _T("Server.exe %d %s"), socketDup, _T("\"CHILD\"")); 
     if (!CreateProcess(NULL, argbuf, NULL, NULL, 
      TRUE, // inherit handles 
      0, NULL, NULL, &si, &pi)){ 
      fprintf(stderr, "createprocess failed %d\n", GetLastError()); 
      return -1; 
     }   
     WaitForSingleObject(pi.hProcess, INFINITE); 
    } 
    cin.get(); 
} 
0

我误解为复制套接字从'线程'而不是'进程'视力不佳。 WSADuplicateSocket函数是正确的。但是,警告是底层套接字将保持打开状态,直到此套接字的所有描述符都被释放,包括父节点。 WSADuplicate

从MSDN

直接:

一个进程可以调用一个复制套接字关闭套接字和 描述符将成为释放。但底层套接字 将保持打开状态,直到最后一个剩余的 描述符调用closesocket。

+0

我如何在创建的子进程中使用此套接字。 –

+0

您还需要在父级上调用close,请参阅上面的MSDN说明。 –