非同期のソケット通信をするには


ごん  2007-09-01 11:20:53  No: 66158

.NET2005  VISTA MFC です。

非同期のソケット通信を勉強しようとして、ネット上で、サンプルコードを、ようやく1件見つけました。
しかし、サンプル通りにコーディングしようとしても、うまくいきません。
そのサイトの掲示板で問い合わせたのですが、返事が頂けず、他のサイトも見つからず、煮詰まって、こちらに質問しました。

URLは、

http://www.g-ishihara.com/mfc_nw_05.htm
http://www.g-ishihara.com/mfc_nw_06.htm

です。

サーバー側のアプリについて、
サンプルは、ダイアログベースで、CAsyncSocketクラスを基本クラスとするサブクラスを派生させています。
その上で、
「ソケットクラスのコンストラクタとCreate()関数をオーバーライドして、」と書いてあるのですが、この「Create()関数をオーバーライドして」が分りません。
クラスのプロパティの「オーバーライド」を開いても、「Create」はありません。
それならばと、「追加」→「関数の追加」で、自分で作ってみたのですが、引数の「CAsyncServerDlg *dlgP, UINT nSocketPort」が入りません。
MSDNを見ると、CAsyncSocketクラスのメンバに「Create」があるようですが、それとの関係も分りません。
関数をオーバーライドする別な方法があるのでしょうか。

また、唐突に「m_conSockP」が出てきています。
ポインタのようなのですが、どこでどう宣言しているのか分かりません。
「m_dlgP」の宣言も分りません。
サンプルの通りにやると、エラーになります。

こうしたことを、こうした掲示板で質問するのは、「掟破り」かもしれないと思ったのですが、他に方法がなく、アドバイス頂けませんでしょうか。


瀬戸っぷ  2007-09-02 10:24:00  No: 66159

MFCは使っていないのでよく分かりませんが…

> それならばと、「追加」→「関数の追加」で、自分で作ってみたのですが、引数の「CAsyncServerDlg *dlgP, UINT nSocketPort」が入りません。

は自分で入力するのでは?
「メンバ関数の追加ウィザード」で、
「戻り値の型」はページを参照するとBOOL(CAsyncSocket::Create()の取り値の型がBOOLの為でしょう)。
コンボボックスのリスト中にはありませんが、エディトボックスに入力できるはずです。
「パラメータの型」のエディトボックスに"CAsyncServerDlg"を入力、「パラメータ名」"*dlgP"と入力して、[追加]ボタンを押すと、「パラメータの一覧」に入ります。
同様にして、"UINT"と"nSocketPort"で[追加]かと。
# "CAsyncServerDlg"でなく、"CAsyncServerDlg*"、"*dlgP"ではなく"dlgP"のような気もしますが。

> 「m_dlgP」の宣言も分りません。
CreateでdlgPをコピーしていますから、型は同じなのでしょう。
ダイアログのthisポインタを入れるようですし。

> また、唐突に「m_conSockP」が出てきています。
> ポインタのようなのですが、どこでどう宣言しているのか分かりません。
ダイアログのメンバ変数のようです。
m_lsnSockは実体ですが、同じクラスのポインタとしてメンバ変数を作成すればよさそうです。

# ページ見た限りでは…確かに説明不足な印象受けますね。
## MFC詳しい方からのフォローあるといいのですが…


ごん  2007-09-02 13:42:07  No: 66160

瀬戸っぷさん、ありがとうございます。

Create(CAsyncServerDlg *dlgP, UINT nSocketPort)  について、
ご指摘のように、「CAsyncServerDlg*」&「dlgP」にすると、ビルドは通ります。

ところが、へんな言い方ですが、「m_lsnSock」と干渉するようなのです。

アプリを新規作成し、サブクラスを作って、Create(...)をつくり(この時はビルドが通ります)、次に「m_lsnSock」を作ると、Create(...)の部分でエラーが出ます。
逆に、「m_lsnSock」を先に作っても、同じ結果になります。

また、「m_conSockP」について、

> m_lsnSockは実体ですが、同じクラスのポインタとしてメンバ変数を作成すればよさそうです。

についてですが、

private:
    CServerASock* m_conSockP;

でよろしいのでしょうか。


瀬戸っぷ  2007-09-02 19:22:01  No: 66161

> アプリを新規作成し、サブクラスを作って、Create(...)をつくり(この時はビルドが通ります)、次に「m_lsnSock」を作ると、Create(...)の部分でエラーが出ます。
> 逆に、「m_lsnSock」を先に作っても、同じ結果になります。

具体的にどんなコードを書いているのか不明ですが…
サイトにあるコードの通りだとすると、
>     // ソケット作成
>     if (!err) if (!m_lsnSock.Create(this, port)) err = 1;
でエラーになる。と言うことでしょうか?
エラーになった場合、エラーメッセージが表示されるようですが、それにはなんと出ていますか?

# ポート番号入力して、[待ち受け]ボタンを押すまで、Create()は実行されないと思いますが。
# ちなみに、ポート番号で0を指定するのは止めた方が良さそうです。


瀬戸っぷ  2007-09-02 19:23:49  No: 66162

もう1つ忘れてました。

