- ベストアンサー
winsockとは?
- winsockについて教えてください。
- winsockはネットワーク通信に関するライブラリです。
- Perlでクライアント側とサーバ側のソケット通信を行うプログラムを作成しましたが、クライアント側のパソコンにPerlがインストールされていなかったため、VC++に書き直しています。しかし、うまく通信できません。どこが問題なのでしょうか?
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
No.1です。 サーバ側の処理を見せてもらって気がつきましたが、 クライアントからサーバへデータを送信した後、 shutdown()関数を使って、片方向切断を実施することで 送信データの終了を伝えるつもりなのだと思います。 おそらくクライアントプログラムの送信処理 > while((fgets(send_buf,size,fp)) != 0){ > send(s,send_buf,size, 0); > } の直後に shutdown(s,SD_SEND); を入れるだけでうまく動作しそうに思います。
その他の回答 (3)
- Lchan0211
- ベストアンサー率64% (239/371)
No.1です。 再コメントします。 サーバ側の受信処理はどうなっていますか? もし、クライアントのrecv()処理のように戻り値が0に なるまで無限ループしているのだったら、 サーバはその受信ループから抜けないことに なりますよ。 サーバ側の受信処理を説明してもらうと アドバイスしやすいと思います。 おそらく、クライアントのコーディングだけの問題でなく、 サーバの処理含め通信手順を見直す必要があると思います。
補足
サーバー側のプログラムはパールなのですが、簡単に書くと use Socket; my ($host, $port, $sockaddr, $count); my $file1="file1.txt"; $port = 3001; $count = 1; # ソケットの生成 $sockaddr = pack_sockaddr_in($port, INADDR_ANY); socket(SOCKET, PF_INET, SOCK_STREAM, 0) || die "socket error.\n"; setsockopt(SOCKET, SOL_SOCKET, SO_REUSEADDR, 1) || die "setsockopt error.\n"; bind(SOCKET, $sockaddr) || die "bind error.\n"; # ポートの監視 listen(SOCKET, SOMAXCONN) || die "listen error.\n"; # クライアントから接続を待つ accept(CLIENT, SOCKET); open(IN, ">$file1") || die "ファイルが開けません\n"; #ファイルの受信 #read(CLIENT, $buf, $mtime); # クライアントからのデータの読み込み while( my $line = <CLIENT> ){ printf("%s\n",$line); print IN "$line"; } #printf("\n"); close(IN); shutdown(SOCKET,0); #入力ファイルサイズ計算 my ($mtime) = (stat($file1))[7]; printf("size=%d\n", $mtime); open(OUT,"<$file1") || die "ファイルが開けません\n"; #処理ファイルの送信 while($line = <OUT>){ print CLIENT $line; } shutdown(SOCKET,2); close(SOCKET); 上記のような感じで書きました。 どうでしょうか? たぶんおっしゃるとおり、サーバー側でずっと受信待ちの状態なのだと思います。 サーバー側かクライアント側を切らないと結果が出てこないんです。 けど、sendのとことでclosesocketを行うとおかしくなりますし、どうすればいいか...。
- Wr5
- ベストアンサー率53% (2173/4061)
>while(1){ > memset(StrRcv, '\0', sizeof(StrRcv)); > nRtn = recv(s, StrRcv, (int)sizeof(StrRcv) - 1, 0); > printf("→ %s\n\n", StrRcv); > if(nRtn == 0) break; > if(nRtn ==SOCKET_ERROR){ > perror("recvエラーです。\n"); > break; > } >} recv()は送信側が100バイトsend()したからといって、対の100バイトを受信できるとは限りません。 # そもそもストリームなのでそのような区切りはありません。 1回のsend()で256バイト送信しても、受信側では16バイト16回になるかもしれませんし、次のsend()のデータと一緒にrecv()するかもしれません。 >recv(s, buffer, size , 0); ここに到達するのは、直前のwhile(1)のループから抜けた場合になります。 recv()の戻り値が0(切断された…などの場合)かソケットエラーが発生したときだけ…になります。 切断された状態でしたらrecv()でいつまで待ってもデータは来ませんからココでずっと待ち続けることになります。
補足
こんな感じに書き直したんですが、Wr5の言うとおり、サーバーの接続を切ると画面に結果が返ってきます。 if(connect(s, (struct sockaddr *) &dest, sizeof(dest))){ printf("%sに接続できませんでした\n", destination); return -1; } printf("%sに接続しました\n", destination); while(fgets(buffer, size, fp)!=NULL){ send(s, buffer, (int)strlen(buffer), 0); } fclose(fp); //サーバからデータを受信 recv(s, recv_buf, BUFSIZE,0); printf("%s",recv_buf); // Windows でのソケットの終了 shutdown(s,2); closesocket(s); WSACleanup(); return 0; すいません。勉強不足なのかこれからどうすべきか、梃子摺っています。 かんたんな、アドバイスを頂戴できますか?
- Lchan0211
- ベストアンサー率64% (239/371)
クライアントからサーバーにファイル内容を送信する際、 ファイルのサイズを知らせてないようですが、 サーバー側はどうやって受信すべきデータのサイズが わかるのでしょうか? これがわからないから、サーバーはどれだけデータを受信したら おしまいかわからなくて、クライアントからのデータを 待ち続けているのではないでしょうか? (たぶんサーバー側はrecvを繰り返す処理になっていると 思いますが、クライアントがsendをやめても、 コネクションを切断しない限り、サーバは 次のsendがあると思ってrecv待ちになると思います。) それと、クライアントでファイルサイズを取得する方法ですが、 http://ameblo.jp/nana-2007-july/entry-10040003590.html にも書かれていますが、 ifs.peek(); streamsize size = ifs.rdbuf()->in_avail(); は、問題があります。 in_avail()は、ファイルサイズを得る関数ではなく、 受信バッファに入っているデータのサイズを得る関数です。
お礼
有難う御座います。うまく動きました。 まだまだ勉強不足でした。 もっとがんばらねば。