XP SP2適用後、ソケット通信に不具合について

解決


mayumi  2004-09-24 19:39:00  No: 54551

お世話になっております。
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);  
}


たく  2004-09-24 19:56:58  No: 54552

ソースコードは見てません(見る気がしません)が
WindowsFireWallの設定ではじかれてるんだと思います。
ポートを手動で開けるか、
FireWallをOffにすればよいのではないでしょうか?

ソースを丸投げするよりも、
どう機能しないのか、
どこでエラーになっているのか、
あるいはエラーになっていないのか、
そのへんを教えてください。


mayumi  2004-09-24 22:30:34  No: 54553

たく様

ご回答どうもありがとうございます。
FireWall機能を無効すれば正常動作を確認しています。
FireWall機能を無効にしない方法は無いでしょうか?
ポートを手動で開けるとありますが、
PASVモードでPORTを固定にすることはできるのでしょうか?

エラーにはなっていないです。
データ取得ができないみたいです。
1回目でログインしたときはポート番号を取得し、
再度2回目でログインしてデータ取得ができないです。

>ソースコードは見てません(見る気がしません)

そうですね  (^^;;;


mayumi  2004-09-24 22:40:30  No: 54554

聞きたい事をまとめますと、
WindowsXP SP2はポート21番使えるので、
クライアントはポート21番から
サーバはPASVモード帰ってきたポート番号で
接続してデータを取得したいのですが、
どのようにすれば宜しいでしょうか?


たく  2004-09-24 23:31:54  No: 54555

あんまり詳しくないのであれですが、
PASVではなく通常FTPで接続すればよいように思いますが。。。


mayumi  2004-09-25 00:23:06  No: 54556

お世話になっております。

たく様
そうですね!
全くその通りなんすけど。
全体のファイル一覧を取得するときに…
FTPコマンドのLIST -lRを使って
全てのディレクトリ一覧を取得させないといけないと
いうことで今回ソケット通信をやっております。
今、PORTモードとPASVモードを勉強していて
PORTモードをどのように接続すれば良いのか
調査しております。
わからなーい  o(><)o


三毛猫  2004-09-25 02:00:24  No: 54557

Passiveモードであればクライアント側で
Windowsファイアウォールが有効になってるかどうかは関係なさそうな気がしますが。
(Windowsファイアウォールでは外向きの通信は関知しないので)

テスト用のFTPサーバがWindowsXP SP2上で動作していて、
こちらのファイアウォールを無効にすると通信できると言うことでしょうか。
そうであればサーバ側で例外を設定する事で動くと思います。

> クライアントはポート21番から
> サーバはPASVモード帰ってきたポート番号で
> 接続してデータを取得したいのですが、
> どのようにすれば宜しいでしょうか?
意味がいまいち分かりませんでしたが、
Passiveモードの場合はサーバから接続に来ることはありません。
PASVコマンドでサーバ側が返してきたポートへ
クライアント側から接続に行くことになります。


mayumi  2004-09-25 02:43:28  No: 54558

三毛猫 様

ご回答どうもありがとうございます。

クライアント側(WindowsXP SP2)でおこなうと
データ取得ができない。
クライアント側WindowsXP SP2)のファイアウォール機能を
無効にするとデータ取得が可能です。
例外を追加しても動作しない。

>PASVコマンドでサーバ側が返してきたポートへ
>クライアント側から接続に行くことになります。

その通りですね!^^
言い方悪かったです。すいません。
サーバ側が返してきたポートは、サーバごと?要求ごと?
に異る(ランダム)のでポートを開く場所が決められない。

[現状]
1.クライアント側ポート21番接続→FTPサーバ(ログイン完了)
2.PASV要求→FTPサーバからポート番号取得
3.ディレクトリ一覧要求
4.一旦切断(ポート21番)
5.再び2で取得したポート番号で接続
6.接続完了
7.ディレクトリ一覧のデータ取得で失敗。

ご教授宜しくお願い致します。


三毛猫  2004-09-25 03:07:08  No: 54559

4番の所で制御ポートへの接続を切ってしまったら、
サーバ側でデータ用として待機中のポートも
閉じてしまうのではないでしょうか。

RFC959には

The server MUST close the data connection under the following conditions:
4. The control connection is closed legally or otherwise.

とありました。


シャノン  2004-09-25 03:14:24  No: 54560

んーと…?
FTP は接続を2本使うってのはご存知ですか?
どうも1本しか使ってないように思えますが…。

1.クライアントからサーバのポート21へ接続→ログイン
  この接続は全ての転送が終了するまで繋ぎっぱなしです(接続1)。
