2017-01-06 6 views
0

私はC++とソケットを学習していますが、問題が発生しました。小さなサンプルアプリケーションを作成してシミュレートしました。リスンソケットを作成してソケットに接続し、クライアントソケットをベクトルSOCKET *に格納します。ソケットをベクトルに格納して閉じ、同じソケットが追加され続ける

3番目のクライアントソケット接続の後、私はベクトルを反復処理して閉じます。最初の1は成功しますが、最後の2はソケットがすでに閉じられているかのように-1のエラーで失敗します。しかし、実際には1つのソケットだけが閉じます。次のように

bool WindowsSocket::bindAndStartListening(int backlog) 
{ 
    stringstream logstream; 

    //iResult = ::bind(this->serverSocket, result->ai_addr, (int)result->ai_addrlen); 
    iResult = ::bind(this->serverSocket, (SOCKADDR *)&this->serv_addr, sizeof(this->serv_addr)); 
    if (iResult != 0) 
    { 
     logstream << "Socket binding failed with error: " << iResult; 
     this->bitsLibrary->writeToLog(logstream.str(), "WindowsSocket", "bindAndStartListening"); 
     logstream.clear(); 
     logstream.str(string()); 
     FreeAddrInfo(result); 
     closesocket(this->serverSocket); 
     WSACleanup(); 
     return false; 
    } 

    freeaddrinfo(result); 
    iResult = listen(this->serverSocket, backlog); 
    if (iResult == SOCKET_ERROR) 
    { 
     throw SocketException(this->getErrorStringFromErrorCode(WSAGetLastError()).c_str()); 
     return false; 
    } 
    logstream << "Socket has binded and is now listening"; 
    this->bitsLibrary->writeToLog(logstream.str(), "WindowsSocket", "bindAndStartListening"); 
    return true; 
} 

acceptClientAndReturnSocket関数は次のよう

bool WindowsSocket::createSocket(int family, int socketType, int protocol, int port, int bufferLength, string ipAddress) 
{ 
    stringstream logstream; 
    //Call the base method to do the prep work e.g. create the buffer 
    BaseSocket::createsocket(port, bufferLength); 

    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); 
    if (iResult != 0) 
    { 
     logstream << "WSAStartup failed with error: " << iResult; 
     this->bitsLibrary->writeToLog(logstream.str(), "WindowsSocket", "createSocket"); 
     logstream.clear(); 
     logstream.str(string()); 
     return false; 
    } 
    this->serverSocket = socket(family, socketType, protocol); 
    this->serv_addr.sin_family = family; 
    if (ipAddress.empty()) 
    { 
     this->serv_addr.sin_addr.s_addr = INADDR_ANY; 
    } 
    else 
    { 
     this->serv_addr.sin_addr.s_addr = inet_addr(ipAddress.c_str()); 
    } 
    this->serv_addr.sin_port = htons(port); 

    return true; 
} 

bindAndStartListening関数である:以下

は、次のようにソケットを作成する機能であるコード

WindowsSocket socketManager(&bitsLibrary); 
    socketManager.createSocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 500, 1024, "127.0.0.1"); 

    socketManager.bindAndStartListening(); 
    vector<SOCKET *> clientSocketList; 
    int i = 0; 
    while (i < 3) 
    { 
     sockaddr_in client; 
     SOCKET clientSock = socketManager.acceptClientAndReturnSocket(&client); 

     cout << "Client Port: " << ntohs(client.sin_port) << endl; 

     //Add the client socket to the vector 
     clientSocketList.push_back(&clientSock); 
     i++; 

     string data = socketManager.receiveDataOnSocket(&clientSock); 

     socketManager.sendToSocket(&clientSock, "Hello, here is a response"); 
    } 

    int index = 1; 
    for (std::vector<SOCKET *>::iterator it = clientSocketList.begin(); it != clientSocketList.end(); ++it) 
    { 
     cout << "Closing socket " << index << " of " << clientSocketList.size() << endl; 
     try 
     { 
      SOCKET *socket = (SOCKET *)*it; 
      socketManager.closeSocket(socket); 
     } 
     catch (SocketException ex) 
     { 
      cout << "Failed to close client socket. Error: " << ex.what() << endl; 
     } 
     index++; 
    } 

    //socketManager.closeSocket(socketManager.returnSocket()); 
    //socketManager.closeSocket(&clientSock); 

    return EXIT_SUCCESS; 

あります:

SOCKET WindowsSocket::acceptClientAndReturnSocket(sockaddr_in *clientAddr) 
{ 
    SOCKET clientSocket = INVALID_SOCKET; 
    //sockaddr_in clientAddr; 
    socklen_t sin_size = sizeof(struct sockaddr_in); 
    clientSocket = accept(this->serverSocket, (struct sockaddr*)clientAddr, &sin_size); 
    return clientSocket; 
} 

私は `` clientSocketList`は、各項目は以下のスクリーンショットのように同じ値が含まれているように見えるが含まれどのようなデバッグ:

Debug screenshot of clientSocketList

同じクライアントソケットがある私はなぜ表示されませんベクターに加えられる。

ご協力いただきありがとうございます。

答えて

3

while(i < 3)ループの各繰り返しでは、新しいSOCKETが作成されます。アドレスは保存しますが、繰り返しの最後には破棄されます。あなたが保存しているのは、スタック上のオブジェクトのアドレスです。最新のclientSockは同じアドレスにあります。

clientSocketListstd::vector<SOCKET*>ですが、おそらくstd::vector<SOCKET>を使用したかったのですが、

+0

もちろん、私はポインタを完全に理解していると思うたびに何かが起こり、私の心が再び変わると思います。 – Boardy

+1

このコードであなたのポインターを使用することはほとんどありません。例えば、 'acceptClientAndReturnSocket'は参照を取るか、' std :: pair'を返すことができるときに、なぜポインタを取るのですか? –

+0

Hmm良い点、私はポインタを使用してソケットを通過するときにコピーを作成しない、私は参照について知りませんでした - まだ完全には - 私はメソッドを元々書きましたが、私が何を変えることができるかを見てください。私が参照の代わりにポインタのために見つけたと思う1つの理由は、refとして渡された場合、パス値が変更可能であることは明らかではない。ポインタ – Boardy

関連する問題