httpに従って、
HEADリクエストでヘッダー情報取得
↓
そこから必要な容量を読み取り、バッファを確保
↓
GETリクエストでデータを取得
ということをやりたいのですが、どうやら持続的接続ができていないようなのです。
GETリクエストを送信した後に受信するデータ量が0なのです。
一旦接続し直してからGETリクエストを送ると正常にデータを受信することができます。
以下ソースコードです。(関数などをできるだけ展開してみました)
main.cpp
► スポイラーを表示
#define _CRT_SECURE_NO_DEPRECATE
#define WIN32_LEAN_AND_MEAN
/*
#include "DxLib.h"
#define FW_DX_DEF_
//*/
#define FW_MAIN_
#define FW_STD_DEF_
//*
#define FW_STD_PROGRAMABLE_DEF_
#define FW_DX_PROGRAMABLE_DEF_
//*/
#include "../safe_fireworks/fireworks.h"
#include "includes.h"
void __cdecl cleanup();
int main()
{
	std::string url("localhost/index.html");
	vuchar content;
	std::string domain;
	std::string uri;
	SOCKET socket;
	SOCKADDR_IN hostinfo;
	// Init Winsock
	{
		const char lobyte = 2;
		const char hibyte = 0;
		WSADATA wsd;
		bool wsdres = WSAStartup(MAKEWORD(lobyte,hibyte), &wsd) == 0;
		if(wsdres)
		{
			bool match = LOBYTE(wsd.wVersion)==lobyte && HIBYTE(wsd.wVersion)==hibyte;
			if(match==false)
			{
				return -1;
			}
		}
		else
		{
			return -1;
		}
		atexit(cleanup);
	}
	// Create Socket
	{
		socket = ::socket(AF_INET, SOCK_STREAM, 0);
		if(socket == INVALID_SOCKET)
		{
			return -1;
		}
	}
	// Get Domain and URI
	{
		uint slash = url.find('/');
		domain = url.substr(0, slash);
		uri = url.substr(slash);
	}
	// Get IP
	{
		hostinfo;
		hostinfo.sin_family = AF_INET;
		hostinfo.sin_port = htons(short(80) );
		ULONG & ref = hostinfo.sin_addr.S_un.S_addr;
		ref = inet_addr(domain.c_str() );
		if(ref==INADDR_NONE)
		{
			HOSTENT * hostent = gethostbyname(domain.c_str() );
			if(hostent==NULL)
			{
				return -1;
			}
			ref = *fw::pointer_cast<uint *>(hostent->h_addr_list[0]);
		}
	}
	// Connect to Server
	{
		if(::connect(socket, fw::pointer_cast<sockaddr *>(&hostinfo), sizeof(hostinfo) ) == SOCKET_ERROR)
		{
			return -1;
		}
	}
	// HEAD Request
	{
		std::string request
		=
		fw::cnct() <<
		"HEAD " << uri << " HTTP/1.1" << "\r\n" <<
		"Host: " << domain << "\r\n" <<
		"Content-Length: 0" << "\r\n" <<
		"Connection: Keep-Alive" << "\r\n" <<=
		"\r\n";
		if(::send(socket, request.c_str(), request.length(), 0) == SOCKET_ERROR)
		{
			return -1;
		}
	}
	// Receive Header
	{
		HTTPheader header;
		header.buffer.setsize(1024);
		uint HeadSize = 0;
		while(true)
		{
			int nBytesRecv = recv(socket, header.bufhead(), header.buffer.size(), 0);
			HeadSize += nBytesRecv;
			if(nBytesRecv == SOCKET_ERROR)
			{
				return -1;
			}
			else
			{
				if(nBytesRecv == 0) break;
			}
		}
		
		header.buffer.setsize(HeadSize);
		header.analyze();
		// Show Header
		header.buffer.add('\0');
		printf("header:\n%s\n\n", header.bufhead() );
		header.buffer.pop();
		// Require Buffer for Header and Body
		if(header.UsefulContentLength() )
		{
			content.setsize(HeadSize + header.ContentLength() );
			printf("Size of Header and Body:%d\n", content.size() );
		}
		else
		{
			printf("Not Found UsefulContentLength\n");
			return -1;
		}
	}
	// GET Request
	{
		std::string request
		=
		fw::cnct() <<
		"GET " << uri << " HTTP/1.1" << "\r\n" <<
		"Host: " << domain << "\r\n" <<
		"Content-Length: 0" << "\r\n" <<
		"Connection: Keep-Alive" << "\r\n" <<=
		"\r\n";
		if(::send(socket, request.c_str(), request.length(), 0) == SOCKET_ERROR)
		{
			printf("Failed to Send 'GET Request'\n");
			return -1;
		}
	}
	// Receive Header and Body
	{
		uint total = 0;
		while(true)
		{
			int nBytesRecv = recv(socket, fw::pointer_cast<char *>(content.head() ), content.size(), 0);
			total += nBytesRecv;
			if(nBytesRecv == SOCKET_ERROR)
			{
				printf("SOCKET ERROR\n");
				return -1;
			}
			else
			{
				if(nBytesRecv == 0) break;
			}
		}
		content.setsize(total);
		// Show Header and Body
		content.add('\0');
		printf("Header and Body:\n%s\n", content.head() );
		content.pop();
	}
	// Disconnect
	{
		shutdown(socket, SD_BOTH);
		closesocket(socket);
	}
	return 0;
}
void __cdecl cleanup(){ WSACleanup(); }► スポイラーを表示
► スポイラーを表示
#pragma once
class HTTPheader
{
public:
	vuchar buffer;
	HTTPheader()
	:
	strContentLength("Content-Length"),
	strConnection("Connection"),
	strLocation("Location")
	{}
	char * bufhead(){ return fw::pointer_cast<char *>(buffer.head() ); }
	uint bufsize() const { return buffer.size(); }
	void analyze(const char * str)
	{
		//content-valueの中に,が入る物があるとリストと区別できない。また、その場合正しく分割できていない
		fw::slice lines;
		lines(str, "\r\n");
		for(uint i=lines.size()-1;i>1;--i)
		{
			const char first = lines[i][0];
			if(first==' ' || first=='\t')
			{
				lines[i-1] += lines[i];
				lines.pop();
			}
		}
		char phrase[32];
		sscanf(lines[0].c_str(),"HTTP/%s %s %s", Version,Code,phrase);
		for(uint i=1;i<lines.size();++i)
		{
			uint colon = lines[i].find(':');
			uint beg = lines[i].find_first_not_of(" \t", colon+1);
			fw::slice param;
			param(lines[i].substr(beg), ",");
			vstring & ref = table[lines[i].substr(0, colon)];
			for(uint j=0;j<param.size();++j)
			{
				ref.add(param[j].substr(param[j].find_first_not_of(" \t") ) );
				uint spht = ref.last().find_first_of(" \t");
				ref.last() = ref.last().substr(0, spht);
			}
		}
	}
	void analyze()
	{
		buffer[buffer.size()-2] = uchar('\0');
		analyze(bufhead() );
	}
	bool ResponseIs2XX() const { return Code[0]=='2'; }
	bool ResponseIs3XX() const { return Code[0]=='3'; }
	bool UsefulContentLength() const { return table[strContentLength].size()>0; }
	uint ContentLength() const { return atoi(table[strContentLength][0].c_str() ); }
	bool UsefulConnection() const { return table[strConnection].size()>0; }
	bool ConnectionIsKeepAlive() const { return table[strConnection][0]=="Keep-Alive"; }
	bool UsefulLocation() const { return table[strLocation].size()>0; }
	const std::string & Location() const { return table[strLocation][0]; }
private:
	mutable std::map<std::string, vstring> table;
	char Version[4];
	char Code[4];
	const std::string strContentLength;
	const std::string strConnection;
	const std::string strLocation;
};safe_fireworksのみ
safe_fireworks + ソースコードファイル(3つ全て)
※クリックした瞬間ダウンロードされます



 メニュー
 メニュー カレンダー
 カレンダー Clock
 Clock 最新メンバー
 最新メンバー 投稿数
 投稿数 Link to us
 Link to us カウンター
 カウンター