私はPhilips Hueの小さなプロジェクトを試して、同時にC++を学んでいます。私がしようとしているのは、クライアントとブリッジの間でプロキシを動作させることです。このアプリケーションは、クライアントが関係する限りブリッジとして動作し、要求を受け取り、これをブリッジに渡します。他のデバイスにトラフィックを転送するC++
アプリが正常に実行されると、HTTP 200 OKレスポンスしか得られません。コードをステップ実行すれば、完全な応答が得られます。
以下は私のコードです、スレッドはありません、クラスはありません、そのすべてがメインメソッドで行われています。
WindowsSocket socketManager(&bitsLibrary);
if (!socketManager.createSocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 80, 1024))
{
cout << "Failed to create socket" << endl;
}
socketManager.bindAndStartListening();
WindowsSocket bridgeSocketManager(&bitsLibrary);
while (true)
{
sockaddr_in clientAddr;
memset(&clientAddr, 0, sizeof(sockaddr_in));
SOCKET clientSocket = socketManager.acceptClientAndReturnSocket(&clientAddr);
this_thread::sleep_for(chrono::milliseconds(500));
string received = socketManager.receiveDataOnSocket(&clientSocket);
bitsLibrary.writeToLog(received);
struct sockaddr_in server;
server.sin_family = AF_INET;
//server.sin_addr.s_addr = inet_addr("139.162.223.149");
server.sin_addr.s_addr = inet_addr("192.168.1.67");
server.sin_port = htons(80);
bridgeSocketManager.createSocket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
this_thread::sleep_for(chrono::milliseconds(500));
int result = connect(*bridgeSocketManager.returnSocket(), (struct sockaddr *)&server, sizeof(server));
if (result < 0)
{
cout << "Connect Failed: " << WSAGetLastError() << endl;
return EXIT_FAILURE;
}
this_thread::sleep_for(chrono::milliseconds(500));
SOCKET * bridgeSocket = bridgeSocketManager.returnSocket();
this_thread::sleep_for(chrono::milliseconds(500));
socketManager.sendToSocket(bridgeSocket, received);
string reply = socketManager.receiveDataOnSocket(bridgeSocket);
//boost::replace_all(reply, "Host: 192.168.1.70", "Host: 192.168.1.67");
bitsLibrary.writeToLog(reply);
this_thread::sleep_for(chrono::milliseconds(1000));
int sent = socketManager.sendToSocket(&clientSocket, reply);
this_thread::sleep_for(chrono::milliseconds(500));
bridgeSocketManager.closeSocket();
this_thread::sleep_for(chrono::milliseconds(500));
socketManager.closeSocket(&clientSocket);
/*while (true)
{
SOCKET clientSocket = socketManager.acceptClientAndReturnSocket(&clientAddr);
SocketProcessor socketProcessor;
socketProcessor.startThread(socketManager, clientSocket);
}*/
}
socketManager.closeSocket();
私のソケットは、次のような方法がある受け取る:
std::string WindowsSocket::receiveDataOnSocket(SOCKET *socket)
{
if (*socket != -1)
{
string receivedData = "";
char *temp = NULL;
int bytesReceived = 0;
do
{
bytesReceived = recv(*socket, this->buffer, this->bufferLength, 0);
if (bytesReceived == SOCKET_ERROR)
{
string socketError = this->getErrorStringFromErrorCode(WSAGetLastError()).c_str();
stringstream logstream;
logstream << "Failed to receive data on socket.The socket will now be closed and cleanup performed. Error: " << socketError;
this->bitsLibrary->writeToLog(logstream.str(), "WindowsSocket", "receiveDataOnSocket");
closesocket(*socket);
WSACleanup();
throw SocketException(socketError.c_str());
return "";
}
//If we got here, then we should be able to get some data
temp = new char[bytesReceived + 1];
//memset(&temp, 0, bytesReceived + 1);
strncpy(temp, this->buffer, bytesReceived);
temp[bytesReceived] = '\0'; //Add a null terminator to the end of the string
receivedData.append(temp);
temp = NULL;
//Now clear the buffer ready for more data
memset(this->buffer, 0, this->bufferLength);
cout << "Bytes Received: " << bytesReceived << " BUffer Length: " << this->bufferLength << endl;
} while (bytesReceived == this->bufferLength && bytesReceived >= 0); //Keep going until the received bytes is less than the buffer length
return receivedData;
}
else
{
stringstream logstream;
logstream << "Can't receive on socket as already be closed";
throw SocketException(logstream.str().c_str());
}
}
次のようにsendメソッドが見えます:
int WindowsSocket::sendToSocket(SOCKET *clientSocket, string dataToSend)
{
//dataToSend.append("\r\n");
int sentBytes = send(*clientSocket, dataToSend.c_str(), dataToSend.length(), 0);
if (sentBytes == SOCKET_ERROR)
{
throw SocketException(this->getErrorStringFromErrorCode(WSAGetLastError()).c_str());
}
return sentBytes;
}
ノーブレークポイントでのVisual Studioで正常にアプリを実行すると、I次の出力を取得します。
03/02/2017 22:08:16: WindowsSocket/bindAndStartListening: Socket has binded and is now listening
Bytes Received: 413 BUffer Length: 1024
Receiving data
GET /api/nouser/config HTTP/1.1
Host: 192.168.1.70
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-GB,en;q=0.8
03/02/2017 22:08:22: BaseSocket/createSocket: Creating buffer of length 1024
Bytes Received: 17 BUffer Length: 1024
03/02/2017 22:08:23: HTTP/1.1 200 OK
Sent: 17
私はブレークポイントを設定し、その後、私は、次の取得コードをステップ実行した場合:私は、ブレークポイントをしないとき、私はHTTPの唯一の17バイトは、200 OK受けるが、私はブレークポイントを設定してステップ際
03/02/2017 22:09:03: WindowsSocket/bindAndStartListening: Socket has binded and is now listening
Bytes Received: 413 BUffer Length: 1024
GET /api/nouser/config HTTP/1.1
Host: 192.168.1.70
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-GB,en;q=0.8
03/02/2017 22:09:09: BaseSocket/createSocket: Creating buffer of length 1024
Bytes Received: 630 BUffer Length: 1024
03/02/2017 22:09:17: HTTP/1.1 200 OK
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Expires: Mon, 1 Aug 2011 09:00:00 GMT
Connection: close
Access-Control-Max-Age: 3600
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE, HEAD
Access-Control-Allow-Headers: Content-Type
Content-type: application/json
{"name":"Philips hue","datastoreversion":"59","swversion":"01036659","apiversion":"1.16.0","mac":"00:17:88:1a:1f:43","bridgeid":"001788FFFE1A1F43","factorynew":false,"replacesbridgeid":null,"modelid":"BSB001"}
Sent: 630
お知らせコードを介して私は600バイト以上を取得し、私が期待していたすべてを受け取ります。
私は問題が何かを見ることができません、私はこれが問題を "修正"することを期待して眠りを入れましたが、睡眠でさえ違いはありません。
ご協力いただきありがとうございます。
あなたの条件(bytesReceived == this-> bufferLength)は無意味です –
[HTTP](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol)の詳細は、想像以上に複雑です。 HTTPサーバーまたはHTTPクライアント・ライブラリーの使用を検討してください。 [libcurl](https://curl.haxx.se/libcurl/)(HTTPクライアント)と[libonion](http://coralbits.com/libonion/)(HTTPサーバー)を調べます。 [POCO](https://pocoproject.org/)、[Boost](http://boost.org/)、[Qt](http://qt.io/)のフレームワークも参照してください。 –