2.PASV 要求→サーバのポート番号取得。接続(接続2)。
3.ディレクトリ一覧を、接続1で要求。
4.接続2を通じてデータを受信。接続2切断。
5.まだ何かデータの転送を行う場合、再度 PASV 発行して接続2を確立。
6.接続2でデータ送受信、切断。
7.必要に応じて 5 と 6 を繰り返す
8.これ以上転送を行わない場合、接続1切断


シャノン  2004-09-25 03:17:49  No: 54561

俺は FTP の基礎はこのへんで学びました。

http://www.atmarkit.co.jp/fnetwork/rensai/netpro10/netpro01.html
http://www.atmarkit.co.jp/fnetwork/rensai/netpro11/netpro01.html


シャノン  2004-09-25 03:43:49  No: 54562

> サーバ側が返してきたポートは、サーバごと?要求ごと?
> に異る(ランダム)のでポートを開く場所が決められない。

要求ごとに異なるので、要求ごとに毎回 PASV 発行して取得します。


mayumi  2004-10-04 21:01:28  No: 54563

お世話になっております。
こちらの私事都合のため、レス遅くなって申し訳ございません。
せっかく回答を頂いたのに本当にごめんんさい。

三毛猫 様、  シャノン様
お二人の見解では、制御ポートを繋ぎっぱなししないと
いけないとおっしゃっているのですか?
しかし、XP以外(Windows2000)では正常動作を確認できています。
もちろん、XP SP2のファイアウォール機能を無効にすれば
正常動作を確認できていますが…。。。


シャノン  2004-10-04 21:46:31  No: 54564

> 制御ポートを繋ぎっぱなししないと
> いけないとおっしゃっているのですか?

はい、そうです。
少なくとも、俺はそう理解しています(間違えていたらご指摘ください)。

> しかし、XP以外(Windows2000)では正常動作を確認できています。
> もちろん、XP SP2のファイアウォール機能を無効にすれば
> 正常動作を確認できていますが…。。。

今回の件に限らず、プログラミングをする上で忘れてはならないのは
「たまたま上手くいっている」というケースが多々あることです。
それをアテにしていると、いつかどこかでボロが出ます…というか
今回は既にボロが出ています(SP2 で動かないという)。
XP SP2 のファイアウォールを有効にしていると正常に動かないものが
間違いないコードだと断言できますか?
あるいは、ファイアウォールを無効にしないとダメな仕様だったり
ファイアウォール自体にバグがあると考えられますか?


mayumi  2004-10-04 23:52:39  No: 54565

シャノン様
その用にプログラミングして
動作確認してみたいと思います。
ご指摘ありがとうございます。
結果は後程、報告したいと思います。

>今回の件に限らず、プログラミングをする上で忘れてはならないのは
>「たまたま上手くいっている」というケースが多々あることです。

ありますね。  (^^;

>それをアテにしていると、いつかどこかでボロが出ます…というか
>今回は既にボロが出ています(SP2 で動かないという)。
>XP SP2 のファイアウォールを有効にしていると正常に動かないものが
>間違いないコードだと断言できますか?
>あるいは、ファイアウォールを無効にしないとダメな仕様だったり
>ファイアウォール自体にバグがあると考えられますか?

いえ、そうは思っていませんが…。
私的の見解では、
ファイアウォールが許可しているのは
21番のポートであり、21番ではデータの送受信は行えるが、
他のポート(パッシブで取得したポート)ではブロックされるのでは?
思っている次第です。

すいません、もう少しお付き合いの程
宜しくお願い致します。


シャノン  2004-10-05 00:45:14  No: 54566

ポートを開けておくということは、そのポートで繋ぎに行く時ではなく、そのポートでの接続を受け入れる時に必要なことです。

WinXP SP2 のファイアーウォールは、外側から自分へのアクセスはブロックしますが、自分から外側へのアクセスはブロックできません。
また、ポート 21 を開けておく必要があるのは FTP サーバ側であり、クライアントである XP SP2 側ではありません。

XP SP2 のファイアウォールでは 21 番を開けておく必要はありませんし、サーバが PASV で返したポートに XP から繋ぎに行くことを XP のファイアウォールは止めることができません。

FTP サーバも XP SP2 を使っているというなら、話は別ですが…


三毛猫  2004-10-05 01:29:42  No: 54567

Windowsファイアウォールの事を気にされているようですので、
試しに他のFTPクライアントを使用してみてはいかがでしょうか。
それで問題なく通信できればファイアウォールは関係ないでしょうし、
他のFTPクライアントでもダメな場合は何か関係があるかもしれません。


mayumi  2004-10-05 22:22:03  No: 54568

いつもお世話になっております。
正常動作を確認できました!
制御ポートを切断させたのが
問題でした。
以前のプログラムは、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);  
}


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加