先日はお世話になりました。
無事に接続の受付・送受信・切断はできたのですが一つ問題が発生しました。
CとCのデータやり取りでは構造体を使用していました。
typedef struct
{
[tab=30]int m_data1;
[tab=30]int m_data2;
} tData;
tData sendData;
sendData.m_data1 = 10;
sendData.m_data2 = 20;
send(socket, (char *)&sendData, sizeof(tData), 0);
recv(socket,(char *)&sendData, sizeof(tData), 0);
といった感じです。
Cで作成したクライアントとPerlで作成したサーバーで(ソケット通信)同様の通信を行いたいのですが、
どのようにすればいいのでしょうか。
Perlの質問とも取れるので、どこに質問したらよいのか迷いましたが、
よろしければご教授していただけるとうれしいです。
C言語とperlでの通信について
Re: C言語とperlでの通信について
こんにちは、トントンです。
※先に言っておきますと、ソケット通信はやったことないので
意味不明なことを言ったら申し訳ないです。
で、幾つか質問です。
>無事に接続の受付・送受信・切断はできたのですが一つ問題が発生しました。
>Cで作成したクライアントとPerlで作成したサーバーで(ソケット通信)同様の通信を行いたいのですが
現状、何が問題なのでしょうか?
CとPerlのソケット通信ができないのでしょうか?
構造体を使用した場合、送受信ができないのでしょうか?
期待する動作は何でしょうか?
※先に言っておきますと、ソケット通信はやったことないので
意味不明なことを言ったら申し訳ないです。
で、幾つか質問です。
>無事に接続の受付・送受信・切断はできたのですが一つ問題が発生しました。
>Cで作成したクライアントとPerlで作成したサーバーで(ソケット通信)同様の通信を行いたいのですが
現状、何が問題なのでしょうか?
CとPerlのソケット通信ができないのでしょうか?
構造体を使用した場合、送受信ができないのでしょうか?
期待する動作は何でしょうか?
Re: C言語とperlでの通信について
はじめまして。ご返信ありがとうございます。
>>無事に接続の受付・送受信・切断はできたのですが一つ問題が発生しました。
>>Cで作成したクライアントとPerlで作成したサーバーで(ソケット通信)同様の通信を行いたいのですが
>現状、何が問題なのでしょうか?
>CとPerlのソケット通信ができないのでしょうか?
前述のとおり、通信は問題なくできています。
>構造体を使用した場合、送受信ができないのでしょうか?
>期待する動作は何でしょうか?[/quote]
たとえば、CとCでの通信では構造体の送受信でゲームなどを作成しています。
これを同様にCとPerl間で行う場合、同様の方法でPerl側でも構造体を利用できるのかどうか、
可能であればその方法がわかれば・・・と思っています。
これが一般的な手法かどうかはわかりません・・・。
とりあえずCで作成したソフト同士では問題なく動作しているのでこの方法を取っていました。
Cではクライアント/サーバーに共有の構造体を使用し、
クライアントから以下のようにデータを送信しています。
// 共有構造体
struct tMovePos{
[tab=30]int m_movePosX;[tab=30]// 移動先座標X
[tab=30]int m_movePosY;[tab=30]// 移動先座標Y
};
// クライアントからサーバーへデータ送信
// 正確には送受信時に確実に処理を完了するような処理、
// そして送信バッファの頭4byteにメッセージタイプを記載していますが
// ここではどのようにPerlで処理を行いたいかが主題のため省略させていただきます。
tMovePos sendBuf;
ZeroMemory(&sendBuf, sizeof(tMovePos));
sendBuf.m_movePosX = 10;
sendBuf.m_movePosY = 10;
send(serverSocket, (char *)&sendBuf, sizeof(tMovePos), 0);
次にサーバー側は受け取ったメッセージタイプごとに処理を振り分け
以下のようにデータを受信、処理しています。
tMovePos recvBuf;
recv(clientSocket, (char *)&recvBuf, sizeof(tMovePos), 0);
このサーバーの処理部分をPerlで書く場合、どのようにしたら良いのか。
という質問をさせていただきました。
Perlで構造体を使用する場合、 use Class::Struct; を記述した上で、
struct tMovePos=> {
[tab=30] m_movePosX => '$',
[tab=30] m_movePosY => '$',
};
// 構造体
my $p = new tMovePos();
// 変数msgに受信データを格納
$msg = $_;
// この後受信したデータを構造体tMovePosに型キャストしたいがうまくいかない
>>無事に接続の受付・送受信・切断はできたのですが一つ問題が発生しました。
>>Cで作成したクライアントとPerlで作成したサーバーで(ソケット通信)同様の通信を行いたいのですが
>現状、何が問題なのでしょうか?
>CとPerlのソケット通信ができないのでしょうか?
前述のとおり、通信は問題なくできています。
>構造体を使用した場合、送受信ができないのでしょうか?
>期待する動作は何でしょうか?[/quote]
たとえば、CとCでの通信では構造体の送受信でゲームなどを作成しています。
これを同様にCとPerl間で行う場合、同様の方法でPerl側でも構造体を利用できるのかどうか、
可能であればその方法がわかれば・・・と思っています。
これが一般的な手法かどうかはわかりません・・・。
とりあえずCで作成したソフト同士では問題なく動作しているのでこの方法を取っていました。
Cではクライアント/サーバーに共有の構造体を使用し、
クライアントから以下のようにデータを送信しています。
// 共有構造体
struct tMovePos{
[tab=30]int m_movePosX;[tab=30]// 移動先座標X
[tab=30]int m_movePosY;[tab=30]// 移動先座標Y
};
// クライアントからサーバーへデータ送信
// 正確には送受信時に確実に処理を完了するような処理、
// そして送信バッファの頭4byteにメッセージタイプを記載していますが
// ここではどのようにPerlで処理を行いたいかが主題のため省略させていただきます。
tMovePos sendBuf;
ZeroMemory(&sendBuf, sizeof(tMovePos));
sendBuf.m_movePosX = 10;
sendBuf.m_movePosY = 10;
send(serverSocket, (char *)&sendBuf, sizeof(tMovePos), 0);
次にサーバー側は受け取ったメッセージタイプごとに処理を振り分け
以下のようにデータを受信、処理しています。
tMovePos recvBuf;
recv(clientSocket, (char *)&recvBuf, sizeof(tMovePos), 0);
このサーバーの処理部分をPerlで書く場合、どのようにしたら良いのか。
という質問をさせていただきました。
Perlで構造体を使用する場合、 use Class::Struct; を記述した上で、
struct tMovePos=> {
[tab=30] m_movePosX => '$',
[tab=30] m_movePosY => '$',
};
// 構造体
my $p = new tMovePos();
// 変数msgに受信データを格納
$msg = $_;
// この後受信したデータを構造体tMovePosに型キャストしたいがうまくいかない
Re: C言語とperlでの通信について
>// この後受信したデータを構造体tMovePosに型キャストしたいがうまくいかない
まずC側の構造体tMovePosとPerl側のtMovePosではサイズが違うから
そのままではキャストできないのではないかと。
C言語のintは32bitの環境ならだいたい4バイトですよね。
でC側のtMovePosはintの変数がm_movePosXとm_movePosYの2つなので
8バイトのサイズだと思います(処理系によるので絶対ではありませんが)。
しかしPerl側のtMovePosで宣言されている変数はスカラ型ですよね。
スカラ型は内部的にはSVというC言語の構造体でsv.hに定義されているようです。
http://perl5.git.perl.org/APC/perl-5.005xx/sv.h
sv_anyにスカラ型で表現できる値を格納し、sv_flagsでどの
タイプの値が格納されているか判断するんだと思います。
IVだったらint,NVだったらdoubleというふうに。
sv_refcntはガベコレ関係ですかね。
つまりPerl側のtMovePosのm_movePosXとm_movePosYメンバ変数は
intではなくSV構造体が宣言されていて$msgをキャストしようにも
サイズが合わないのでうまくいかないということだとおもいます。
PerlのtMovePosをC言語風にするとこんな感じだとおもいます。実際にはもっとゴテゴテしてるはず。 C言語風のイメージはさておき、実際にはバイナリをスカラに直す必要があると思います。
なにかいいバイナリ操作のモジュールがあるかもしれませんが
基本的にはunpackをつかえばよさそうです。
このようにスカラとして取り出したのをそれぞれ代入すればいいと思います。
まちがってたらすみません。
まずC側の構造体tMovePosとPerl側のtMovePosではサイズが違うから
そのままではキャストできないのではないかと。
C言語のintは32bitの環境ならだいたい4バイトですよね。
でC側のtMovePosはintの変数がm_movePosXとm_movePosYの2つなので
8バイトのサイズだと思います(処理系によるので絶対ではありませんが)。
しかしPerl側のtMovePosで宣言されている変数はスカラ型ですよね。
スカラ型は内部的にはSVというC言語の構造体でsv.hに定義されているようです。
http://perl5.git.perl.org/APC/perl-5.005xx/sv.h
struct sv {
void* sv_any; /* pointer to something */
U32 sv_refcnt; /* how many references to us */
U32 sv_flags; /* what we are */
};
タイプの値が格納されているか判断するんだと思います。
IVだったらint,NVだったらdoubleというふうに。
sv_refcntはガベコレ関係ですかね。
つまりPerl側のtMovePosのm_movePosXとm_movePosYメンバ変数は
intではなくSV構造体が宣言されていて$msgをキャストしようにも
サイズが合わないのでうまくいかないということだとおもいます。
PerlのtMovePosをC言語風にするとこんな感じだとおもいます。実際にはもっとゴテゴテしてるはず。 C言語風のイメージはさておき、実際にはバイナリをスカラに直す必要があると思います。
なにかいいバイナリ操作のモジュールがあるかもしれませんが
基本的にはunpackをつかえばよさそうです。
#バイトエンディアンなどを考慮する必要があると思うので
#具体的にunpackの第一引数になにを指定すればいいかわからないのと、
#そもそもPerlしらないので擬似コードとして読んで下さい
($header, $x, $y) = unpack(バイナリの取り出し方を指定, $msg);
my $recv_pos = new tMovePos;
$recv_pos->m_movePosX = $x;
$recv_pos->m_movePosY = $y;
まちがってたらすみません。