HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2014
0806
rikuriku112233hspsock 送信できない13解決


rikuriku112233

リンク

2014/8/6(Wed) 10:01:52|NO.63461

今HSPでゲームを作っていて、ログインシステムみたいなのを作ろうと思い、
クライアントからログイン要請を送り、サーバーを通して管理用クライアント
から受信して、管理クライアントからクライアントにログイン成功と同時に
ゲームの課金らしきもの(課金といっても無料)のデータを受信、というのを
やりたいのですが、実際にスクリプトを作ると送信やサーバーでの受け取り確認は
行えたのですが、管理用クライアントが応答なしになって、サーバーを閉じると同時に
受信に失敗したときに流すよう設定しておいたエラーが出る、というようになってしまい
ました。
下のスクリプトが作ってみたスクリプトです
(管理クライアント)
#include "hspsock.as"
sockopen 0,"localhost",89325;まだ1台のパソコンでしかやってません if stat = 1 :goto*error;エラーの判定 if stat = 2 :goto*error if stat = 3 :goto*error if stat = 4 :goto*error1 sockget zyume,8,0 if stat > 0 :goto*error dialog "メッセージを受信しました",0,"受信";受信したことのお知らせ mes zyume sockclose 0;ソケットを閉じる end *error dialog "エラーが発生しました",1,"エラー";エラー sockclose 0 end *error1 dialog "サーバーが開いていません",0,"接続不能";接続できないとき sockclose 0 end
(サーバー)
#include "hspsock.as"
timeout = 0 sockmake 0,89325;初期化 if stat = 1:goto*error;エラー判定 if stat = 2:goto*error1 if stat = 3:goto*error *swait sockwait 0;タイムアウト処理 timeout + 1 if timeout = 6:goto*error3 wait 300 if stat =1:goto*swait if stat =2:goto*error2 if stat =3:goto*error2 if stat =4:goto*error2 if stat =5:goto*error2 if stat =0:goto*tyakusin *error;エラー mes "エラー発生!" wait 300 sockclose 0 end *error1;エラー2 mes "初期化失敗!" wait 300 sockclose 0 end *error2;エラー3 mes "接続失敗!" wait 300 sockclose 0 end *error3;タイムアウト mes "タイムアウト!" wait 300 sockclose 0 end *tyakusin;きたことの確認 mes "着信が来ました!" wait 10000 sockclose 0 end
(普通のクライアント)
#include "hspsock.as"
sockopen 0,"localhost",89325;接続 if stat = 1 :goto*error;エラー判定 if stat = 2 :goto*error if stat = 3 :goto*error if stat = 4 :goto*error1 sockput "message",0;メッセージ送信 dialog "メッセージを送信しました",0,"送信" sockclose 0 end *error dialog "エラーが発生しました",1,"エラー";エラー sockclose 0 end *error1 dialog "サーバーが開いていません",0,"接続不能";接続不能 sockclose 0 end
どうか、解決方法を教えてください。



この記事に返信する


KOMARI

リンク

2014/8/6(Wed) 11:11:42|NO.63465

こりゃ動かないはずだ。いろいろおかしい(・ω・)……

まず、管理用クライアントってなんだろう?
サーバーが管理するんじゃだめなのかな。そっちのが手っ取り早いと思うのだが。
サーバーの管理者と、課金データの管理者が異なる場合が想定されているのだろうか。

見る限り、サーバーでのsockwaitとクライアント側でのsockgetのやり方に難がある。
sockwaitはrepeatとwait 1を使って回した方がよさそう。
sockgetに関してはsockcheckを使いましょう。
エラーに表示に関しては命令を使いましょう。コピペすぎる。

#deffunc DialogError int statid  if (errorid==0) : dialog "エラー発生!"  if (errorid==1) : dialog "初期化失敗!"  if (errorid==2) : dialog "接続失敗!"  if (errorid==3) : dialog "タイムアウト!"  wait 300  sockclose 0 return
こんな感じのを用意してネ。
endは関数内に書くのが気持ち悪かったから書いてません。

