2016-07-25 79 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說明。 –