初回のrecv関数呼び出しから制御が全く返ってきません。
以下は、WEBページを読み込むことを目的としたwinsockプログラムです。
#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 <WinSock2.h>
#pragma comment(lib, "wsock32.lib")
// this stores the got datas in "result"
// this returns true/false as Normal End or not
bool http(const std::string & URL, std::string & result)
{
result = "";
std::string url;
if(URL.find("http://") == std::string::npos) url = URL;
else url = URL.substr(7);
printf("url:%s\n", url.c_str() ); // debug
std::string domain = url.substr(0, url.find('/') );
printf("domain:%s\n", domain.c_str() ); // debug
const char lobyte = 2;
const char hibyte = 0;
// init winsock
WSADATA wsd;
bool wsdres = WSAStartup(MAKEWORD(2,0), &wsd) == 0;
if
(
atexit
(
(void (*)(void) )(WSACleanup) // cast of function pointer
)
)
{
WSACleanup();
printf("failed at atexit(WSACleanup)\n"); // debug
return false;
}
if(wsdres)
{
bool match = LOBYTE(wsd.wVersion)==lobyte && HIBYTE(wsd.wVersion)==hibyte;
if(match==false)
{
printf("failed to match version\n"); // debug
return false;
}
}
else
{
printf("failed to init winsock\n"); // debug
return false;
}
printf("succeeded to init winsock\n"); // debug
// create socket
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == INVALID_SOCKET)
{
printf("failed to create socket"); // debug
return false;
}
// get IP address
SOCKADDR_IN hostinfo;
hostinfo.sin_family = AF_INET;
hostinfo.sin_port = htons(short(80) );
HOSTENT * host = gethostbyname(domain.c_str() );
if(host==NULL)
{
printf("failed to find IP address\n"); // debug
return false;
}
hostinfo.sin_addr.S_un.S_addr = *fw::pointer_cast<uint *>(host->h_addr_list[0]);
// connect to the server
if(connect(sock, fw::pointer_cast<sockaddr *>(&hostinfo), sizeof(hostinfo) ) == SOCKET_ERROR)
{
closesocket(sock);
printf("failed to connect to socket\n"); // debug
return false;
}
// send GET request to the server
std::string request = fw::cnct()<<"GET http://"<<url<<=" HTTP/1.0\r\n\r\n";
if(send(sock, request.c_str(), sizeof(request), 0) == SOCKET_ERROR)
{
printf("failed to send\n"); // debug
printf("error:%d\n", WSAGetLastError() ); // debug
shutdown(sock, SD_BOTH);
closesocket(sock);
return false;
}
// receive the datas
const uint bufsize = 1024;
char recv_buf[bufsize];
int nBytesRecv;
printf("began recv\n"); // debug
while(true)
{
nBytesRecv = recv(sock, recv_buf, sizeof(recv_buf), 0);
printf("got a packet\n"); // debug
if(nBytesRecv == SOCKET_ERROR)
{
printf("failed to receive\n"); // debug
printf("error:%d\n", WSAGetLastError() ); // debug
break;
}
else
{
if(nBytesRecv == 0) break;
}
}
recv_buf[bufsize-1] = '\0';
result = recv_buf;
shutdown(sock,SD_BOTH);
closesocket(sock);
return true;
}
int main()
{
std::string result;
if(http("dixq.net/forum/index.php", result) ) printf("%s\n", result.c_str() );
}
試したURLは
http://dixq.net/forum/index.php
と
http://www.geocities.jp/playtown1056/program/ws_6.htm
で、どちらも初回のrecv関数呼び出しから制御がいつまでたっても返ってきませんでした。
原因も解決法も全くわかりません。
どうすればよいのでしょうか?
また、recv関数の仕様について質問があります。
recv関数に指定するバッファは途中で変更するとどのような挙動になるのでしょうか?
バッファが足りなくなってきたらそれを破棄して動的に新たなバッファを確保してそれ以後そのバッファを指定するようにすれば程よいバッファサイズを実現することができそうです。
ただ、recvがどのような仕様になっているのかわからない内は手の出しようがありません。
recvが内部でどこまで書き込んだのかをポインタ値として持っているのならば指定するバッファを途中で変更しても意味がありませんし、バッファが変更された場合はエラー終了するようになっているかもしれません。
よろしくお願いいたします。