> についてですが、
> private:
>     CServerASock* m_conSockP;
> でよろしいのでしょうか。

OKだと思います。
時間無くて実際に試してはいませんが…。


b@y  2007-09-02 21:22:49  No: 66163

構文エラー : 識別子 'CAsyncServerDlg'
関数に 2 個の引数を指定できません。
識別子 'UNIT'
'CServerASock' の宣言を確認してください。


ごん  2007-09-02 21:40:09  No: 66164

すみません。
間違えて、送信してしまいました。

> エラーになった場合、エラーメッセージが表示されるようですが、それにはなんと出ていますか?

下記のように出ます。

構文エラー : 識別子 'CAsyncServerDlg'
関数に 2 個の引数を指定できません。
識別子 'UNIT'
'CServerASock' の宣言を確認してください。

その後、Create(...)を作らずにできないかと思い、ろいろやってみました。

CAsyncSocketクラスの派生クラスのコンストラクタで、

CServerASock::CServerASock()
{
    //-----------------------------------------------------■ここから
    m_conSockP = this;
    //-----------------------------------------------------■ここまで
}
//---------------------------------------------------------■ここから
CServerASock *m_conSockP = NULL;
//---------------------------------------------------------■ここまで

として、ヘッダファイルで外部宣言してみました。

m_lsnSock.Create( port)  と、直接APIを呼んでみました。
(破れかぶれみたいなものです)

ビルドは通ったのですが、実行すると例外が発生して、どうもデストラクタでひっかかっているようなのです。

で、不勉強で恥ずかしいのですが、

CServerASock::~CServerASock()
{
}

の中に、何か書きこむ必要はありますでしょうか。


瀬戸っぷ  2007-09-03 08:30:40  No: 66165

> 構文エラー : 識別子 'CAsyncServerDlg'
> 関数に 2 個の引数を指定できません。
> 識別子 'UNIT'
> 'CServerASock' の宣言を確認してください。

実行時エラーでなくコンパイルエラーですか。
上のエラーメッセージ、コピペミスでなければ型名が間違えています。
"UNIT"(ニユット)でなく"UINT"(unsigned int)です。

> CServerASock::CServerASock()
> {
>     //-----------------------------------------------------■ここから
>     m_conSockP = this;
>     //-----------------------------------------------------■ここまで
> }

C++は勉強中の身(と言いつつ5年近く経っているけど)ですが、
上記の書き方だと、自分自身を代入しているだけなのでは?


ごん  2007-09-04 14:58:27  No: 66166

瀬戸っぷさん、ありがとうございます。

ご迷惑をおかけしました。
改めて、最初からやり直してみました。

まず、「関数の追加」で、
BOOL CServerASock::Create(CAsyncServerDlg* dlgP, UINT nSocketPort)
は、ビルドを通ります。

次に、「変数の追加」で、
CServerASock m_lsnSock;
を作ると、

...\serverasock.h(10) : error C2061: 構文エラー : 識別子 'CAsyncServerDlg'
...\asyncserverdlg.h(33) : error C2146: 構文エラー : ';' が、識別子 'm_lsnSock' の前に必要です。
...\asyncserverdlg.h(33) : error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません

というエラーが出ます。

...\serverasock.h(10)は、
BOOL Create(CAsyncServerDlg* dlgP, UINT nSocketPort);
です。(関数の宣言)

...\asyncserverdlg.h(33)は、
CServerASock m_lsnSock;
で、これも変数の宣言です。

CServerASock::CServerASock()
{
    //-----------------------------------------------------■ここから
    m_conSockP = this;
    //-----------------------------------------------------■ここまで
}
//---------------------------------------------------------■ここから
CServerASock *m_conSockP = NULL;
//---------------------------------------------------------■ここまで

は、

private:
    CServerASock* m_conSockP;

がうまくいかなかったので、試してみました。
以前、教わって、時々使うやり方です。

でも、今回は、実行するとなぜか例外が発生して、デストラクタのところに見かけないタイプの緑の矢印が付いて、デバッグが止まってしまいます。

\asyncserverdlg.h(33)


ごん  2007-09-04 15:00:12  No: 66167

たびたび、不注意で、申し訳ありません。
直前のアップで、最後の行の\asyncserverdlg.h(33)は、無視してください。


fuji  2007-09-05 03:35:02  No: 66168

#include "AsyncClientDlg.h"
がClientASock.cppにないとか…?


fuji  2007-09-05 04:00:47  No: 66169

すみません、クライアントの方をやってました…
とにかく serverasock.h で CAsyncServerDlg がわからないから
エラーを起こしているのでは…?
Createをつくってビルドが通ったのでしたら
serverasock.hに
class CAsyncServerDlg;
を足してみるとか


ごん  2007-09-05 18:49:38  No: 66170

fujiさん、ありがとうございます。

ヘッダファイルは、インクルードしています。

fujiさんが試した結果では、アプリは動くのでしょうか。


fuji  2007-09-05 23:13:14  No: 66171

サーバーの方でm_conSockPを作るところまで試してみましたが
とくに問題なくビルドできてますね
ServerASock.hには
class CAsyncServerDlg;
は追加しないといけなかったですけど。


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

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






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