msgrcv( )で領域破壊?

このQ&Aのポイント
  • Solaris + Cでのプロセス間通信でmsgsnd( )、msgrcv( )を使用しています。
  • プロセスAからmsgsndで送信した電文のサイズは32バイトで、受信用のバッファ(gRecv)も32バイト分用意しています。
  • しかし、msgrcvの前後で受信用バッファの後ろの領域が破壊されていることが判明しました。
回答を見る
  • ベストアンサー

msgrcv( )で領域破壊?

Solaris + Cです。 プロセス間通信でmsgsnd( )、msgrcv( )を使用しています。 プロセスAからmsgsndで送信した際に、送信電文のサイズは32バイトと設定しています。  msgsnd(iQue,&stmsg,32,IPC_NOWAIT ); また、受信するプロセスBでも受信した電文のサイズ(rcvmsgの戻り値)は32バイトと認識しており、受信用のバッファ(下記 gRecv)も32バイト分用意しています。  msgrcv(iMyQue,&gRecv,32,0,MSG_NOERROR); しかし、電文の受信(msgrcv)の前後で確認したところ、受信用に用意しているgRecvのすぐ後ろの領域を破壊していることが判明しました。 ※gRecvの中身にはプロセスAから送信した内容が正しく入っています。 msgrcv,msgsndの使用方法に誤りがあるのでしょうか?

  • mkob
  • お礼率36% (18/50)

質問者が選んだベストアンサー

  • ベストアンサー
  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.1

>msgrcv,msgsndの使用方法に誤りがあるのでしょうか? はい、誤っています。 電文を送信するときの第3パラメータ(=32)は、以下の構造体の場合、のmtextのサイズを渡す必要があります。 struct msgbuf { long int mtype; /* message type */ char mtext[1]; /* message text */ } 従って32を指定した場合は、mtypeのサイズ+32バイトが、送り出されます。(32ビットモードでは36バイト) 受信の場合も同様に、36バイトを受信することになります。 従って、 struct msgbuf *msg; として、 msgsnd(iQue,&stmsg,32-sizeof(msg->mtype),IPC_NOWAIT ); msgrcv(iMyQue,&gRecv,32-sizeof(msg->mtype),0,MSG_NOERROR); とすれば、32バイト(mtypeを含めて)が送受信できます。

mkob
質問者

お礼

解決しました。 ありがとうございました。

