「Win32/64ネットワーク開発 003 wininetを使ったftp通信」の版間の差分

提供:yonewiki
231行目: 231行目:
'''第3引数:'''LPCWSTR lpszNewRemoteFile
'''第3引数:'''LPCWSTR lpszNewRemoteFile


 アップロードしたファイルをアップロード先でのファイル名を指定したルートディレクトリからのファイルパスを含めた文字列を保持した配列変数の先頭を差す文字型のポインタです。FTP_TRANSFER_TYPE_BINARY(2)とFTP_TRANSFER_TYPE_ASCII(1)を主に指定します。FTP_TRANSFER_TYPE_BINARYの場合はファイルはそのまま送られ、FTP_TRANSFER_TYPE_ASCIIの場合は改行コードを変換する処理が入ります。CR+LFをLFだけにする変換を行います。現代においては、サーバー側に配置されるテキストがCR+LFの形式であっても問題なく表示・プログラム実行処理されるので、変換する必要はなくなってきています。ただし、変換してアップロードしたファイルがあって、取得する場合にまた変換する必要があったりはしますので、ファイルの扱い方の状況次第では必要になってきます。改行コードがごちゃごちゃしてきている可能性があります。WindowsではCR+LFにUnix系ではLFにという変換を管理する必要があります。
 アップロードしたファイルをアップロード先でのファイル名を指定したルートディレクトリからのファイルパスを含めた文字列を保持した配列変数の先頭を差す文字型のポインタです。




'''第4引数:'''DWORD dwFlags
'''第4引数:'''DWORD dwFlags


 アップロードするファイルの通信方式を定義するフラグです。
 アップロードするファイルの通信方式を定義するフラグです。FTP_TRANSFER_TYPE_BINARY(2)とFTP_TRANSFER_TYPE_ASCII(1)を主に指定します。FTP_TRANSFER_TYPE_BINARYの場合はファイルはそのまま送られ、FTP_TRANSFER_TYPE_ASCIIの場合は改行コードを変換する処理が入ります。CR+LFをLFだけにする変換を行います。現代においては、サーバー側に配置されるテキストがCR+LFの形式であっても問題なく表示・プログラム実行処理されるので、変換する必要はなくなってきています。ただし、変換してアップロードしたファイルがあって、取得する場合にまた変換する必要があったりはしますので、ファイルの扱い方の状況次第では必要になってきます。正しくない通信によって、改行コードがごちゃごちゃしてきている可能性があります。WindowsではCR+LFにUnix系ではLFにという変換を管理する必要があります。作るならば、そういったことを手助けするようなFTPツールであるべきですね。




'''第5引数:'''DWORD_PTR dwContext
'''第5引数:'''DWORD_PTR dwContext
 返されるハンドルと共にコールバック関数に渡されるアプリケーション定義値を指定する変数へのポインター。一瞬なんのことをいっているかわからない説明だったと思いますが、DWORD dwContext=123(関数はDWORD_PTRの形式を必要としているので、&dwContextのように設定します)のように特定の識別値を与えることで、このあと使う関数で、この値によって複数の通信を切り分けて使うのに利用する目的で準備されている仕組みです。wininetを使うときにそこまで複雑な通信をするとは思えませんが、winsockなどで通信するときも、こういった複数のハンドル値を管理するうまい仕組みが必要だという予備知識にもなるかと思います。切り分けをするためにもこういった使い方をする手法があるということくらいは頭の隅においておいたほうがいいかもしれません。この仕組みを使わないで、適当に0と設定しておいてもいいわけです。毎回同じことを書いてますので、以降では説明は省略しましょうかね。
<span style="color:darkred;font-weight:bold">■FtpRenameFile(HINTERNET, LPCWSTR, LPCWSTR)</span>
'''第1引数:'''HINTERNET hConnect
 InternetConnect関数で得られるHINTERNET型ハンドルです。
'''第2引数:'''LPCWSTR lpszExisting
 変更するファイルの元の名前の文字列を保持した配列変数の先頭を差す文字型のポインタです。
'''第3引数:'''LPCWSTR lpszNew
 変更するファイルの変更後の名前の文字列を保持した配列変数の先頭を差す文字型のポインタです。
<span style="color:darkred;font-weight:bold">■FtpFindFirstFile(HINTERNET, LPCWSTR, LPWIN32_FIND_DATAW, DWORD, DWORD_PTR)</span>
'''第1引数:'''HINTERNET hConnect
 InternetConnect関数で得られるHINTERNET型ハンドルです。
'''第2引数:'''LPCWSTR lpszSearchFile
 検索するファイル名の文字列を保持した配列変数の先頭を差す文字型のポインタです。
'''第3引数:'''LPWIN32_FIND_DATAW lpFindFileData
'''第4引数:'''DWORD dwFlags
'''第5引数:'''DWORD_PTR dwContext
 返されるハンドルと共にコールバック関数に渡されるアプリケーション定義値を指定する変数へのポインター。





2023年11月24日 (金) 21:38時点における版

Win32/64 ネットワーク処理開発へ戻る。