では、何で動かないかを説明しましょうか。
実際にされているやり取りはこんな感じです。

サーバー「つないできてね(・ω・)」
クライアント「つないだぜ」
管理クライアント「つないだよ、サーバーから8byteのデータを早速受け取ろうか」
クライアント「データ"message"をサーバーに送るぜ」
クライアント「役目は果たしたからドロン(end)するぜ」
サーバー「クライアントから"message"ってデータが無事届いたヽ(・ω・)ノ」
管理クライアント「ねえねえサーバーさん、8byteのデータまだー?」
サーバー「データ受信も完了したし、sockcloseしてendするよっと(・ω・)」
管理クライアント「あれ、サーバーさんがお亡くなりに(´・ω・`)」
管理クライアント「サーバーがいないんじゃsockgetしようがないなあ。エラー吐いてendすっか」

問題点はお分かりりでしょうか?
・サーバーはクライアントからデータを受け取るのみで、管理クライアントに対してデータを送信していない。
・管理クライアントは、サーバーからのデータの着信の有無にかかわらず、8byteのデータの受け取りを起動してすぐしようとしている。

サーバーにクライアント1、クライアント2が繋いでいるとする。(同じport/sockid)
クライアント1がsockid 0にデータを送信すると『サーバー』にはデータが送られるが、『クライアント2』には送られない。
ここを勘違いされているのでは?



rikuriku112233

リンク

2014/8/6(Wed) 15:34:12|NO.63482

>KOMARIさん
わかりやすい説明ありがとうございました。
そうだったんですね!
でも、実際にゲームをするときはログイン申請を送り、サーバーからデータをもらうとき、
ユーザー名やパスが間違っていたらエラー、合っていたらそのIDのデータをクライアントに
送る、という動作をさせようと思いますが、サーバーからメッセージを送るということはできる
のでしょうか?
また、自動ではできないということでしたら手動でもサーバーからメッセージを送る
ということはできるんでしょうか?



KOMARI

リンク

2014/8/6(Wed) 16:46:06|NO.63484

あ、今気づいたけど
× #deffunc DialogError int statid
○ #deffunc DialogError int errorid
でした。すいません。

>>でも、実際にゲームをするときはログイン申請を送り、サーバーからデータをもらうとき、
>>ユーザー名やパスが間違っていたらエラー、合っていたらそのIDのデータをクライアントに
>>送る、という動作をさせようと思いますが、サーバーからメッセージを送るということはできる
>>のでしょうか?
>>また、自動ではできないということでしたら手動でもサーバーからメッセージを送る
>>ということはできるんでしょうか?

私の知る限り、自動送信は無理だと思います。
手動でメッセージを送るにはsockput系命令を使用してください。
誰であろうがsockputはできます。
sockputはそのsockidに接続している者すべてに対して行われます。
要するに
・クライアントはサーバー
・サーバーはそこにつないできたクライアント全員
に対して処理されます。

さて、sockid 0にクライアントが複数つないでいるとします。
この状況だと、サーバーから特定の対象にメッセージを送信することはできませんね。
sockid毎にクライアントを割り振れば、特定の対象にのみメッセージを送れます。
これについて少し考えてみて下さい。

ヒント:
hspsockでは、クライアント毎の固有のuseridが割り振られることはない。
ipgetを使ってクライアントからipを送り、それをuseridとして認識すれば……?



rikuriku112233

リンク

2014/8/6(Wed) 16:57:27|NO.63487

下のページをみたところ、ipgetは、ホストのipを取得すると書いてあるので、
全員が同じipを送信しても、見分けがつかないのでは?
http://www.onionsoft.net/hsp/v33/doclib/hspsock.txt
(スパム判定防止)



KOMARI

リンク

2014/8/6(Wed) 17:55:46|NO.63492

詳しくはわかりませんが、ざっとテストした限りでは自分自身(ipgetした者)のIPが取得されているように見えました。
もちろん、同一者が複数のクライアントを接続する場合は、同じIPがサーバーに送信されることになりますけどね。
むしろそのおかげで2重接続防止になります。

>>ipgetは、ホストのipを取得すると書いてあるので

この発言を見る限り、ホストとサーバーを混同されていると思いますが、"ホスト"はあくまで自分のことであって"サーバー"のことではないと思います。
クライアントは、IPがわかっているからサーバーに対して接続できているのに、そのIPがわかっても仕方ないですしね。
サーバーとしてipgetを使うのであれば、クライアントに対してIPを教える為に(コピペ用に)表示するのはありでしょうね。

こういっちゃなんですが、個人的にhspsockはあまりお勧めしません。
私はこの前ネット対戦ゲームを組みましたが、あまりの不便さゆえにpcbnet2を使いました。
ちなみにpcbnet2では個別のuseridが自動で割り振られるので、クライアントの管理が楽でした。



rikuriku112233

リンク

2014/8/7(Thu) 16:01:19|NO.63522

そうなんですね!てっきりサーバーホストのことかと(w)
>sockid毎にクライアントを割り振れば、特定の対象にのみメッセージを送れます。
sockidは31までしかないので、登録者数が31人を超えた場合、もう1つポートを解放し、
新たに31個解放する、という手もあるのですが、これだと増えれば増えるほどポートが
どんどん使われて行ってしまうので、何か別の方法はないか教えてくれませんか?
>こういっちゃなんですが、個人的にhspsockはあまりお勧めしません。
たしかにpcbnetなどを使ったほうが楽にできるのですが、まだ初心者なので、pcbnet
よりhspsockのほうがわかりやすい(検索かけてもいいサイトが出なかったw)ので、
hspsockで行こうと思います。



KOMARI

リンク

2014/8/7(Thu) 17:02:38|NO.63526

>>sockidは31までしかないので、登録者数が31人を超えた場合、もう1つポートを解放し、
>>新たに31個解放する、という手もあるのですが、これだと増えれば増えるほどポートが
>>どんどん使われて行ってしまうので、何か別の方法はないか教えてくれませんか?

登録者数と同時接続数というのは必ずしも一致しませんが、もちろん登録している以上は同時接続されることを考慮しないといけませんね。
実をいうと、
http://www.atmarkit.co.jp/fwin2k/win2ktips/1349maxusr/maxusr.html
ここに書いてある通り、同時接続数にはライセンス上の限界があります。
この上限についてはサーバーの管理者の責任なので、config等で上限数を設定できるようにしましょう。
上限がない場合は仕方ないので同じsockidを使い、送信するメッセージに誰が送ったかを識別するコードをいれましょう。

例:
クライアント1がサーバーに送信する時の内容:"message \1"
 サーバーは\1を感知してクライアント1からの送信と判断する。
サーバーがクライアント2に送信する時の内容:"message \2"
 クライアント全員にこのメッセージが送られるが、自分のidが2でない人はこのメッセージを破棄する。
クライアント3がクライアント2に送信する時の内容:"message \3\2"
 まずはサーバーは\3\2の\3をみて3から着信があったと認識する。
 \3の後ろにコードが続いているのでそのコードを見る。\2らしい。
 "message \2"をクライアントに送信する。

まあ実はそんなことは問題ではないんですけどね。
どんなソフトを作るかにもよりますが、例えばチャットでなくFPSゲームのようにリアルタイムで通信するものを作るとします。
もちろんhspsockはTCP通信しかできないので、処理負荷が半端ないことになります。
32人以上なんてとてもじゃないけど考えたくないです。精々4人程度でしょうか。
もし、"リアルタイム通信をする大規模人数の接続が想定される"ソフトを作るのであればpcbnet2等のUDP通信に対応したものをお勧めします。
リアルタイムで通信をしないのであればこの限りではありませんが、人数が多くなるならば出来る限り通信量を減らすような工夫をすることは必要でしょう。

余談ですが、クライアントの接続や管理やメッセージ送受信の管理等に関するmoduleを作れば、後々ごちゃごちゃしてこなくて楽になりますよ。
実際私はそんなmoduleを作ってゲームを作成していました。



rikuriku112233

リンク

2014/8/8(Fri) 09:36:45|NO.63565

>ここに書いてある通り、同時接続数にはライセンス上の限界があります。
私のpcはなぜか日本未発売と書いてあるWindows Vista Home Basicなんですよね(w)
なので5人なんですね...
私はminecraftをしていますが、前普通のXPhomeに6人くらいサーバーに友達呼んでる
人とかいたんですよね(w)
configから設定できるようにしたいんですけどどうすればいいか...
ライセンス違反になるとどうなるんですかね。
>余談ですが、クライアントの接続や管理やメッセージ送受信の管理等に関するmoduleを作れば、
後々ごちゃごちゃしてこなくて楽になりますよ。
moduleの作り方わかんないんですよね(w)
作り方が乗ってるページとか探してみます。
>もし、"リアルタイム通信をする大規模人数の接続が想定される"
ソフトを作るのであればpcbnet2等のUDP通信に対応したものをお勧めします。
通信するのはログインとニコニコ生放送でのイベントステージのクリア判定(一番最初に
クリアした人が課金(?)ポイントがもらえるみたいなイベント)などにしか使わないので、
sockで行こうと思います。



KOMARI

リンク

2014/8/8(Fri) 11:36:40|NO.63573

>>configから設定できるようにしたいんですけどどうすればいいか...
configから設定させるなら、適当にdatファイルを作ってそこに書かせればいいんじゃないでしょうか。
[config.dat]
maxconnection = 5
[EOF]
これをどう読み込むかは考えてみてください。

>>ライセンス違反になるとどうなるんですかね。
ライセンス違反になったらどうなるかは知りませんが、知ってしまった以上は違反しないようにしたほうがいいでしょうね。
minecraftはサーバー側が上限人数を設定できるので、本来ならそこで設定するべきでしょうね。
そういえば、日本語Wikiのマルチプレイの項目に同時接続人数の一覧が書いてありましたね。

>>moduleの作り方わかんないんですよね
moduleを作る目的は、
・外部からmodule内の関数を呼ぶだけでいい
・変数名の重複を気にしなくていい
・別のプログラムに流用が利く
こんなところですかね。

まずは、2重インクルード防止のためにファイル名等重複しなそうな"名前"を決めましょう。
例として"hspsock_module_rikuriku112233"とします。

#ifndef hspsock_module_rikuriku112233  #define hspsock_module_rikuriku112233  #module   #deffunc func1   return   #defcfunc func2   return   ・・・  #global #endif
私が作る時はこんな感じにしています。参考までに。



rikuriku112233

リンク

2014/8/8(Fri) 18:59:35|NO.63583

>configから設定させるなら...
configから読み込んだ後、どうすれば
最大接続数をきめられるのですか?



名無し

リンク

2014/8/8(Fri) 19:32:47|NO.63585

接続数を管理する変数を作って接続すると+1 切断すると-1にして、
接続された時にそれが設定された数を超えていたらクライアントに警告メッセージを送り切断というようにすれば
いいと思います。
でも一瞬設定された数を1超えるのかな?



KOMARI

リンク

2014/8/8(Fri) 19:38:55|NO.63586

hspsockにそういう命令はないんで自分で管理するしかないです。
接続者数を数え、上限を超えて接続しようとしてきたらそれを打ち切る感じです。



rikuriku112233

リンク

2014/8/10(Sun) 17:11:30|NO.63677

>接続数を管理する変数を作って接続すると+1 切断すると-1にして、
>接続された時にそれが設定された数を超えていたらクライアントに
>警告メッセージを送り切断というようにすれば
>いいと思います。
この方法でやろうと思います。
解決にさせていただきます。
ありとうございました。



ONION software Copyright 1997-2018(c) All rights reserved.