関連するQ&A

  • recv関数の戻り値について

    おせわになります。 socket関数(WinSock2)のrecv関数のことで質問なのですが、 第4引数にMSG_PEEKを指定したときと、指定しない時(=0) の戻り値が、明らかに違うのです。 実際は、20000バイトを送信し、受信側でrecvすると、 MSG_PEEKを指定すると、8760が返り、 MSG_PEEKを指定しない(=0)と、20000が返ります。 (もっと試して、200000と10倍にしても一回で受信しました。) recvが一度に受信できる容量のテストをしていたときに発見したのですが、こういうものなのでしょうか? 以上、よろしくおねがいします。

  • 【CAsyncSocket::OnReceive()呼び出しが遅れる?

    【CAsyncSocket::OnReceive()呼び出しが遅れる?】 MFCのCAsyncSocketを使ってTCP/IPクライアントアプリケーションより、 別マシン上のサーバアプリケーションに対して、以下の手順で非同期通信をおこなっています。 【クライアント】※以下CAsyncSocketの派生クラス関数です 接続:Connect() 電文送信:Send() *送信通知:OnSend() ※送信しきれなかったデータ送信 (実際には送信処理の分割は発生していません) *受信通知:OnReceive() 電文受信:Recv() ※ヘッダ部約60バイト分受信 受信通知:OnReceive() -----------複数回受信を想定 →電文受信:Recv() ※残りのデータ受信 ↓ (データ受信完了後) 通信終了:ShutDown() 切断:Close() クライアントから送信する電文データサイズは6000バイト弱の固定長です。 サーバから返信される電文データサイズは6000バイト弱または100バイト弱どちらかの固定長です。 サーバアプリケーションは、クライアントからの電文受信後すぐに応答電文を返信しています。 現在、*印のOnSend()呼び出し~OnReceive()呼び出しの間で、ある環境では3、4秒程度必ずかかります。 (受信電文データサイズ6000バイト弱・100バイト弱どちらも発生します) ヘッダ部約60バイト受信後は、遅れは発生していないようです。 CAsyncSocket::SetSockOpt()で送信・受信バッファサイズを65537バイトに設定してみたのですが、 改善されませんでした。 同じ(と思われる)環境を自作して(サーバアプリはテスト用自作アプリ)試してみたのですが 今のところ再現しません。 SocketDebuggerFree(http://sdg.ex-group.jp/)を使用して同じ電文データをサーバアプリに 送信してみたところ、上記のような遅延は発生せず送信後すぐに応答電文受信処理が実行されました。 パケット分割が発生しているようで、6000バイト弱のデータを3回に分けて受信しています。 クライアントアプリでもそのように分割受信されることを想定したのですが、ヘッダ部を受信した 後に1回のOnReceive()内で残りのデータすべてをReceive()によって受信しています。 (自作環境では、ヘッダ部受信後OnReceive()×2回で残りのデータを受信しています) ちなみに、クライアントマシンよりサーバマシンに社内LANを経由して接続してみたところ、 *印間の処理で2秒程度の遅延が発生します。SocketDebuggerFreeでは遅延が発生しません。 試しに、CSocketクラスとCSocketFileクラスを使用して以下の手順で処理を実行してみましたが、 同様に*印の処理の間で3、4秒程度の受信遅れが発生しました。 CSocket::Create() CSocket::Connect() *CSocketFile::Write() *CSocketFile::Read() ※ヘッダ部約60バイト分受信 CAsyncSocket::IOCtl(FIONREAD, XXX) ←※必要なデータサイズ分受信可能になるまでループ CSocketFile::Read() ※残りのデータ受信 : 上記のソケット関連関数をAPIの関数に入れ替えてみたのですが、変わりはありませんでした。 自作環境では、受信遅れは発生していません。 遅れが発生する環境の詳細がわからないので恐縮ですが、なにかお気づきの点をご指摘いただければ 幸いです。 開発環境 OS:Windows XP Professional Version 2002 SP3 Microsoft Visual C++ .NET クライアントアプリの運用環境 OS:Windows Server 2003(SP2?) サーバアプリの運用環境 不明

  • VC++ 6.0 のソケット通信について

    VC++6.0にてソケット通信プログラムを作成中(学習中)なのですが 以下のようなソケットのやり取りを想定しています。 A→B→C A←B←C 分かりづらいかもしれませんが、A,B,C三つのプログラムがあり まず、AはBに向けて電文を送信、Bはそれを受信し、Cに電文を送信 Cはそれに対してBへ電文を送信、BはCからの電文を受信しAへ電文を送信 こんな感じになっています。いうなればA,C間の中継器のような役割をBに持たせたいのです。 http://blog.livedoor.jp/akf0/archives/51585502.html ここのソースなどを参考にしてBのプログラムを組んでいるのですが サーバとクライアントでソースが分かれています。 Bはサーバもクライアントも兼ねるような仕様なのですが、この場合に使用するソケットは (1)Aからの受信を行う(待つ)ソケット (2)Cへ送信を行うソケット (3)Cからの受信を行う(待つ)ソケット (4)Aへ送信を行うソケット の4つのソケットが必要になるのでしょうか? ソケットの仕組みがうまく理解できていないので頓珍漢な質問かもしれませんが 回答よろしくお願いします。

  • UDPソケット通信におけるデータパケット

    UDPソケット通信をする際、受信データサイズとして考慮するべきサイズはアプリサイズとUDPヘッダー(8バイト)としてソケットオプションで受信バッファサイズを増加させたのですが、予想より受信できるパケット数が少ないです。 例) 1パケットのアプリサイズを10バイトしUDPヘッダーも考慮して実際1パケットあたり18バイトとして、最大5パケット受け取れるようにソケットオプションで アプリサイズ(10バイト)× UDPヘッダー(8バイト)×パケット数(5) 上記のように設定したのですが、実際5パケットも受信できませんでした。 上記のほかにIPヘッダーなども考慮しなければならないのでしょうか? 開発環境:solaris8 C言語

  • ファイルサイズの転送

    javaのファイルサイズの転送で困っています。 最初にファイルサイズを転送し、あらかじめ受信サイズを知らせておきたいのですが。。。うまくいきません。 送信側では最初にファイルサイズ4バイト(intサイズ)送信し、サイズを書き込む。 受信側では4バイト読み込み、ファイルサイズ分のバッファを用意する。 どうすれば出来るでしょうか。おねがいします。

    • ベストアンサー
    • Java
  • ポインタの引数について。

    C言語初心者です。 既存のプログラムを直そうとしているのですが、ポインタの概念がいまいち理解できていないのか、修正した箇所がうまく動きません。 どうすればよいかをご教示いただけませんでしょうか。 元のプログラムは void sub() { SOCKET s; struct msg r_msg; int time; int cc; cc = sub_recv(s, &r_msg, time); ・・・ } void sub_recv(s,*msg,time) { unsigned char *pack; int cc; int len; pack = (unsigend char *)msg cc = recv(s, (char *)pack, len, 0); if(cc < 0) return(cc); ・・・ } という感じでr_msg構造体にrecvで受け取ったものを入れて行きます。 ccにはrecv()の戻り値でサイズが返ってきて直後のifにはひっかかりません。 構造体の中でサイズが固定されているため、可変にするために以下のようにしたいです。 extern int buflen; void sub() { SOCKET s; unsigned char *r_msg; int time; int cc; r_msg=(char *)malloc(sizeof(char)*buflen ); cc = sub_recv(s, r_msg, time); free(r_msg); ・・・ } void sub_recv(s,*msg,time) { unsigned char *pack; int cc; int len; pack = (unsigend char *)msg /*ここの代入は無意味と思いますがなくしても同様の結果のなので残してます。*/ cc = recv(s, (char *)pack, len, 0); if(cc < 0) return(cc); ・・・ } しかし、このような修正で*r_msgにはrecv()で受け取った内容が入る気がするのですが、 ccには-1が入ってしまい、ifに引っかかって終了してしまいます。 この時のerrnoを見ても104が入り、connection reset by peerといった感じです。 recv()の第二引数にはこれがバッファが用意されてればいいと解釈しておりますが、 これではバッファが1バイトしかとれていないなどあるのでしょうか。 因に、send()がないからというのはありません。 キャストが間違えているなどもあるかもしれませんが、宜しくお願いします。

  • Readメソッドが次の行に処理を渡すタイミング

    C#ですが、Readメソッドを使ってバイト配列を 読み込むとき、次の処理に移るタイミングが よく分かりません(ソケットからデータを受ける時)。 例えば、JAVAなどのreadLine()などは、改行や、 EOFで、次の行に移ります。 Readは、このような、区切りが無いのでよく分かり ません。 0バイトで移るのかとも思いましたが、受信バイト数 を数えると、文字数以上のバイトはいっさい受信 されていないので、送信側で、自動で0バイトを つけているようでもありません。 それでも送信側で文字を送ると、その送信単位で 次の処理に移ってくれています。 送信から次の送信までの区切りは何で認識して いるのでしょうか(区切りがない以上、受信バッファ がいっぱいになるまで、待ってもよさそうですが)。 なにか分かる人がいましたらお願いします。

  • POSIXメッセージとは?

    こんにちわ。 私はSolaris8のC++でプログラミングをしている中級者です。 プロセス間通信の方法として、メッセージキューを使っています。 具体的には、キュー作成(msgget)、送信(msgsnd)、受信(msgrcv)、削除(msgctl)等の関数を使っているのですが、これ以外に「POSIXメッセージ」とかいうメッセージがあると聞きました。 SUNのドキュメントで調べてみたのですが、POSIXとは"Potal Operating System Interface for UNIX"で、まあUNIXベースのOSならみんな使えるような関数と解釈しました。この解釈は正しいでしょうか? そして、私が使用しているmsgXXX関数とどのように違って、どのような利点があるのでしょうか? 具体的には、上記のmsgXXXを実現するために、mq_open(), mq_close, mq_send, mq_receiveを使えば良いというだけのことなのでしょうか? POSIXメッセージとは、何か?また、こうやって使うんだよというような参考になるURLをご存じの方がいらっしゃいましたら、教えてくださいませ。

  • XMLで電文を送受信するプログラムの設計について

    システム間で電文を送受信する機能の設計を 担当することになり悩んでおります。 「相手システムに電文を送信して、その結果を受信する」または、 「相手から送信されてきた電文を受け取って、その結果を返す」 っといった設計に関してまったくの素人です。 なぜ素人に担当させるのかっといった事で突っ込まれると、 みもふたもないので、その点に関して触れないで下さい m(_ _)m とりあえず、私のレベル(下記)にあった 分かりやすい参考書、またはインターネットのサイトを見て 基礎勉強(下記)からはじめたいのですが、参考資料/サイト の紹介をお願いします。 <開発環境(案)> OS:Solaris 言語:Java(自分からAシステムへ)とPerl(自分からBシステムへ) プロトコル:https 電文形式:XML <私のレベル> https,SSL、SOAPといった通信用語の意味は知っている(つもり) Javaは実装の経験は無いが解析は出来る。 <知りたいと思っている事> ※「思っている」の意味は、今まで見た事・聞いた事からインスピレーション的に、 「多分、この辺を押さえておかなければいけないんだろうな...」っと思っている事です。 ・送受信処理のJavaの実装例 ・送受信が1秒間に100回あってもレスポンス悪化しない方法  (100回という数値は適当です。普通どれくらいを目標にするのですか?) ・通信エラー等の例外処理の実装方法  (通信エラー発生時の電文はロストするのですか?それってどうリカバリー   するのですか? その当たりに関する事) ・「なりすまし,盗聴,改ざん」っといった事に対する防御方法とその実装方法に関する事

  • ソケット通信内 read関数について

    現在C言語にソケット通信を作成しているのですが、read関数内の作成でつまずいています。 ご存知でしたら教えてください。 自分なりに調べた結果read関数の戻り値は受信した バイト数、毎回指定サイズ受け取るとは限らないと いうことでした。 そこでread関数を無限ループで回し 指定サイズ受信したら、ループを抜ける使用にしたのですが、受信バイトが0だった場合はどうすればよいのでしょか? よくサンプルなどでは、0だったらエラーと判断し、すかさずbreakしているのですが、一度でも0バイトを受信すると、それ以降は1バイト以上受信出来ないものなのでしょうか? もし出来ないのなら一度でも0を受信したら、breakしようと思っています。 出来るのでしたら、タイマー設定をし、指定受信バイトに満たなくても一定時間が過ぎたらループから抜ける使用にしたいと考えています。 そのほか良い方法があれば教えてください。 分かりずらい説明になってしまいましたが、宜しくお願い致します。