これは、ソケットを使用してアプリケーション間の一時的なプロセス間通信を作成するためのテストです。これらのアプリケーションは、後でカスタマイズされた組み込み通信システムを使用して別のシステムで実行されますが、現時点では後者は利用できません。その結果、これらのアプリケーション間のプロセス間通信を実装するための迅速な (おそらく少し汚れた) C++ の方法を探しています。アプリケーションはいくつかの文字列を送信します (あまり凝ったものではありません)。
オープンサウンドコントロール用のメッセージパッシングを実装するために利用するoscpackに出くわしました。udp
を使用して共有オブジェクトとしてgcc4.7.1を使用してLinuxでコンパイルしましたmake lib
。-fPIC
のCOPTS
変数にオプションを追加する必要があることに注意してくださいMakefile
。
共有ライブラリを用意して、小さな概念実証アプリケーションを作成しました。このアプリケーションは、メッセージのリスニングに別のスレッドを使用し、メイン スレッドで何らかの文字列を待機しstdin
て、それを他のアプリケーションに転送します。このアプリケーションの 2 つの非常によく似たインスタンスを実行します。2番目のインスタンスで、PORT_RCV
とのPORT_SND
数字を交換しただけです。
実際の問題はここから始まります:
私が直面している問題は、受信側でosc::UdpSocket::ReceiveFrom()
(最終的に recvfrom() を実行する) への呼び出しがブロック解除されると、ゼロ (0) に等しい読み取りバイトの戻り値を取得することです。また、char * data
ポインターはまだゼロを指しています。そのため、recvfrom() が適切なタイミングでブロック解除されたにもかかわらず、本質的に送信側アプリケーションから文字列を受信していません。
マニュアルページから、送信者が接続を閉じたときに recv と recvfrom が値 0 を返す可能性があることを読みました。しかし、この場合の送信者は udp を使用しています。
netcat
対応するポートでudpメッセージをリッスンし、少なくとも送信側が機能することを確認するために使用しようとしました。確かにnetcat -u -l -p <sender port of the running instance>
、私は入力したメッセージを受け取ります。したがって、問題はおそらく受信側に関連している可能性があります。
問題は、recvfrom を正しく使用していますか?
プロセス間通信テスト アプリケーション (実際には全二重メッセンジャー) にコードが添付されていることを確認してください。そのうちの 2 つを実行するには、まずライブラリをダウンロードしてライブラリとしてコンパイルしoscpack
ます。PORT_RCV
次に、以下のソースを 2 つのファイルにコピーし、2 つ目のソース ファイルのとPORT_SND
番号を入れ替えます。
次に、それぞれを次のようにコンパイルします。
#compile
g++ -g -Wall -Wextra -pedantic -std=c++11 -I../oscpack -c -o "obj_dbg/messenger.opp" "src/messenger.cpp"
#link
g++ -g -Wall -Wextra -pedantic -std=c++11 -I../oscpack obj_dbg/messenger.opp -o "messenger_dbg" -L../oscpack -pthread -loscpack
次に、それらを実行して単語を入力し、Enter キーを押して、それが他のアプリケーションに表示されることを期待します (表示されません)。
#include <iostream>
#include <string>
#include <string.h>
#include <thread>
#include <unistd.h>
#include "osc/OscReceivedElements.h"
#include "osc/OscPacketListener.h"
#include "ip/UdpSocket.h"
#include "osc/OscOutboundPacketStream.h"
#include "ip/UdpSocket.h"
using namespace std;
using namespace osc;
#define ADDRESS "127.0.0.1"
#define PORT_RCV 34343U
#define PORT_SND 34344U
#define IP_MTU_SIZE 1536
class EnaluPacketListener : public OscPacketListener
{
protected:
void ProcessMessage( const ReceivedMessage& m, const IpEndpointName& /*remoteEndpoint*/ )
{
//ReceivedMessageArgumentStream args = m.ArgumentStream();
ReceivedMessage::const_iterator arg = m.ArgumentsBegin();
try{
if( strcmp( m.AddressPattern(), "/info" ) == 0 )
{
msg.clear();
msg = (arg++)->AsString();
//args >> msg >> EndMessage;
if( arg != m.ArgumentsEnd() )
std::cout << "more args exist\n";
}
}
catch( Exception& e )
{
// any parsing errors such as unexpected argument types, or
// missing arguments get thrown as exceptions.
std::cout << "error while parsing message: "
<< m.AddressPattern() << ": " << e.what() << "\n";
}
}
public:
std::string msg;
};
void sendMsg(UdpTransmitSocket & transmitSocket , std::string const & msgTitle , std::string const & msg)
{
char buffer[IP_MTU_SIZE];
osc::OutboundPacketStream p( buffer, IP_MTU_SIZE );
p.Clear();
//p << osc::BeginBundleImmediate;
p << osc::BeginMessage( msgTitle.c_str() );
p << msg.c_str();
p << osc::EndMessage;
//p << osc::EndBundle;
transmitSocket.Send( p.Data(), p.Size() );
}
void rcvThread(bool bExit)
{
IpEndpointName ipen(ADDRESS,PORT_RCV);
UdpReceiveSocket s(ipen);
EnaluPacketListener pckParser;
IpEndpointName ipenRcv;
char * buffer = nullptr;
int bufferSize = 0U;
while (!bExit)
{
std::cout << "hello1\n";
int i = s.ReceiveFrom(ipenRcv,buffer,bufferSize);
if (i > 0)
{
std::cout << "bufferSize=" << bufferSize << " , buffer: " << buffer << std::endl;
//we have data
pckParser.ProcessPacket(buffer,bufferSize,ipenRcv);
std::cout << "rcved: " << pckParser.msg << "\n";
}
sleep(1);
}
}
//int main(int argc, char* argv[])
int main(int , char**)
{
bool bExit = false;
UdpTransmitSocket transmitSocket( IpEndpointName( ADDRESS, PORT_SND ) );
std::thread thr(rcvThread, std::ref(bExit));
std::string str;
while (!bExit)
{
std::cin >> str;
if ((!str.empty()) && (str.compare("q") != 0))
sendMsg(transmitSocket,"info",str);
else
bExit = true;
}
thr.join();
return 0;
}