お世話になっております。
mayumiです。
Windows XP SP2適用後、ソケット通信がうまく機能ができなくりました。
どのように直せばいいか検討がつかないので
投稿させて頂きました。
何か少しでも気がついた点がありましたら、
教えて頂けないでしょうか?
宜しくお願い致します。
開発環境
WindowsXP
VC++6.0
以下がソースです。
ソースの内容は、サーバにアクセスし、PASVモードで
ディレクトリ一覧を取得する。
BOOL SocketOpen(HWND ahWnd, LPCTSTR lpServName,LPCTSTR lpServUID,LPCTSTR lpServUPW)
{
int i;
WORD wVersionRequested;
int nErrorStatus;
WSADATA wsaData;
int soc; /* ソケット(Soket Descriptor) */
unsigned long serveraddr; /* サーバのIPアドレス */
struct hostent *serverhostent; /* サーバのホスト情報を指すポインタ */
struct sockaddr_in serversockaddr; /* サーバのアドレス */
char buf[MAX_PATH]; /* 受信するバッファ */
int buf_len; /* 受信したバイト数 */
char buf_sub[1024];
char szPort[8];
int port;
int pos_start, pos_end;
char *token;
char seps[] = ",";
int idx;
int intPortFirst, intPortSecond;
int list_count;
int intfirst;
/* WinSockの初期化を行う */
wVersionRequested = MAKEWORD(1, 1); /* バージョン 1.1 を要求する */
nErrorStatus = WSAStartup(wVersionRequested, &wsaData);
if (atexit((void (*)(void))(WSACleanup))) { /* 終了時にWinSockのリソースを解放するようにしておく */
fprintf(stderr,"atexit(WSACleanup)失敗\n");
MessageBox(ahWnd,"FTPセッション(atexit)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
if ( nErrorStatus != 0 ) {
fprintf(stderr,"WinSockの初期化失敗\n");
MessageBox(ahWnd,"FTPセッション(WinSock初期化)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
/* socにソケットを作成します */
soc = socket(PF_INET, SOCK_STREAM, 0);
if(soc == INVALID_SOCKET){
fprintf(stderr,"ソケット作成失敗\n");
MessageBox(ahWnd,"FTPセッション(ソケット作成)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
/* svNameにドットで区切った10進数のIPアドレスが入っている場合、serveraddrに32bit整数のIPアドレスが返ります */
serveraddr = inet_addr((char*)lpServName);
if (serveraddr == -1) {
/* サーバ名(svName)からサーバのホスト情報を取得します */
serverhostent = gethostbyname(lpServName);
if (serverhostent == NULL) {
fprintf(stderr,"ホストアドレス取得失敗\n");
MessageBox(ahWnd,"FTPセッション(ホストアドレス取得)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}else{
/* サーバのホスト情報からIPアドレスをserveraddrにコピーします */
serveraddr = *((unsigned long *)((serverhostent->h_addr_list)[0]));
}
}
printf("ポート番号---");
strcpy(szPort, "21");
port = (int)atoi(szPort);
/* サーバのアドレスの構造体にサーバのIPアドレスとポート番号を設定します */
serversockaddr.sin_family = AF_INET; /* インターネットの場合 */
serversockaddr.sin_addr.s_addr = serveraddr; /* サーバのIPアドレス */
serversockaddr.sin_port = htons((unsigned short)port); /* ポート番号 */
memset(serversockaddr.sin_zero,(int)0,sizeof(serversockaddr.sin_zero));
/* 指定のソケットでサーバへコネクトします */
if(connect(soc,(struct sockaddr *)&serversockaddr,sizeof(serversockaddr)) == SOCKET_ERROR){
fprintf(stderr,"サーバへの接続失敗\n");
shutdown(soc, 2);
closesocket(soc);
WSACleanup();
MessageBox(ahWnd,"FTPセッションを確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
wsprintf( buf, "USER %s\r\n", lpServUID);
/* 指定のソケットに文字列(buf)を送信します */
/* 送信した文字列はサーバに届きます */
if(send(soc, buf, lstrlen(buf), 0) == SOCKET_ERROR){
fprintf(stderr,"サーバへの送信失敗\n");
shutdown(soc, 2);
closesocket(soc);
WSACleanup();
MessageBox(ahWnd,"FTPセッション(サーバ送信)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
/* ソケットから文字列を受信します */
/* 受信した文字列は buf に入ります */
/* 受信する文字列はサーバが送信したものです */
buf_len = recv(soc, buf, MAX_PATH - 1, 0);
if (buf_len == SOCKET_ERROR ){
fprintf(stderr,"サーバからの受信失敗\n");
shutdown(soc, 2);
closesocket(soc);
WSACleanup();
MessageBox(ahWnd,"FTPセッション(サーバ受信)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}else{
buf[buf_len] = '\0'; /* 受信したバッファの後ろにNULLを付加する */
}
wsprintf( buf, "PASS %s\r\n", lpServUPW);
if(send(soc, buf, lstrlen(buf), 0) == SOCKET_ERROR){
fprintf(stderr,"サーバへの送信失敗\n");
shutdown(soc, 2);
closesocket(soc);
WSACleanup();
MessageBox(ahWnd,"FTPセッション(サーバ送信)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
buf_len = recv(soc, buf, MAX_PATH - 1, 0);
if (buf_len == SOCKET_ERROR ){
fprintf(stderr,"サーバからの受信失敗\n");
shutdown(soc, 2);
closesocket(soc);
WSACleanup();
MessageBox(ahWnd,"FTPセッション(サーバ受信)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}else{
buf[buf_len] = '\0'; /* 受信したバッファの後ろにNULLを付加する */
}
lstrcpy(buf, "");
lstrcpy(buf, "PASV\r\n");
if(send(soc, buf, lstrlen(buf), 0) == SOCKET_ERROR){
fprintf(stderr,"サーバへの送信失敗\n");
shutdown(soc, 2);
closesocket(soc);
WSACleanup();
MessageBox(ahWnd,"FTPセッション(サーバ送信)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
buf_len = recv(soc, buf, MAX_PATH - 1, 0);
if (buf_len == SOCKET_ERROR ){
fprintf(stderr,"サーバからの受信失敗\n");
shutdown(soc, 2);
closesocket(soc);
WSACleanup();
MessageBox(ahWnd,"FTPセッション(サーバ受信)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}else{
buf[buf_len] = '\0'; /* 受信したバッファの後ろにNULLを付加する */
}
lstrcpy(buf, "");
lstrcpy(buf, "LIST -lR\r\n");
if(send(soc, buf, lstrlen(buf), 0) == SOCKET_ERROR){
fprintf(stderr,"サーバへの送信失敗\n");
shutdown(soc, 2);
closesocket(soc);
WSACleanup();
MessageBox(ahWnd,"FTPセッション(サーバ送信)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
buf_len = recv(soc, buf, MAX_PATH - 1, 0);
if (buf_len == SOCKET_ERROR ){
fprintf(stderr,"サーバからの受信失敗\n");
shutdown(soc, 2);
closesocket(soc);
WSACleanup();
MessageBox(ahWnd,"FTPセッション(サーバ受信)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}else{
buf[buf_len] = '\0'; /* 受信したバッファの後ろにNULLを付加する */
}
/* 送受信を無効にする */
shutdown(soc, 2);
/* ソケットを破棄する */
closesocket(soc);
WSACleanup();
pos_start = 0;
pos_end = 0;
pos_start = strcspn( buf, "(" ) + 1;
pos_end = strcspn( buf, ")" );
pos_end = pos_end - pos_start;
if (pos_end < 1) {
MessageBox(ahWnd,"FTPセッション(PASS)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
strncpy( buf_sub, buf + pos_start, pos_end );
idx = 0;
token = strtok( buf_sub, seps );
while( token != NULL ){
if (idx == 4) {
intPortFirst = (int)atoi(token);
}
if (idx == 5) {
intPortSecond = (int)atoi(token);
}
token = strtok( NULL, seps );
idx = idx + 1;
}
intPortFirst = intPortFirst * 256 + intPortSecond;
/* WinSockの初期化を行う */
wVersionRequested = MAKEWORD(1, 1); /* バージョン 1.1 を要求する */
nErrorStatus = WSAStartup(wVersionRequested, &wsaData);
if (atexit((void (*)(void))(WSACleanup))) { /* 終了時にWinSockのリソースを解放するようにしておく */
fprintf(stderr,"atexit(WSACleanup)失敗\n");
MessageBox(ahWnd,"FTPセッション(atexit)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
if ( nErrorStatus != 0 ) {
fprintf(stderr,"WinSockの初期化失敗\n");
MessageBox(ahWnd,"FTPセッション(WinSock初期化)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
/* socにソケットを作成します */
soc = socket(PF_INET, SOCK_STREAM, 0);
if(soc == INVALID_SOCKET){
fprintf(stderr,"ソケット作成失敗\n");
MessageBox(ahWnd,"FTPセッション(ソケット作成)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
/* svNameにドットで区切った10進数のIPアドレスが入っている場合、serveraddrに32bit整数のIPアドレスが返ります */
serveraddr = inet_addr((char*)lpServName);
if (serveraddr == -1) {
/* サーバ名(svName)からサーバのホスト情報を取得します */
serverhostent = gethostbyname(lpServName);
if (serverhostent == NULL) {
fprintf(stderr,"ホストアドレス取得失敗\n");
MessageBox(ahWnd,"FTPセッション(ホストアドレス取得)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}else{
/* サーバのホスト情報からIPアドレスをserveraddrにコピーします */
serveraddr = *((unsigned long *)((serverhostent->h_addr_list)[0]));
}
}
/* サーバのアドレスの構造体にサーバのIPアドレスとポート番号を設定します */
serversockaddr.sin_family = AF_INET; /* インターネットの場合 */
serversockaddr.sin_addr.s_addr = serveraddr; /* サーバのIPアドレス */
serversockaddr.sin_port = htons((unsigned short)intPortFirst); /* ポート番号 */
memset(serversockaddr.sin_zero,(int)0,sizeof(serversockaddr.sin_zero));
/* 指定のソケットでサーバへコネクトします */
if(connect(soc,(struct sockaddr *)&serversockaddr,sizeof(serversockaddr)) == SOCKET_ERROR){
fprintf(stderr,"サーバへの接続失敗\n");
shutdown(soc, 2);
closesocket(soc);
WSACleanup();
MessageBox(ahWnd,"FTPセッションを確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
/* ソケットから文字列を受信します */
/* 受信した文字列は buf に入ります */
/* 受信する文字列はサーバが送信したものです */
intfirst = 0;
list_count = 0;
SendDlgItemMessage(ahWnd,IDC_FILELIST,LB_RESETCONTENT,(WPARAM)0,(LPARAM)0);
while (1) {
buf_len = recv(soc, buf, MAX_PATH - 1, 0);
if (buf_len == SOCKET_ERROR ){
fprintf(stderr,"サーバからの受信失敗\n");
shutdown(soc, 2);
closesocket(soc);
WSACleanup();
MessageBox(ahWnd,"FTPセッション(サーバ受信)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
if ((buf_len == 0) || (buf_len == -1)) {
break;
}
buf[buf_len] = '\0'; /* 受信したバッファの後ろにNULLを付加する */
i = 0;
while (buf_len > i) {
if(buf[i] == '\r'){
if(buf[i+1] == '\n'){
i++;
buf_sub[intfirst] = '\0';
if (list_count == 0) {
idx = strspn( buf_sub, "total" );
if (idx == 5) {
lstrcpy(buf_sub, ".:");
}
}
idx = strspn( buf_sub, "total" );
if (idx != 5) {
idx = strspn( buf_sub, "d");
if (idx != 1) {
SendDlgItemMessage(ahWnd,IDC_FILELIST,LB_INSERTSTRING,(WPARAM)list_count,(LPARAM)buf_sub);
list_count++;
}
}
intfirst = 0;
}
} else {
buf_sub[intfirst] = buf[i];
intfirst++;
}
i++;
}
}
/* 送受信を無効にする */
shutdown(soc, 2);
/* ソケットを破棄する */
closesocket(soc);
WSACleanup();
return(TRUE);
}
ソースコードは見てません(見る気がしません)が
WindowsFireWallの設定ではじかれてるんだと思います。
ポートを手動で開けるか、
FireWallをOffにすればよいのではないでしょうか?
ソースを丸投げするよりも、
どう機能しないのか、
どこでエラーになっているのか、
あるいはエラーになっていないのか、
そのへんを教えてください。
たく様
ご回答どうもありがとうございます。
FireWall機能を無効すれば正常動作を確認しています。
FireWall機能を無効にしない方法は無いでしょうか?
ポートを手動で開けるとありますが、
PASVモードでPORTを固定にすることはできるのでしょうか?
エラーにはなっていないです。
データ取得ができないみたいです。
1回目でログインしたときはポート番号を取得し、
再度2回目でログインしてデータ取得ができないです。
>ソースコードは見てません(見る気がしません)
そうですね (^^;;;
聞きたい事をまとめますと、
WindowsXP SP2はポート21番使えるので、
クライアントはポート21番から
サーバはPASVモード帰ってきたポート番号で
接続してデータを取得したいのですが、
どのようにすれば宜しいでしょうか?
あんまり詳しくないのであれですが、
PASVではなく通常FTPで接続すればよいように思いますが。。。
お世話になっております。
たく様
そうですね!
全くその通りなんすけど。
全体のファイル一覧を取得するときに…
FTPコマンドのLIST -lRを使って
全てのディレクトリ一覧を取得させないといけないと
いうことで今回ソケット通信をやっております。
今、PORTモードとPASVモードを勉強していて
PORTモードをどのように接続すれば良いのか
調査しております。
わからなーい o(><)o
Passiveモードであればクライアント側で
Windowsファイアウォールが有効になってるかどうかは関係なさそうな気がしますが。
(Windowsファイアウォールでは外向きの通信は関知しないので)
テスト用のFTPサーバがWindowsXP SP2上で動作していて、
こちらのファイアウォールを無効にすると通信できると言うことでしょうか。
そうであればサーバ側で例外を設定する事で動くと思います。
> クライアントはポート21番から
> サーバはPASVモード帰ってきたポート番号で
> 接続してデータを取得したいのですが、
> どのようにすれば宜しいでしょうか?
意味がいまいち分かりませんでしたが、
Passiveモードの場合はサーバから接続に来ることはありません。
PASVコマンドでサーバ側が返してきたポートへ
クライアント側から接続に行くことになります。
三毛猫 様
ご回答どうもありがとうございます。
クライアント側(WindowsXP SP2)でおこなうと
データ取得ができない。
クライアント側WindowsXP SP2)のファイアウォール機能を
無効にするとデータ取得が可能です。
例外を追加しても動作しない。
>PASVコマンドでサーバ側が返してきたポートへ
>クライアント側から接続に行くことになります。
その通りですね!^^
言い方悪かったです。すいません。
サーバ側が返してきたポートは、サーバごと?要求ごと?
に異る(ランダム)のでポートを開く場所が決められない。
[現状]
1.クライアント側ポート21番接続→FTPサーバ(ログイン完了)
2.PASV要求→FTPサーバからポート番号取得
3.ディレクトリ一覧要求
4.一旦切断(ポート21番)
5.再び2で取得したポート番号で接続
6.接続完了
7.ディレクトリ一覧のデータ取得で失敗。
ご教授宜しくお願い致します。
4番の所で制御ポートへの接続を切ってしまったら、
サーバ側でデータ用として待機中のポートも
閉じてしまうのではないでしょうか。
RFC959には
The server MUST close the data connection under the following conditions:
4. The control connection is closed legally or otherwise.
とありました。
んーと…?
FTP は接続を2本使うってのはご存知ですか?
どうも1本しか使ってないように思えますが…。
1.クライアントからサーバのポート21へ接続→ログイン
この接続は全ての転送が終了するまで繋ぎっぱなしです(接続1)。
2.PASV 要求→サーバのポート番号取得。接続(接続2)。
3.ディレクトリ一覧を、接続1で要求。
4.接続2を通じてデータを受信。接続2切断。
5.まだ何かデータの転送を行う場合、再度 PASV 発行して接続2を確立。
6.接続2でデータ送受信、切断。
7.必要に応じて 5 と 6 を繰り返す
8.これ以上転送を行わない場合、接続1切断
俺は FTP の基礎はこのへんで学びました。
http://www.atmarkit.co.jp/fnetwork/rensai/netpro10/netpro01.html
http://www.atmarkit.co.jp/fnetwork/rensai/netpro11/netpro01.html
> サーバ側が返してきたポートは、サーバごと?要求ごと?
> に異る(ランダム)のでポートを開く場所が決められない。
要求ごとに異なるので、要求ごとに毎回 PASV 発行して取得します。
お世話になっております。
こちらの私事都合のため、レス遅くなって申し訳ございません。
せっかく回答を頂いたのに本当にごめんんさい。
三毛猫 様、 シャノン様
お二人の見解では、制御ポートを繋ぎっぱなししないと
いけないとおっしゃっているのですか?
しかし、XP以外(Windows2000)では正常動作を確認できています。
もちろん、XP SP2のファイアウォール機能を無効にすれば
正常動作を確認できていますが…。。。
> 制御ポートを繋ぎっぱなししないと
> いけないとおっしゃっているのですか?
はい、そうです。
少なくとも、俺はそう理解しています(間違えていたらご指摘ください)。
> しかし、XP以外(Windows2000)では正常動作を確認できています。
> もちろん、XP SP2のファイアウォール機能を無効にすれば
> 正常動作を確認できていますが…。。。
今回の件に限らず、プログラミングをする上で忘れてはならないのは
「たまたま上手くいっている」というケースが多々あることです。
それをアテにしていると、いつかどこかでボロが出ます…というか
今回は既にボロが出ています(SP2 で動かないという)。
XP SP2 のファイアウォールを有効にしていると正常に動かないものが
間違いないコードだと断言できますか?
あるいは、ファイアウォールを無効にしないとダメな仕様だったり
ファイアウォール自体にバグがあると考えられますか?
シャノン様
その用にプログラミングして
動作確認してみたいと思います。
ご指摘ありがとうございます。
結果は後程、報告したいと思います。
>今回の件に限らず、プログラミングをする上で忘れてはならないのは
>「たまたま上手くいっている」というケースが多々あることです。
ありますね。 (^^;
>それをアテにしていると、いつかどこかでボロが出ます…というか
>今回は既にボロが出ています(SP2 で動かないという)。
>XP SP2 のファイアウォールを有効にしていると正常に動かないものが
>間違いないコードだと断言できますか?
>あるいは、ファイアウォールを無効にしないとダメな仕様だったり
>ファイアウォール自体にバグがあると考えられますか?
いえ、そうは思っていませんが…。
私的の見解では、
ファイアウォールが許可しているのは
21番のポートであり、21番ではデータの送受信は行えるが、
他のポート(パッシブで取得したポート)ではブロックされるのでは?
思っている次第です。
すいません、もう少しお付き合いの程
宜しくお願い致します。
ポートを開けておくということは、そのポートで繋ぎに行く時ではなく、そのポートでの接続を受け入れる時に必要なことです。
WinXP SP2 のファイアーウォールは、外側から自分へのアクセスはブロックしますが、自分から外側へのアクセスはブロックできません。
また、ポート 21 を開けておく必要があるのは FTP サーバ側であり、クライアントである XP SP2 側ではありません。
XP SP2 のファイアウォールでは 21 番を開けておく必要はありませんし、サーバが PASV で返したポートに XP から繋ぎに行くことを XP のファイアウォールは止めることができません。
FTP サーバも XP SP2 を使っているというなら、話は別ですが…
Windowsファイアウォールの事を気にされているようですので、
試しに他のFTPクライアントを使用してみてはいかがでしょうか。
それで問題なく通信できればファイアウォールは関係ないでしょうし、
他のFTPクライアントでもダメな場合は何か関係があるかもしれません。
いつもお世話になっております。
正常動作を確認できました!
制御ポートを切断させたのが
問題でした。
以前のプログラムは、Windows2000で
たまたま動作していたんですね (^^;
どうも本当にありがとうございます!
※何か参考なればとプログラムを掲載しときます。
シャノン 様
そういう意味ですか。
クライアント側は、ポートとか
気にしなくて宜しいですね。
勉強になります。
ご教授どうもありがとうございました。
三毛猫 様
はい。FFFTPでは正常動作しているので、
何か、特別なプログラムをしてるのでは?
ソースをダウンロードして調べても
結局わかりませんでした… (^^;
ご親切にどうもありがとうございました。
永い間、私を見捨てず、付き合ってくれて
どうもありございました。
以下ソースです。
----------------------------------------------------------------
BOOL SocketOpen(HWND ahWnd, LPCTSTR lpServName,LPCTSTR lpServUID,LPCTSTR lpServUPW)
{
int i;
WORD wVersionRequested;
int nErrorStatus;
WSADATA wsaData;
int soc1, soc2; /* ソケット(Soket Descriptor) */
unsigned long serveraddr1, serveraddr2; /* サーバのIPアドレス */
struct hostent *serverhostent1, *serverhostent2; /* サーバのホスト情報を指すポインタ */
struct sockaddr_in serversockaddr1, serversockaddr2; /* サーバのアドレス */
char buf[MAX_PATH]; /* 受信するバッファ */
int buf_len; /* 受信したバイト数 */
char buf_sub[1024];
char szPort[8];
int port;
int pos_start, pos_end;
char *token;
char seps[] = ",";
int idx;
int intPortFirst, intPortSecond;
int list_count;
int intfirst;
/* WinSockの初期化を行う */
wVersionRequested = MAKEWORD(1, 1); /* バージョン 1.1 を要求する */
nErrorStatus = WSAStartup(wVersionRequested, &wsaData);
if (atexit((void (*)(void))(WSACleanup))) { /* 終了時にWinSockのリソースを解放するようにしておく */
fprintf(stderr,"atexit(WSACleanup)失敗\n");
MessageBox(ahWnd,"FTPセッション(atexit)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
if ( nErrorStatus != 0 ) {
fprintf(stderr,"WinSockの初期化失敗\n");
MessageBox(ahWnd,"FTPセッション(WinSock初期化)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
/* socにソケットを作成します */
soc1 = socket(PF_INET, SOCK_STREAM, 0);
if(soc1 == INVALID_SOCKET){
fprintf(stderr,"ソケット作成失敗\n");
MessageBox(ahWnd,"FTPセッション(ソケット作成)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
/* svNameにドットで区切った10進数のIPアドレスが入っている場合、serveraddr1に32bit整数のIPアドレスが返ります */
serveraddr1 = inet_addr((char*)lpServName);
if (serveraddr1 == -1) {
/* サーバ名(svName)からサーバのホスト情報を取得します */
serverhostent1 = gethostbyname(lpServName);
if (serverhostent1 == NULL) {
fprintf(stderr,"ホストアドレス取得失敗\n");
MessageBox(ahWnd,"FTPセッション(ホストアドレス取得)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}else{
/* サーバのホスト情報からIPアドレスをserveraddr1にコピーします */
serveraddr1 = *((unsigned long *)((serverhostent1->h_addr_list)[0]));
}
}
printf("ポート番号---");
strcpy(szPort, "21");
port = (int)atoi(szPort);
/* サーバのアドレスの構造体にサーバのIPアドレスとポート番号を設定します */
serversockaddr1.sin_family = AF_INET; /* インターネットの場合 */
serversockaddr1.sin_addr.s_addr = serveraddr1; /* サーバのIPアドレス */
serversockaddr1.sin_port = htons((unsigned short)port); /* ポート番号 */
memset(serversockaddr1.sin_zero,(int)0,sizeof(serversockaddr1.sin_zero));
/* 指定のソケットでサーバへコネクトします */
if(connect(soc1,(struct sockaddr *)&serversockaddr1,sizeof(serversockaddr1)) == SOCKET_ERROR){
fprintf(stderr,"サーバへの接続失敗\n");
shutdown(soc1, 2);
closesocket(soc1);
WSACleanup();
MessageBox(ahWnd,"FTPセッションを確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
wsprintf( buf, "USER %s\r\n", lpServUID);
/* 指定のソケットに文字列(buf)を送信します */
/* 送信した文字列はサーバに届きます */
if(send(soc1, buf, lstrlen(buf), 0) == SOCKET_ERROR){
fprintf(stderr,"サーバへの送信失敗\n");
shutdown(soc1, 2);
closesocket(soc1);
WSACleanup();
MessageBox(ahWnd,"FTPセッション(サーバ送信)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
/* ソケットから文字列を受信します */
/* 受信した文字列は buf に入ります */
/* 受信する文字列はサーバが送信したものです */
buf_len = recv(soc1, buf, MAX_PATH - 1, 0);
if (buf_len == SOCKET_ERROR ){
fprintf(stderr,"サーバからの受信失敗\n");
shutdown(soc1, 2);
closesocket(soc1);
WSACleanup();
MessageBox(ahWnd,"FTPセッション(サーバ受信)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}else{
buf[buf_len] = '\0'; /* 受信したバッファの後ろにNULLを付加する */
}
wsprintf( buf, "PASS %s\r\n", lpServUPW);
if(send(soc1, buf, lstrlen(buf), 0) == SOCKET_ERROR){
fprintf(stderr,"サーバへの送信失敗\n");
shutdown(soc1, 2);
closesocket(soc1);
WSACleanup();
MessageBox(ahWnd,"FTPセッション(サーバ送信)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
buf_len = recv(soc1, buf, MAX_PATH - 1, 0);
if (buf_len == SOCKET_ERROR ){
fprintf(stderr,"サーバからの受信失敗\n");
shutdown(soc1, 2);
closesocket(soc1);
WSACleanup();
MessageBox(ahWnd,"FTPセッション(サーバ受信)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}else{
buf[buf_len] = '\0'; /* 受信したバッファの後ろにNULLを付加する */
}
lstrcpy(buf, "");
lstrcpy(buf, "PASV\r\n");
if(send(soc1, buf, lstrlen(buf), 0) == SOCKET_ERROR){
fprintf(stderr,"サーバへの送信失敗\n");
shutdown(soc1, 2);
closesocket(soc1);
WSACleanup();
MessageBox(ahWnd,"FTPセッション(サーバ送信)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
buf_len = recv(soc1, buf, MAX_PATH - 1, 0);
if (buf_len == SOCKET_ERROR ){
fprintf(stderr,"サーバからの受信失敗\n");
shutdown(soc1, 2);
closesocket(soc1);
WSACleanup();
MessageBox(ahWnd,"FTPセッション(サーバ受信)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}else{
buf[buf_len] = '\0'; /* 受信したバッファの後ろにNULLを付加する */
}
lstrcpy(buf, "");
lstrcpy(buf, "LIST -lR\r\n");
if(send(soc1, buf, lstrlen(buf), 0) == SOCKET_ERROR){
fprintf(stderr,"サーバへの送信失敗\n");
shutdown(soc1, 2);
closesocket(soc1);
WSACleanup();
MessageBox(ahWnd,"FTPセッション(サーバ送信)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
buf_len = recv(soc1, buf, MAX_PATH - 1, 0);
if (buf_len == SOCKET_ERROR ){
fprintf(stderr,"サーバからの受信失敗\n");
shutdown(soc1, 2);
closesocket(soc1);
WSACleanup();
MessageBox(ahWnd,"FTPセッション(サーバ受信)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}else{
buf[buf_len] = '\0'; /* 受信したバッファの後ろにNULLを付加する */
}
pos_start = 0;
pos_end = 0;
pos_start = strcspn( buf, "(" ) + 1;
pos_end = strcspn( buf, ")" );
pos_end = pos_end - pos_start;
if (pos_end < 1) {
MessageBox(ahWnd,"FTPセッション(PASS)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
strncpy( buf_sub, buf + pos_start, pos_end );
idx = 0;
token = strtok( buf_sub, seps );
while( token != NULL ){
if (idx == 4) {
intPortFirst = (int)atoi(token);
}
if (idx == 5) {
intPortSecond = (int)atoi(token);
}
token = strtok( NULL, seps );
idx = idx + 1;
}
intPortFirst = intPortFirst * 256 + intPortSecond;
/* socにソケットを作成します */
soc2 = socket(PF_INET, SOCK_STREAM, 0);
if(soc2 == INVALID_SOCKET){
fprintf(stderr,"ソケット作成失敗\n");
MessageBox(ahWnd,"FTPセッション(ソケット作成)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
/* svNameにドットで区切った10進数のIPアドレスが入っている場合、serveraddr2に32bit整数のIPアドレスが返ります */
serveraddr2 = inet_addr((char*)lpServName);
if (serveraddr2 == -1) {
/* サーバ名(svName)からサーバのホスト情報を取得します */
serverhostent2 = gethostbyname(lpServName);
if (serverhostent2 == NULL) {
fprintf(stderr,"ホストアドレス取得失敗\n");
MessageBox(ahWnd,"FTPセッション(ホストアドレス取得)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}else{
/* サーバのホスト情報からIPアドレスをserveraddr2にコピーします */
serveraddr2 = *((unsigned long *)((serverhostent2->h_addr_list)[0]));
}
}
/* サーバのアドレスの構造体にサーバのIPアドレスとポート番号を設定します */
serversockaddr2.sin_family = AF_INET; /* インターネットの場合 */
serversockaddr2.sin_addr.s_addr = serveraddr2; /* サーバのIPアドレス */
serversockaddr2.sin_port = htons((unsigned short)intPortFirst); /* ポート番号 */
memset(serversockaddr2.sin_zero,(int)0,sizeof(serversockaddr2.sin_zero));
/* 指定のソケットでサーバへコネクトします */
if(connect(soc2,(struct sockaddr *)&serversockaddr2,sizeof(serversockaddr2)) == SOCKET_ERROR){
fprintf(stderr,"サーバへの接続失敗\n");
shutdown(soc1, 2);
shutdown(soc2, 2);
closesocket(soc1);
closesocket(soc2);
WSACleanup();
MessageBox(ahWnd,"FTPセッションを確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
/* ソケットから文字列を受信します */
/* 受信した文字列は buf に入ります */
/* 受信する文字列はサーバが送信したものです */
intfirst = 0;
list_count = 0;
SendDlgItemMessage(ahWnd,IDC_FILELIST,LB_RESETCONTENT,(WPARAM)0,(LPARAM)0);
while (1) {
buf_len = recv(soc2, buf, MAX_PATH - 1, 0);
if (buf_len == SOCKET_ERROR ){
fprintf(stderr,"サーバからの受信失敗\n");
shutdown(soc1, 2);
shutdown(soc2, 2);
closesocket(soc1);
closesocket(soc2);
WSACleanup();
MessageBox(ahWnd,"FTPセッション(サーバ受信)を確立できませんでした ","Parameter Error",MB_OK|MB_ICONERROR);
return(FALSE);
}
if ((buf_len == 0) || (buf_len == -1)) {
break;
}
buf[buf_len] = '\0'; /* 受信したバッファの後ろにNULLを付加する */
i = 0;
while (buf_len > i) {
if(buf[i] == '\r'){
if(buf[i+1] == '\n'){
i++;
buf_sub[intfirst] = '\0';
if (list_count == 0) {
idx = strspn( buf_sub, "total" );
if (idx == 5) {
lstrcpy(buf_sub, ".:");
}
}
idx = strspn( buf_sub, "total" );
if (idx != 5) {
idx = strspn( buf_sub, "d");
if (idx != 1) {
SendDlgItemMessage(ahWnd,IDC_FILELIST,LB_INSERTSTRING,(WPARAM)list_count,(LPARAM)buf_sub);
list_count++;
}
}
intfirst = 0;
}
} else {
buf_sub[intfirst] = buf[i];
intfirst++;
}
i++;
}
}
/* 送受信を無効にする */
shutdown(soc1, 2);
shutdown(soc2, 2);
/* ソケットを破棄する */
closesocket(soc1);
closesocket(soc2);
WSACleanup();
return(TRUE);
}
ツイート | ![]() |