私は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`は、各項目は以下のスクリーンショットのように同じ値が含まれているように見えるが含まれどのようなデバッグ:
同じクライアントソケットがある私はなぜ表示されませんベクターに加えられる。
ご協力いただきありがとうございます。
もちろん、私はポインタを完全に理解していると思うたびに何かが起こり、私の心が再び変わると思います。 – Boardy
このコードであなたのポインターを使用することはほとんどありません。例えば、 'acceptClientAndReturnSocket'は参照を取るか、' std :: pair'を返すことができるときに、なぜポインタを取るのですか? –
Hmm良い点、私はポインタを使用してソケットを通過するときにコピーを作成しない、私は参照について知りませんでした - まだ完全には - 私はメソッドを元々書きましたが、私が何を変えることができるかを見てください。私が参照の代わりにポインタのために見つけたと思う1つの理由は、refとして渡された場合、パス値が変更可能であることは明らかではない。ポインタ – Boardy