I wrote an HTTP server in Java and a client in C++ with Poco. This is a part of the C++ client code:
URI uri("http://127.0.0.1:4444");
HTTPClientSession session(uri.getHost(), uri.getPort());
HTTPRequest req(HTTPRequest::HTTP_POST,
"/pages/page",
HTTPMessage::HTTP_1_1);
session.sendRequest(req);
HTTPResponse res;
std::istream &is = session.receiveResponse(res);
In the last line I get the following error:
terminate called after throwing an instance of 'Poco::Net::NoMessageException'
what(): No message received
But I don't understand why. The connection was established successfully and the page requested exists. I tried the same code with known websites (like Wikipedia) and it works without any exception.
I also tried to make the exact same request with cURL (to my server) in command-line and it shows the response of the server, so the server seems fine.
This is the original response of the server in a string form:
"HTTP/1.1 200 OK\r\n" +
"Server: [server name]\r\n" +
"Content-Type: text/xml; charset=utf-8\r\n" +
"Content-Length:" + bodyBytes.length + "\r\n" +
"Resource: " + job.resId + "\r\n\r\n" +
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><JobRequest><InputRepresentation id=\"0\"/> <effectsList><cvtColor><code> CV_RGB2GRAY </code></cvtColor><resize><scaleFactorX> 0.5 </scaleFactorX><scaleFactorY> 0.5 </scaleFactorY><interpolation> INTER_LINEAR </interpolation></resize><GaussianBlur><kSize> 3 </kSize><sigmaX> 2 </sigmaX><sigmaY> 2 </sigmaY><borderType> BORDER_REPLICATE </borderType></GaussianBlur></effectsList></JobRequest>"
I have written a simple HTTP server which respond with a fixed response for every request, to test what's wrong. this is the code:
public class Test {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(4449);
Socket clientSocket = serverSocket.accept();
String body = "ab";
byte[] bodyBytes = body.getBytes("UTF-8");
String headers = "HTTP/1.1 200 OK\r\n" +
"Server: Foo\r\n" +
"Content-Type: text/plain\r\n" +
"Content-Length: " + bodyBytes.length + "\r\n\r\n";
byte[] headerBytes = headers.getBytes("UTF-8");
byte[] responseBytes = new byte[headerBytes.length + bodyBytes.length];
/* Fill responseBytes with the header and body bytes */
int i = 0;
for (int j = 0; j < headerBytes.length; ++j) {
responseBytes[i] = headerBytes[j];
++i;
}
for (int j = 0; j < bodyBytes.length; ++j) {
responseBytes[i] = bodyBytes[j];
++i;
}
clientSocket.getOutputStream().write(responseBytes);
} catch (IOException e) {}
}
}
I get the same exception even with this server. So what's wrong here?
Based on experimentation, I've found that it's necessary to include a Content-Length header if you are making an empty POST request. I.e.,
req.add("Content-Length", "0");
I had to use the following sequence in my handler code for a minimal response to be received without a No message received error:
resp.setStatus( Poco::Net::HTTPResponse::HTTP_OK );
resp.setContentType( "text/json" );
ostream &out = resp.send();
out << "[]";
out.flush();
Related
I tried to parse the data which was generated by chunked transfer encoding in a Rest API ,I did see the data has value when I tried to print the value in a string and I thought it should be working,but when I tried to assign the value to the file, the file is totally unreadable, the code below I used boost library and I gonna elaborate my thoughts in the code , we gonna get started from the response portion of my code, I have no idea what wrong I have done
// Send the request.
boost::asio::write(socket, request);
// Read the response status line. The response streambuf will automatically
// grow to accommodate the entire line. The growth may be limited by passing
// a maximum size to the streambuf constructor.
boost::asio::streambuf response;
boost::asio::read_until(socket, response, "\r\n");
// Check that response is OK.
std::istream response_stream(&response);
std::string http_version;
response_stream >> http_version;
unsigned int status_code;
response_stream >> status_code;
std::string status_message;
std::getline(response_stream, status_message);
if (!response_stream || http_version.substr(0, 5) != "HTTP/")
{
//std::cout << "Invalid response\n";
return 9002;
}
if (status_code != 200)
{
//std::cout << "Response returned with status code " << status_code << "\n";
return 9003;
}
// Read the response headers, which are terminated by a blank line.
boost::asio::read_until(socket, response, "\r\n\r\n");
// Process the response headers.
//this portion of code I tried to parse the file name in the header of response which the file name is in the content-disposition of header
std::string header;
std::string fullHeader = "";
string zipfilename="", txtfilename="";
bool foundfilename = false;
while (std::getline(response_stream, header) && header != "\r")
{
fullHeader.append(header).append("\n");
std::transform(header.begin(), header.end(), header.begin(),
[](unsigned char c){ return std::tolower(c); });
string containstr = "content-disposition";
string containstr2 = "filename";
string quotestr = "\"";
if (header.find(containstr) != std::string::npos && header.find(containstr2) != std::string::npos)
{
int countquotes = 0;
bool foundquote = true;
std::size_t startpos = 0, beginpos, endpos;
while (foundquote)
{
std::size_t myfound = header.find(quotestr, startpos);
if (myfound != std::string::npos)
{
if (countquotes % 2 == 0)
beginpos = myfound;
else
{
endpos = myfound;
foundfilename = true;
}
startpos = myfound + 1;
}
else
foundquote = false;
countquotes++;
}
if (endpos > beginpos && foundfilename)
{
size_t zipfileleng = endpos - beginpos;
zipfilename = header.substr(beginpos+1, zipfileleng-1);
txtfilename = header.substr(beginpos+1, zipfileleng-5);
}
else
return 9004;
}
}
if (foundfilename == false || zipfilename.length() == 0 || txtfilename.length() == 0)
return 9005;
//when the zipfilename has been found, we gonna get the data from the body of response, due to the response was chunked transfer encoding, I tried to parse it,it's not complicated due to I saw it on the Wikipedia, it just first line was length of data,the next line was data,and it's the loop which over and over again ,all I tried to do was spliting all the data from the body of response by "\r\n" into a vector<string>, and I gonna read the data from that vector
// Write whatever content we already have to output.
std::string fullResponse = "";
if (response.size() > 0)
{
std::stringstream ss;
ss << &response;
fullResponse = ss.str();
}
//tried split the entire body of response into a vector<string>
vector<string> allresponsedata;
split_regex(allresponsedata, fullResponse, boost::regex("(\r\n)+"));
//tried to merge the data of response
string zipfiledata;
int myindex = 0;
for (auto &x : allresponsedata) {
std::cout << "Split: " << x << std::endl;// I tried to print the data, I did see the value in the variable of x
if (myindex % 2 != 0)
{
zipfiledata = zipfiledata + x;//tried to accumulate the datas
}
myindex++;
}
//tried to write the data into a file
std::ofstream zipfilestream(zipfilename, ios::out | ios::binary);
zipfilestream.write(zipfiledata.c_str(), zipfiledata.length());
zipfilestream.close();
//afterward, the zipfile was built, but it's unreadable which it's not able to open,the zip utlities software says it's a damaged zip file though
I even tried something else ways like this slow http client based on boost::asio - (Chunked Transfer) ,but this way is not working as well ,VS says
1 IntelliSense: no instance of overloaded function "boost::asio::read" matches the argument list
argument types are: (boost::asio::ip::tcp::socket, boost::asio::streambuf, boost::asio::detail::transfer_exactly_t, std::error_code)
it just NOT able to compile in the line which is
size_t n = asio::read(socket, response, asio::transfer_exactly(chunk_bytes_to_read), error);
even I have read the example of asio::transfer_exactly, there's no exactly example like this though https://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/reference/transfer_exactly.html
any idea?
I don't see you read the format correctly: https://en.wikipedia.org/wiki/Chunked_transfer_encoding#Format
You need to read the chunk length (in hex) and any optional chunk extensions before accumulating the full response body.
It needs to be done before, because the sequence \r\n that you split on can easily appear inside the chunk data.
Again, I recommend to just use Beast's support, making it all a simple
http::response<http::string_body> response;
boost::asio::streambuf buf;
http::read(socket, buf, response);
And you will have the headers fully parsed, interpreted (including Trailer headers!) and the content in response.body() as a std::string.
It will do the right thing even if the server doesn't use chunked encoding or combines with different encoding options.
There's simply no reason to reinvent the wheel.
Full Demo
This demonstrates with the Chunked Encoding test url from https://jigsaw.w3.org/HTTP/:
#include <boost/process.hpp>
#include <boost/beast.hpp>
#include <iostream>
namespace http = boost::beast::http;
using boost::asio::ip::tcp;
int main() {
http::response<http::string_body> response;
boost::asio::io_context ctx;
tcp::socket socket(ctx);
connect(socket, tcp::resolver{ctx}.resolve("jigsaw.w3.org", "http"));
http::write(
socket,
http::request<http::empty_body>(
http::verb::get, "/HTTP/ChunkedScript", 11));
boost::asio::streambuf buf;
http::read(socket, buf, response);
std::cout << response.body() << "\n";
std::cout << "Effective headers are:" << response.base() << "\n";
}
Printing
This output will be chunked encoded by the server, if your client is HTTP/1.1
Below this line, is 1000 repeated lines of 0-9.
-------------------------------------------------------------------------
01234567890123456789012345678901234567890123456789012345678901234567890
01234567890123456789012345678901234567890123456789012345678901234567890
...996 lines removed ...
01234567890123456789012345678901234567890123456789012345678901234567890
01234567890123456789012345678901234567890123456789012345678901234567890
Effective headers are:HTTP/1.1 200 OK
cache-control: max-age=0
date: Wed, 31 Mar 2021 20:09:50 GMT
transfer-encoding: chunked
content-type: text/plain
etag: "1j3k6u8:tikt981g"
expires: Wed, 31 Mar 2021 20:09:49 GMT
last-modified: Mon, 18 Mar 2002 14:28:02 GMT
server: Jigsaw/2.3.0-beta3
I'm trying to implement simple, bare-bones mini web server, it's main and only task would be to send simple html/js page to client and then do real-time updates to it. Implementing transport layer is pretty simple, but I met surprising difficulties in server-side implementation of EventSource... Initially I tried this straightforward approach:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <string>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#define PORT 80
using namespace std;
string head =
"HTTP/1.1 200 OK\n\
Content-Type: text/html\n\
Content-Length: ";
string update_head =
"HTTP/1.1 200 OK\n\
Content-Type: text/event-stream\n\
Cache-Control: no-cache\n\
Content-Length: ";
string update = "retry: 10000\ndata: SERVER SAYS: ";
string response =
"<!DOCTYPE html>\
<html>\n\
<head>\n\
</head>\n\
<body>\n\
<div id=\"serverData\">Here is where the server sent data will appear</div>\n\
<script>\n\
if(typeof(EventSource)!==\"undefined\") {\n\
var eSource = new EventSource(\"/\");\n\
eSource.onmessage = function(event) {\n\
document.getElementById(\"serverData\").innerHTML = event.data;\n\
};\n\
}\n\
else {\n\
document.getElementById(\"serverData\").innerHTML=\"Whoops! Your browser doesn't receive server-sent events.\";\n\
}\n\
</script>\n\
</body>\n\
</html>";
int serverMain()
{
int listen_sock, new_sock;
struct sockaddr_in addr;
int addr_len = sizeof(addr);
listen_sock = socket(AF_INET, SOCK_STREAM, 0);
if(listen_sock == 0)
{
perror("Error creating socket");
return 1;
}
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(PORT);
memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
int ret = bind(listen_sock, (struct sockaddr*)&addr, addr_len);
if(ret < 0)
{
perror("Error binding socket");
return 2;
}
ret = listen(listen_sock, 10);
if(ret < 0)
{
perror("Error setting up server as listеner");
return 3;
}
while(1)
{
char buff[2048] = {0};
printf("Waiting for clients...\n\n");
new_sock = accept(listen_sock, (struct sockaddr*)&addr, (socklen_t*)&addr_len);
if(new_sock < 0)
{
perror("Error accepting client connection into new socket");
return 4;
}
long bytes_read = read(new_sock, buff, 2048);
printf("------------------Client-Request------------------\n%s\
\n------------------Client-Request------------------\n", buff);
string reply = head + to_string(response.size()) + "\n\n" + response;
write(new_sock, reply.c_str(), reply.size());
printf("Server response sent.\n\n");
bytes_read = read(new_sock, buff, 2048);
printf("------------------Client-Request------------------\n%s\
\n------------------Client-Request------------------\n", buff);
for(int i = 0; i < 60; ++i)
{
sleep(1);
string msg = update + to_string(i) + "\n\ndata: some other stufff morestuff "
+ to_string(i) + "\n\n";
string upd = update_head + to_string(msg.size()) + "\n\n" + msg;
write(new_sock, upd.c_str(), upd.size());
printf("Server UPDATE %d sent.\n", i);
}
close(new_sock);
}
return 0;
}
TLDR: basically, I was just pushing "updates" wrapped in a header every second. Result was not good at all:
Only first update was actually received by browser, all subsequent updates where ignored. What's even worse — after browser sent another request for EventStream data 10 s later (look at retry: 10000\n I sent with each massage), server crashed with no error messages (I still have no idea what was the reason).
After this I tried another approach:
for(int i = 0; i < 60; ++i)
{
bytes_read = read(new_sock, buff, 2048);
printf("------------------Client-Request------------------\n%s\
\n------------------Client-Request------------------\n", buff);
string msg = update + to_string(i) + "\n\ndata: some other stufff morestuff "
+ to_string(i) + "\n\n";
string upd = update_head + to_string(msg.size()) + "\n\n" + msg;
write(new_sock, upd.c_str(), upd.size());
printf("Server UPDATE %d sent.\n", i);
}
I removed sleep(1) from the server update loop and allowed client to send me requests, and only after that server could send update (header + data). This, kind of, sort of worked:
In a way that, yes, browser really received all updates and correctly displayed it in the html page. But something is still off... I need 1 second intervals. Of course, I can set retry: 1000\n and browser will send requests every second and everything will work "perfectly". But actually not so. Because its not server who decides when to push update, its client who does it. It's not much different to clicking "refresh page" button every second...
In php and node.js examples I saw on the Internet, it seems to me that they somehow send data continuously without waiting for client. Maybe they use some sort of buffer or memory mapping or something?
So, apparently, I was doing everything in the right direction apart from tiny little undocumented (at least I didn't found anything at all about it) detail on how exactly to send updates correctly.
First change header to this:
string update_head =
"HTTP/1.1 200 OK\n\
Content-Type: text/event-stream\n\
Cache-Control: no-cache\n\n";
There is no need for content length! Now, after sending actual HTML page, client will send request for text/event-stream. You need to read it and reply with bare header (important, no data or anything else!).
write(new_sock, update_head.c_str(), update_head.size());
printf("Server HEAD UPDATE sent.\n");
And only after this you can start sending actual updates without any header or Content-Length:
for(int i = 0; i < 60; ++i)
{
sleep(1);
string msg = update + to_string(i) + "\n\ndata: some other stufff morestuff "
+ to_string(i) + "\n\n";
write(new_sock, msg.c_str(), msg.size());
printf("Server UPDATE %d sent.\n", i);
}
This results in browser correctly interpreting event stream:
I am using an Adafruit Feather Huzzah ESP8266 and the ArduinoJson library to parse the response of an HTTP request. I am successfully getting the expected responses but the deserialization process fails every other time it iterates through the loop. I think it may be a memory allocation issue but I cannot resolve the problem. Any help would be greatly appreciated.
I have tried using dynamic vs static documents and initialising them inside/outside the loop without success. I have also tried the doc.clear() method to release the memory but still no luck. Below is my loop with the connection parameters missing:
void loop() {
WiFiClientSecure client;
for (int i = 0; i <= numOfInstallations - 1; i++) {
String url = "/v2/installations/" + String(idSites[i]) +
"/widgets/Graph?attributeCodes[]=SOC&instance=" + String(instance[i]) +
"&start=" + String(startTime) +
"&end=" + String(endTime);
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"X-Authorization: Token " + token + "\r\n" +
"Connection: keep-alive\r\n\r\n");
Serial.println(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"X-Authorization: Token " + token + "\r\n" +
"Connection: keep-alive\r\n\r\n");
Serial.println("request sent");
delay(500);
// Ignore the response headers
char endOfHeaders[] = "\r\n\r\n";
if (!client.find(endOfHeaders)) {
Serial.println(F("No headers"));
return;
}
const size_t capacity = 5*JSON_ARRAY_SIZE(2) + JSON_ARRAY_SIZE(5) + 2*JSON_OBJECT_SIZE(1) + 2*JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(4) + 130;
DynamicJsonDocument doc(capacity); // Json document setup
// Get the Json data from the response
DeserializationError error = deserializeJson(doc, client);
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.c_str());
Serial.print("\r\n");
}
else {
Serial.println("deserializeJson() successful\r\n");
}
}
}
I am expecting the deserialization process to be successful each time but here is the output:
GET /v2/installations/xxxxx/widgets/Graph?attributeCodes[]=SOC&instance=215&start=1555070100&end=1555070400 HTTP/1.1
Host: vrmapi.victronenergy.com
X-Authorization: Token c324f8876e672ad1797cd69a9d9f62611507d25aa5a0b1ff40f9fb524d96f2fc
Connection: keep-alive
request sent
deserializeJson() successful
GET /v2/installations/xxxxx/widgets/Graph?attributeCodes[]=SOC&instance=258&start=1555070100&end=1555070400 HTTP/1.1
Host: vrmapi.victronenergy.com
X-Authorization: Token XXXXXXXXXX
Connection: keep-alive
request sent
deserializeJson() failed: InvalidInput
GET /v2/installations/xxxxx/widgets/Graph?attributeCodes[]=SOC&instance=258&start=1555070100&end=1555070400 HTTP/1.1
Host: vrmapi.victronenergy.com
X-Authorization: Token XXXXXXXXXX
Connection: keep-alive
request sent
deserializeJson() successful
GET /v2/installations/xxxxx/widgets/Graph?attributeCodes[]=SOC&instance=258&start=1555070100&end=1555070400 HTTP/1.1
Host: vrmapi.victronenergy.com
X-Authorization: Token XXXXXXXXXX
Connection: keep-alive
request sent
deserializeJson() failed: InvalidInput
GET /v2/installations/xxxxx/widgets/Graph?attributeCodes[]=SOC&instance=258&start=1555070100&end=1555070400 HTTP/1.1
Host: vrmapi.victronenergy.com
X-Authorization: Token XXXXXXXXXX
Connection: keep-alive
request sent
deserializeJson() successful
I am trying to send a get request to acounts.google.com to be able to implement a library for C++ OAuth to learn it.
I get the following code from this post: Creating a HTTPS request using Boost Asio and OpenSSL and modified it as follow:
int main()
{
try
{
std::string request = "/o/oauth2/v2/auth";
boost::system::error_code ec;
using namespace boost::asio;
// what we need
io_service svc;
ssl::context ctx(svc, ssl::context::method::sslv23_client);
ssl::stream<ip::tcp::socket> ssock(svc, ctx);
ip::tcp::resolver resolver(svc);
auto it = resolver.resolve({ "accounts.google.com", "443" }); // https://accouts.google.com:443
boost::asio::connect(ssock.lowest_layer(), it);
ssock.handshake(ssl::stream_base::handshake_type::client);
// send request
std::string fullResuest = "GET " + request + " HTTP/1.1\r\n\r\n";
boost::asio::write(ssock, buffer(fullResuest));
// read response
std::string response;
do
{
char buf[1024];
size_t bytes_transferred = ssock.read_some(buffer(buf), ec);
if (!ec) response.append(buf, buf + bytes_transferred);
std::cout << "Response received: '" << response << "'\n"; // I add this to see what I am getting from the server, so it should not be here.
} while (!ec);
// print and exit
std::cout << "Response received: '" << response << "'\n";
}
catch (const std::exception& e)
{
std::cerr << e.what() << std::endl;
if (std::string const * extra = boost::get_error_info<my_tag_error_info>(e))
{
std::cout << *extra << std::endl;
}
}
}
The problem that I have is as follow:
1- The results that I am getting is not what I am getting when I visit https://accounts.google.com/o/oauth2/v2/auth using a web browser. I essentially getting a message that they can not find the requested URL /o/oauth2/v2/auth
<p>The requested URL <code>/o/oauth2/v2/auth</code> was not found on this server. <ins>ThatÔÇÖs all we know.</ins>
How should I setup the GET commend so I can get the same result that I am getting with a browser?
2- The application hangs getting data from server, apparently the following loop is not right:
do
{
char buf[1024];
size_t bytes_transferred = ssock.read_some(buffer(buf), ec);
if (!ec) response.append(buf, buf + bytes_transferred);
} while (!ec);
What is the correct way of reading responce from the web server which is fast and read all data?
Edit 1
For reference based on accepted answer, I fixed the problem using the correct GET header as shown below:
// send request
std::string fullResuest = "GET " + request + " HTTP/1.1\r\n";
fullResuest+= "Host: " + server + "\r\n";
fullResuest += "Accept: */*\r\n";
fullResuest += "Connection: close\r\n\r\n";
boost::asio::write(ssock, buffer(fullResuest));
A HTTP/1.1 request must have a Host header. A simple experiment with OpenSSL will show the problem, i.e. the missing header:
$ openssl s_client -connect accounts.google.com:443
...
GET /o/oauth2/v2/auth HTTP/1.1
... The requested URL <code>/o/oauth2/v2/auth</code> was not found on this server. <ins>That’s all we know.</ins>
When adding the Host header instead we get a different response:
$ openssl s_client -connect accounts.google.com:443
...
GET /o/oauth2/v2/auth HTTP/1.1
Host: accounts.google.com
... >Required parameter is missing: response_type<
Apart from that HTTP/1.1 implicitly uses HTTP keep-alive, i.e. server and client might keep the connection open after the response is done. This means you should not read until the end of connection but should instead properly parse the HTTP header, extract the Content-length header and/or Transfer-Encoding header and behave according to their values. Or if you want it simpler use HTTP/1.0 instead.
For more information see the HTTP/1.1 standard.
I'm trying to upload a PNG file through Winsock2 HTTP Post. Here's my request string:
boundary = "-----rueldotme";
request += "POST " + uri + " HTTP/1.1\r\n";
request += "Host: " + hostname + "\r\n";
request += "User-Agent: " + UserAgent + "\r\n";
request += "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
request += "Accept-Language: en-us,en;q=0.5\r\n";
request += "Accept-Encoding: gzip,deflate\r\n";
request += "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n";
request += "Keep-Alive: 115\r\n";
request += "Connection: keep-alive\r\n";
request += "Content-Length: " + fileSize + "\r\n";
request += "Content-Type: multipart/form-data, boundary=" + boundary + "\r\n";
request += "\r\n";
request += "--" + boundary + "\r\n";
request += "Content-Disposition: form-data; name=\"filename\"; filename=\"" + fileName + "\"\r\n";
request += "Content-Type: image/png; charset=binary\r\n";
request += "Content-Transfer-Encoding: binary\r\n";
request += "\r\n";
request += "%s\r\n";
request += "\r\n";
The connection is OK, no errors and such, the fileCon by the way is from ReadFile(). And there's no error code. The number of bytes read is the same as the output of GetFileSize(). I tried displaying the contents of fileCon but only gave me this:
Don't mind the title "Error" (I set it).
Also, the request takes ages to complete, and gives me a blank response. Yep, blank with no HTTP headers. Am I doing the request right? Should I really have to include the file contents at the POST data?
Thanks in advance.
EDIT: The PNG size is about 256KB. I'm in a 1mbps connection.
EDIT: Sorry if the information was insufficient. Anyway, here's what I did lately:
int flz;
char bdata[BSIZE];
DWORD dwe, bytesRead = 0;
HANDLE fh = CreateFile(fileName.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
LPVOID fbuff = NULL;
flz = GetFileSize(fh, NULL);
fbuff = malloc(flz);
ReadFile(fh, fbuff, flz, &bytesRead, NULL));
...
sprintf_s(bdata, BSIZE, request.c_str(), reinterpret_cast<char *>(fbuff)); //BSIZE = 1024
...
send(sock, bdata, std::strlen(bdata), 0);
Not enough information to solve the problem, so I'll give a meta-answer instead:
Use a packet sniffer (e.g., wireshark) to check exactly what data is actually being sent and received. This will let you verify that the request is as it should be, and that the "blank response" you're getting really is blank.
One wild stab in the dark:
You haven't included any variable declarations in your code snippet, so I don't know what type "fileCon" is, but don't forget that the PNG data is likely to contain null bytes, which will mess up a default conversion from a char* to a std::string.
Edit:
Your modification contains the same bug that the std::string based version had, namely, that the PNG data is likely to contain null bytes. Perhaps this code will explain more clearly:
const char* data = "Hello\0world."; // some data that contains a null byte
std::string dataStr(data);
std::cout << dataStr << "\n"; // will print "Hello".
std::cout << dataStr.size() << "\n"; // will print "5"
char buf[512];
sprintf_s(buf, sizeof(buf), "Data: %s\n", data);
std::cout << buf; // will print "Data: Hello"
Both the conversion to std::string and formatting with sprintf will interpret the null byte as being the end of the data, and so the rest of the original data ("world.") will never be used.