Win32/64ネットワーク開発 003 wininetを使ったftp通信
前の記事:Win32/64ネットワーク開発 002 wininetを使ったhttp通信
次の記事:[[Win32/64ネットワーク開発 004]]
概要
wininet.Libやwininet.hのインクルードについては前の記事の通り、同じように設定する必要があります。
まずは、ホスト名やユーザID、パスワード、接続時に最初に表示するディレクトリ名を聞いてくるようなインタフェースを持たない固定値での接続を試してみましょう。接続して、FTPでカレントディレクトリを設定してカレントディレクトリが今何かを返してくれるとこまでのプログラムを書いてみます。以下のとおりです。
HINTERNET HINTERNETinet = InternetOpen(L"yo-net.jp ftp", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
HINTERNET HINTERNEThost = InternetConnect(
HINTERNETinet,
L"ftp.xxxx.com", INTERNET_DEFAULT_FTP_PORT,
L"ftp_user_name", L"ftp_user_password",
INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);
FtpSetCurrentDirectory(HINTERNEThost, L"/");
DWORD DWORDsize = 0;
FtpGetCurrentDirectory(HINTERNEThost, NULL, &DWORDsize);
wchar_t* pwchCurrentDir = new wchar_t[DWORDsize/sizeof(wchar_t)];
FtpGetCurrentDirectory(HINTERNEThost, pwchCurrentDir, &DWORDsize);
上記のプログラムにより、pwchCurrentDirにFTP接続したときの現在のディレクトリを取得できます。
InternetOpen関数についての説明はコチラのリンクから確認して下さい。FTP通信をするときはホスト名やログイン名を使うので第2引数のフラグはINTERNET_OPEN_TYPE_DIRECTを指定します。
URLを指定してhttp通信をするときは、InternetOpenUrl関数を使いましたが、FTP通信をするときはInternetConnect関数を使います。
■InternetConnect(HINTERNET, LPCWSTR, INTERNET_PORT, LPCWSTR, LPCWSTR, DWORD, DWORD, DWORD_PTR)
第1引数:HINTERNET hInternet
InternetOpen関数によって得られる、HINTERNETハンドルです。
第2引数:LPCWSTR lpszServerName
FTPサーバへのアドレスまたはホスト名を文字列で指定します。
第3引数:INTERNET_PORT nServerPort
wininet.hで INTERNET_DEFAULT_FTP_PORT には通常FTPで使われるポート番号21が設定されていますので、このキーワードを使うのが普通ですが、違うPORT番号でサーバ側がFTP通信をリスニング、受け入れ待ちをしている場合は、特定の番号を指定する必要があります。DWORD型の別名がINTERNET_PROTとなっています。0~65535の間の16bitの整数値です。
第4引数:LPCWSTR lpszUserName
FTPログインをするときのID名です。
第5引数:LPCWSTR lpszPassword
FTPログインをするときのID名に対して関連付けられたパスワード文字列です。
第6引数:DWORD dwService
アクセスするサービスの種類です。FTP(INTERNET_SERVICE_FTP)とGOPHER(INTERNET_SERVICE_GOPHER)とHTTP(INTERNET_SERVICE_HTTP)があります。FTP通信時は通常はFTPを指定します。
第7引数:DWORD dwFlags
INTERNET_FLAG_PASSIVE(0x0800 0x0000)を指定します。
第8引数:DWORD_PTR dwContext
返されるハンドルと共にコールバック関数に渡されるアプリケーション定義値を指定する変数へのポインター。一瞬なんのことをいっているかわからない説明だったと思いますが、DWORD dwContext=123(関数はDWORD_PTRの形式を必要としているので、&dwContextのように設定します)のように特定の識別値を与えることで、このあと使う関数で、この値によって複数の通信を切り分けて使うのに利用する目的で準備されている仕組みです。wininetを使うときにそこまで複雑な通信をするとは思えませんが、winsockなどで通信するときも、こういった複数のハンドル値を管理するうまい仕組みが必要だという予備知識にもなるかと思います。切り分けをするためにもこういった使い方をする手法があるということくらいは頭の隅においておいたほうがいいかもしれません。この仕組みを使わないで、適当に0と設定しておいてもいいわけです。
■FtpSetCurrentDirectory(HINTERNET, LPCWSTR)
第1引数:HINTERNET hConnect
InternetConnect関数で得られるHINTERNET型ハンドルです。
第2引数:LPCWSTR lpszDirectory
接続しているFTP通信で、現在のディレクトリとして設定したい文字列を設定します。FTPルートディレクトリからの絶対パスである必要があります。
■FtpGetCurrentDirectory(HINTERNET, LPCWSTR)
第1引数:HINTERNET hConnect,
InternetConnect関数で得られるHINTERNET型ハンドルです。
第2引数:LPWSTR lpszCurrentDirectory
接続しているFTP通信で、現在のディレクトリがどういう名前なのか取得したい文字列取得領域を設定します。FTPルートディレクトリからの絶対パスが取得できます。文字列の確保領域が取得できる文字列より小さいあるいはNULLである場合は、第3引数に必要な文字列バイト長が返却されます。UTF-16で受け取ろうとする場合は、文字列の長さの2倍となっています。
第3引数:LPDWORD lpdwCurrentDirectory
取得した文字列の長さを受け取るWORD型の変数へのアドレスを指定します。
DWORD DWORDcontext0 = 0;
DWORD DWORDcontext1 = 1;
DWORD DWORDcontext2 = 2;
DWORD DWORDcontext3 = 3;
DWORD DWORDcontext4 = 4;
DWORD DWORDcontext5 = 5;
DWORD DWORDcontext6 = 6;
FtpCreateDirectory(HINTERNEThost, L"NewFolder230101011111");
FtpRemoveDirectory(HINTERNEThost, L"NewFolder230101011111");
FtpPutFile(HINTERNEThost, //FTPのインターネットハンドル
L"File230101011111.lzh", //アップロードするファイル
L"/public_html/www.yo-net.jp/File230101011111.lzh", //アップロード先のパス付ファイル名
FTP_TRANSFER_TYPE_BINARY, //バイナリファイルとしてダウンロード
(DWORD_PTR)&DWORDcontext0);
FtpRenameFile(HINTERNEThost, L"File230101011111.lzh", L"File230101011112.lzh");
FtpRenameFile(HINTERNEThost, L"File230101011112.lzh", L"File230101011111.lzh");
WIN32_FIND_DATA WIN32_FIND_DATAfind;
FtpFindFirstFile(HINTERNEThost, L"File230101011111.lzh", &WIN32_FIND_DATAfind, 0, 0);
FtpDeleteFile(HINTERNEThost, L"File230101011111.lzh");
HINTERNET HINTERNETopen = FtpOpenFile(HINTERNEThost, L"Test_SJIS.css", GENERIC_READ, FTP_TRANSFER_TYPE_ASCII, (DWORD_PTR)&DWORDcontext1);
DWORDcontext3 = FtpGetFileSize(HINTERNETopen, (LPDWORD)&DWORDcontext2);
DWORD DWORDBufSize = 1024;
DWORD DWORDTotal = 0;
HGLOBAL HGLOBALMem;
HGLOBALMem = GlobalAlloc(GHND, 1);
char* pchOpenFileStrTotal = nullptr;
char* pchOpenFileStr = new char[DWORDBufSize + 1];
while(1){
BOOL bResult = InternetReadFile(HINTERNETopen, pchOpenFileStr, DWORDBufSize, &DWORDcontext4);
pchOpenFileStr[DWORDcontext4] = '\0';
if (DWORDcontext4 == 0) {
break;
}
DWORDTotal += DWORDcontext4;
HGLOBALMem = GlobalReAlloc(HGLOBALMem, DWORDTotal + 1, GMEM_MOVEABLE);
pchOpenFileStrTotal = (char*)GlobalLock(HGLOBALMem);
strcat_s(pchOpenFileStrTotal, DWORDTotal + 1, pchOpenFileStr);
}
int iSize = MultiByteToWideChar(932, 0U, pchOpenFileStrTotal, -1, nullptr, 0);
wchar_t* pwchOpenFileStr = new wchar_t[iSize];
MultiByteToWideChar(932, 0U, pchOpenFileStrTotal, -1, pwchOpenFileStr, iSize);
InternetCloseHandle(HINTERNEThost);
InternetCloseHandle(HINTERNETinet);
HINTERNETinet = InternetOpen(L"yo-net.jp ftp", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
HINTERNEThost = InternetConnect(
HINTERNETinet,
L"ftp.xxxx.com", INTERNET_DEFAULT_FTP_PORT,
L"ftp_user_name", L"ftp_user_password",
INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);
FtpSetCurrentDirectory(HINTERNEThost, L"/public_html/www.yo-net.jp/");
HINTERNET HINTERNETopen = FtpOpenFile(HINTERNEThost, L"Test_SJIS.css", GENERIC_READ, FTP_TRANSFER_TYPE_ASCII, (DWORD_PTR)&DWORDcontext5);
//sjisのcssファイルをUTF-8に変換する処理。
InternetWriteFile(HINTERNETopen, stringutf8String.c_str(), stringutf8String.size() - 1, &&DWORDcontext6);
前の記事:Win32/64ネットワーク開発 002 wininetを使ったhttp通信
次の記事:[[Win32/64ネットワーク開発 004]]