前の記事: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に変換する処理。
	wchar_t* pwchutf16String = nullptr;
	int utf16Length = MultiByteToWideChar(932, 0, pchOpenFileStrTotal, -1, NULL, 0);
	if (utf16Length > 0) {
		pwchutf16String = new wchar_t[utf16Length];
		MultiByteToWideChar(932, 0, pchOpenFileStrTotal, -1, pwchutf16String, utf16Length);
	}

	char* pchutf8String = nullptr;
	int iutf8Length = WideCharToMultiByte(CP_UTF8, 0, pwchutf16String, -1, nullptr, 0, nullptr, nullptr);
	pchutf8String = new char[iutf8Length];  // NULL 終端文字を含めないサイズに修正
	std::string stringutf8String(iutf8Length, 0);
	if (iutf8Length > 0) {
		WideCharToMultiByte(CP_UTF8, 0, pwchutf16String, -1, &stringutf8String[0], iutf8Length, nullptr, nullptr);
		stringutf8String[iutf8Length - 1] = '\0';
	}

    InternetWriteFile(HINTERNETopen, stringutf8String.c_str(), stringutf8String.size() - 1, &DWORDcontext6);

    delete[] pwchutf16String;
    delete[] pchutf8String;


■FtpCreateDirectory(HINTERNET, LPCWSTR)


第1引数:HINTERNET hConnect

 InternetConnect関数で得られるHINTERNET型ハンドルです。


第2引数:LPCWSTR lpszDirectory

 作成するディレクトリの名前の文字列を保持した配列変数の先頭を差す文字型のポインタです。


■FtpRemoveDirectory(HINTERNET, LPCWSTR)


第1引数:HINTERNET hConnect

 InternetConnect関数で得られるHINTERNET型ハンドルです。


第2引数:LPCWSTR lpszDirectory

 削除するディレクトリの名前の文字列を保持した配列変数の先頭を差す文字型のポインタです。


■FtpPutFile(HINTERNET, LPCWSTR, LPCWSTR, DWORD, DWORD_PTR)


第1引数:HINTERNET hConnect

 InternetConnect関数で得られるHINTERNET型ハンドルです。


第2引数:LPCWSTR lpszLocalFile

 アップロードするファイル名の文字列を保持した配列変数の先頭を差す文字型のポインタです。


第3引数:LPCWSTR lpszNewRemoteFile

 アップロードしたファイルをアップロード先でのファイル名を指定したルートディレクトリからのファイルパスを含めた文字列を保持した配列変数の先頭を差す文字型のポインタです。


第4引数:DWORD dwFlags

 アップロードするファイルの通信方式を定義するフラグです。FTP_TRANSFER_TYPE_BINARY(2)とFTP_TRANSFER_TYPE_ASCII(1)を主に指定します。FTP_TRANSFER_TYPE_BINARYの場合はファイルはそのまま送られ、FTP_TRANSFER_TYPE_ASCIIの場合は改行コードを変換する処理が入ります。CR+LFをLFだけにする変換を行います。現代においては、サーバー側に配置されるテキストがCR+LFの形式であっても問題なく表示・プログラム実行処理されるので、変換する必要はなくなってきています。ただし、変換してアップロードしたファイルがあって、取得する場合にまた変換する必要があったりはしますので、ファイルの扱い方の状況次第では必要になってきます。正しくない通信によって、改行コードがごちゃごちゃしてきている可能性があります。WindowsではCR+LFにUnix系ではLFにという変換を管理する必要があります。作るならば、そういったことを手助けするようなFTPツールであるべきですね。


第5引数:DWORD_PTR dwContext

 返されるハンドルと共にコールバック関数に渡されるアプリケーション定義値を指定する変数へのポインター。一瞬なんのことをいっているかわからない説明だったと思いますが、DWORD dwContext=123(関数はDWORD_PTRの形式を必要としているので、&dwContextのように設定します)のように特定の識別値を与えることで、このあと使う関数で、この値によって複数の通信を切り分けて使うのに利用する目的で準備されている仕組みです。wininetを使うときにそこまで複雑な通信をするとは思えませんが、winsockなどで通信するときも、こういった複数のハンドル値を管理するうまい仕組みが必要だという予備知識にもなるかと思います。切り分けをするためにもこういった使い方をする手法があるということくらいは頭の隅においておいたほうがいいかもしれません。この仕組みを使わないで、適当に0と設定しておいてもいいわけです。毎回同じことを書いてますので、以降では説明は省略しましょうかね。


■FtpRenameFile(HINTERNET, LPCWSTR, LPCWSTR)


第1引数:HINTERNET hConnect

 InternetConnect関数で得られるHINTERNET型ハンドルです。


第2引数:LPCWSTR lpszExisting

 変更するファイルの元の名前の文字列を保持した配列変数の先頭を差す文字型のポインタです。


第3引数:LPCWSTR lpszNew

 変更するファイルの変更後の名前の文字列を保持した配列変数の先頭を差す文字型のポインタです。


■FtpFindFirstFile(HINTERNET, LPCWSTR, LPWIN32_FIND_DATAW, DWORD, DWORD_PTR)


第1引数:HINTERNET hConnect

 InternetConnect関数で得られるHINTERNET型ハンドルです。


第2引数:LPCWSTR lpszSearchFile

 検索するファイル名の文字列を保持した配列変数の先頭を差す文字型のポインタです。


第3引数:LPWIN32_FIND_DATAW lpFindFileData


第4引数:DWORD dwFlags


第5引数:DWORD_PTR dwContext

 返されるハンドルと共にコールバック関数に渡されるアプリケーション定義値を指定する変数へのポインター。


 

前の記事:Win32/64ネットワーク開発 002 wininetを使ったhttp通信

次の記事:[[Win32/64ネットワーク開発 004]]

Win32/64 ネットワーク処理開発へ戻る。