質問

では基本的には一つのアプリに設置されている複数のPCでは、各トを維持で自分のデータベースでは同期の思いを他のときがあり、それぞれ特色があって同一のネットワークに接続される)でも同時に行います。

私はこの試験は簡単なソケット接続とカスタムバッファがいのcomms間はアプリケーションに適合し認められた基準とすることを確保/堅調に推移し、してみませんの再発明をするつもりはありま

どノーマル/標準の仕このアプリをアプリcomms&っておりますぐ。

また、どんな技術が利用できるし、他のアプリをネットワーク?


編集:(石油精製私の問題)

The pub/subモデル"によって指定されたgimel以下のようだが、私が必要です。では作るのはいい思いを持つことができる使用からすべてのこと。

もうを確立する必要があるP2P接続を一度に二つ以上のアプリに見られない。

がある場合例/チュートリアルのご利用となりますので、ご点んで頂きたいと思います。小さなオープンソースのソフトウェア-モジュールを実装したようなものかいもあります。

私のホーム選択はLinux、Windowsベースの例としてもご利用いただけます。


編集[09-01-06]:

私は現在、以下のオプション:

  1. multicasting (TLDP-ハウトゥ)-このよう可能なものかを研究する必要があるのである。
  2. 利用無料ダイナミックDNSサーバーは、このように見えるビットdicey...
  3. 用のフリーメール施設などgmail/yahoo/...送信し/メールを読むのが見その他のアプリケーションのIPので、気汚)
  4. webサービスることが示唆されているが、わからないから仕事としての研究で

私は皆さまからのご意見これらのオプションがある場合の例があります。私は残念ながらないオプションを使用し、中央サーバやウェブサイトの除できる保証をするために常設)しています。

[編集2009-02-19]

(ってしまいまし受け入れにつ/三回答!私が最も気に入っていっていただくようお願い申し上げで行う可能性がって固定が適なソリューション。下さった皆様、ありがとうござ答えで役立っています。)

しが見/実行っ液を更新しますことを解決する適切ない作sourceforgeプロジェクトです。(ある場合小さなけの問題で分かれます。)

役に立ちましたか?

解決

んー、

このような数学の問題です。かつコンピュータ 接続を確立する 回答を見つけ出すのではかなり簡単です。ご利用できますのP2Pまたはクライアント-サーバプロトコル SSL ほぼ普遍的にご利用いただけますがおられる可能性がある SSH, 実 Freenet などを実行します。一度接続を確立するため、このプロトコル、publish/Subscribeモデル データ交換 が多くなっております。がありま

このようにコンピュータを探することがで取り上げるべきだったトリッキー.が本質的には例:

  1. すべてのコンピュータを自分ですることができます。 この場合、コンピュータがオンラインでの放送るメッセージでオンラインやメッセージ裏面に関する他の機械です。忘れずに放送/マルチキャストメッセージはあらゆる機械をネットワークではないでいきます。できないこのインターネットではできませんメッセージを送るあらゆる機械。

  2. コンピュータに任意のノードのインターネット** **が与えられたテーブルを作成するコンピューターに接続してweb** **すべての機械とオンライン。 この場合、各マシンでランニングリストのIPアドレスを使います。機械がるオフラインが戻オンラインでチェックのための既知のアドレスに接続する初の有効なアドレスはどのようにemuleプロトコルがサーバー

  3. コンピュータに任意のノードのインターネット** **すべての機械をオフラインと** または **かくオフラインでの長期間がotheersスイッチのIPアドレスを使います。 ここではないと思うからできることを示しなければならない新しい機械を多くの方の参加をお待ちしてお見その他の各 なし 一部の中央サーバへのリンク共通。る方法はありませんの放送メッセージを通じて、インターネットできます。こうしたもとで、コンピュータを特定する情報その他の機械らオンラインで利用する必要があり、共通のリソース:をいただいたメールアドレスが、ウェブサイト、ftpサーバー、IRCチャンネルは、ダイナミックDNSは一つのインスタンスを一元化された情報ます。が発生する場合には、利用などのお店ですべてを評価するの店のために利用できる信頼性、速度、目と耳で感じることができ、貴重.される場合を除き、情報のほとんどのアプリケーションのニーズに関すとは思わない人を決めることができる常設店舗あります。

このケーション能力の向上に取り組も可能です。いうこれらの一般的な場合お申込に該当するとその決定のプロトコルを組み合わせます。

編集:

から、その場合3が適用される。から推論できる上記すべきで存在することが明らかではないような何らかの外部サーバを探すしかないようで針にhaystackは身体の安全を確保するためです。品質につくようなプロバイダ:

  • 信頼性:どのくらいのものまで与えられた日
  • 速度:いかなものに対応
  • 目と耳で感じることができ、貴重:どのように長められていくと期待しているものですか。ま本体を万が一紛失してしまっへのアクセスとしてのインターネットの進化?

このように、多く簡単に利用可能な資源がります。メールサーバーして現在お使いのwebサーバー、FTPサーバ、DNSサーバー、IRCチャネルのつながりのないユーザーは、ウェブフォーラム....

の問題にアプリケーションが生み出されるのが、更新を必要とせずに、中央サーバは共通の問題で共通を中心にウイルスのライター-ちょうど約あらゆる組織の資源を生かしたアプリケーションにも資源を維持し、中央サーバーです。とはいえ、標準的なソリューションの付属、メール、httpサーバー、ftpサーバー、IRCチャンネルとダイナミックDNSサーバー異なるサーバーのそれぞれの項目がないよう、速度、信頼性、永続性の課題を選ぶ際にはお客様ご自身のご判断.IRCチャネルの値もない方が簡単でスピーディーがこれらが実際にフェードインターネットの進化

例として配布アプリを使用してクライアントの発見"技術で、ダウンロードできます の源BO2K, 、、"リモート管理ユーティリティ".このもつすべての機能のリモート更新します。

を繰り返す。私が部品をお客様の問題点:

  1. 機械見れます(上記を参照)
  2. 機械の接続の確立も、SSL、SSH等のご利用が可能で)
  3. の機器の交換-データです。を使用してくださ"を公開/購読"のモデルやロール自分で簡単に プロトコル.私の会社が自動更新のお客さんにしました。その理由を作成するプロトコルとしては、1)の中でも最も単純な場合には、要求に迅速かつ信頼性としてのデータ交換2.最も簡単なデータの交換が必要でわずか数行のコードで一気に次のプロトコルのための本当の簡単なデータ交換、3.以降では各種アプリケーションの使用方法や言語、プロトコルを簡単にデータ交換になります。のために複雑な状況が実際に全体の森林のプロトコルが異なり複雑なだぎこちない使用のための簡単なデータ交換を行えます。の方法を応用すること git scm 送信データの更新プロトコルです。だるまのデータベースに似てのソースコードgitを送信し、利用gitを維持するためにデータベースです。そのチャンスは更新か違うgitはとです。別の例とプロトコルは一または別バージョンの webサービス など、まさに日進月歩であります。これらのプロトコルだけで 包む の処理を呼び出す機能を一台の機械を使用xmlおよびhttp.できれば、既に確立ソケットとアプリケーションを理由はありませんよろしくお願いします。記憶に導入できるウェブサービスを使う必要があり、走りのhttpサーバの構文解析のxmlるhttpお客様へのデータを収集します。を考慮に送信できるデータを直接ソケットな関係ではないかと思います。していただく必要があり戻転がります。

とにかく、簡単なプロトコルがす:

  • 一つのアプリ初に送のインデックス データでの配列としてスを作成します。
  • その他のアプリを送信しリストの項目で
  • その最初のアプリに送信者の実際のです。

その後、アプリの役割を変更データの交換、その他。あらかにすることを目指してハンドシェーク"に貴議定書のようになります疑似コード

void update_database(in_stream, out_stream) {
  Get_Index_Of_Other_Machines_Items(in_stream);
  Send_Index_Of_Items_You_Need(out_stream);
  Get_Items_You_Need(in_stream);
}

他の機能を反対側の面にはこれらのデータです。

さらに検討する場合の各エントリデータベースに生成される独立して、生成するIDのこなしで参照すべての項目に分散データベースです。き出すことができ GUID それどころか、もし大きな乱数です。

誰して調節のために開発される場合には使用します。

意すること 場合にアプリケーションがすべてだけたまに更新, がなされている一意のインスタンスにてデータ項目です。例えば、仮に、一日では、機械だけではなくオンライン 5:00pm、残りの半分のみオンライン 5:00pm.この場合には、両グループの機械を共有しないデータは一切の場合で直接更新します。場合は、機んでも配布時よりによるパターンのように説明した)するおそれがあると認められるときそれぞれのマシンが最終的にすべてのアップデート(少なくとものすべての古います。

すべてこの思うことを検討すべき正確に うごく稀に お申し込接続していることは間違いありませんのためのデータがすべて完全に同期化されます。場の極端なが頻繁する必要がある外部サーバへの移動データとともに、サービスも提供いたします 通常のメール 当然こうした問題をクリアできる.いので気をつけなければいけない場合は使用しないコンピュータはオンラインきものです。不要な場合アクセスについて、特定のメールアカウント、開始から各アプリのリストの複数のメールアドレスのアドレスをチェックされているときのオプションの更新の申請にはもっとアドレスを指定されたアドレスに失敗します。コンピュータ通信を利用した全ての徳を意味します。を使用できる

に軽量化にも注 番駅 は、事前にインターネットへの情報の更新の問題もなせる場合(放送大部分の世界が)になる。

他のヒント

の非同期メッセージングパラダイムをパブリッシュ/サブスクライブを参照してください。

例implementaionはのApache ActiveMQの

  

はApache ActiveMQのは、高速であり、多くのクロス言語のクライアントをサポートし、プロトコル、完全にJMS 1.1およびJ2EE 1.4をサポートしながら、エンタープライズ統合パターンと多くの高度な機能を使用するように簡単に付属しています。

私はあなたが数年前に記述されているものに似たアプリを設計しました。私は、各デスクトップに走った「広告サーバー」を設計し、それがネットワーク上で実行されている他のプログラムへのステータスのブロードキャストするためにUDPを使用します。さて、これはあなたがこのアプリケーションを実行する予定の方法に応じ、問題のそれ自身のセットを持っている...しかし、ここでは、迅速かつそれが働いたかの汚いです...

私のセットアップデータベース・サーバをハッシュすることによって選ばれた、データベース、アプリケーションが接続されたポート上で「リスナー」。これは、誰も私は、からの放送を得た私がいたのと同じデータベースを使用していた、とデスクトップ(設計要件)上で実行するアプリケーションの複数のインスタンスを許可されていることを確認します。

特定のイベントを放送するでしょう。

次に、Iセットアップさまざまな「BroadcastMessage()」機能。私もプログラムがそのイベントが入って来たとき、レジストラに通知するでしょう、そのイベントのために、リスナーを登録し、それを渡してきた、カスタムペイロードデータと、私のAPIカスタムイベントを作成する機能を使用して許可され、開発者としてこれまで行って、それに付属しているデータ。

アプリが起動したときに

は、例えば、それは「私がここにいる」というメッセージをブロードキャストだろう、と誰のリスニングは、メッセージを食べて、それを無視するか、それに答えることができます。任意のクライアントが配信されなければならなかった、さらにデータ更新のためのTCP接続を介してそれに接続することができるように、「私がここにいる」で、それは、実行中のアプリケーションのIPアドレスが含まれています。

それはこれらの放送は、他のすべての実行中のインスタンスで見ることが要件ではありませんでしたので、

私は、UDPを選択しました。それは何よりも利便性のより多くのだった...あなたが同じ画面上にあったが、誰かがDBにレコードを追加した場合は、新しいレコードはちょうどあなたのデスクトップ上に表示される「」でしょう。

これはまた、彼らはアプリを実行していた間、管理者がユーザーの権限を変更した場合、ユーザーが終了し、アプリを再入力する必要はありませんでした、更新がすぐそこに受信、および処理された、とすることを便利になりましたユーザーは、彼らが必要なものを行うことができます。

それはあなたのサンプルコードが必要な場合は、私もそれを提供することができます...ちょうどこれらの種類のメッセージをリッスンスレッドでリスナーのセットアップには本当に簡単ですが、それはC ++であり、およびWindows用に設計されたが、それは使用しています生WSOCK32.LIBは、それはかなり簡単に任意のUNIXプラットフォームに介して転送する必要がありますので。 (ちょうど私がその多くを使用して、DWORDをtypedefをする必要があります...)。

私は何回かは、ネットワーク管理にある。この問題を解決してきました。あなたの基本的な懸念は、あなたのアプリが互いを発見しないか、「ディスカバリー」のようです。

正直なところ、最も簡単な方法は、あなたのIPアドレス&マスク(ほとんどのあるクラスCを)知っていると、そのクラスCの各マシンに接続しようとすることです。

あなたはクラスCにデフォルト設定された場合は、

、それはそれはちょうど約常にほとんどのネットワークのために働くだろうことを意味します。あなたは、あなたがに接続するために特定のIPアドレスのいずれかに追加オーバーライド、または追加のサブネットを許可することができます。

クラスCを発見するために、あなたは自分のIPアドレスを把握、その後、192.168.2のすべてを反復(のは192.168.2.77を言わせて)。(1-254)を、それぞれへの接続をオープンしようとします。

私は(あなたがそのように一度にすべてのデバイスにpingを実行し、3秒以内に良い結果を持つことができる。私は数百のスレッドで5分のように、クラスBのネットワークを発見!)複数のスレッドでそれを行って、またはあなたましたただシングルスレッドで次の1から行くことができます - しかし、あなたはそれを行う場合は必ずあなたのタイムアウトがそうでなければ、それは永遠にかかります(その1/2秒または)本当に低であることを確認してください - でも1/2秒でそれがしますラウンドを作るために分を取るます。

あなたはおそらくも常に新しい仲間を探し、低速でバックグラウンドで実行されているディスカバリスレッドを残したい。

そして迅速に起動するために、あなたの「既知の正常な」IPアドレスをキャッシュします。

これは難しい問題ではありませんが、それはどちらかの些細ではありません。ほんの少し取材を行うことを期待しています。

また、あなたはおそらく、外部サブネットをスキャンし、新しいIP /マスクを追加できるようにしたいです。あなたは、インターネット上のデバイスに連絡したい場合は、この周りだけの方法は(かつて一台のPCがネットを発見したが、あなたがしたい場合、それは他のすべてのアドレスを送信することができ、そしてそれは本当に大きな、本当に速い成長できた!)はありません。

あなたは、これは完全にP2Pになりたいか、あなたがディレクトリであること、より多くの何かを行うための中央サーバーを持つことを計画しているか?

通信セキュリティを強化するため、SSLは問題ないはずです。それはあなたが使用しているものだと、Javaは、非常に簡単な方法でこれらをサポートしています。ここでのSSLのための参照するですJava 6の

[OK]をクリックします。約束どおり、ここで私は自分のアプリケーションからリッピングサンプルコードの一部です。これは、コンパイルして実行することが予想されていない、これは<全角>私はがそれをやった方法の例です。あなたは、あなたが完全に異なるしなければならないことがあります。プラス、これはWindowsのために書かれたもの、そしてあなたがコードで表示されますように、サーバースレッドとメインアプリケーション間の間でデータを送信するために、Windowsのメッセージを使用していますが、すべてはあなたがそれを使用する予定の方法に依存していること。私はあなたが参照するために、より興味深い部分の一部を残しています。

セキュリティ部分については、まあ、私はあなたがその部分を処理することができます把握します。それはいくつかのよく暗号を知って使用して、ワイヤーの上に行く前に、つまり、データを暗号化するだけの単純な問題ですので、私は、私はそれのいずれかを含める必要がありましたとは思いませんでした。たとえば、私はパケットヘッダを構築方法を見ることができ、その後、通常は別の構造で構成されたペイロードがあります。だから、その構造を暗号化データとして送信した後、もう一方の端にそれを解読し、適切な構造にコピーします。

// Some defines that you may see in the code, all of which are user defined...
#define ADVERTISE_SERVER           0x12345678 // Some unique ID for your advertisement server
#define ACTIVITY_NONE              0x00000000
#define ACTIVITY_LOGON             0x00000001
#define ACTIVITY_LOGOFF            0x00000002
#define ACTIVITY_RUNNING           0x00000004
#define ACTIVITY_IDLE              0x00000005
#define ACTIVITY_SPECIFIC          0x00000006


enum Advertisements {
   ADVERTISE_SHUTDOWN,
   ADVERTISE_MESSAGE,
   ADVERTISE_DEBUG,
   ADVERTISE_OVERLAPPED,
   ADVERTISE_BROADCAST_IDENTITY,
   ADVERTISE_IDENTITY,
   ADVERTISE_PARAMETER_CHANGE
};

struct TAdvertiseServerPacket {
   UINT     uiAdvertisePacketType;
   DWORD    dwPacketLength;
   bool     bRequestReply;
   UINT     uiReplyType;
   bool     bOverlappedResult;
   int      iPacketId;
   bool     bBroadcast;
   char     GuidHash[35];
   BYTE     PacketData[1024];
};

struct TAdvertiseIdentity {
   TCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
   char  szUserName[LEN_APPL_USERNAME + 1];
   char  szDatabase[MAX_PATH];
   char  szConfiguration[MAX_PATH];
   char  szVersion[16];
   long  nUserId;
   char  szApplication[MAX_PATH];
   char  szActivity[33];
   UINT  uiStartupIndc;
};

struct TAdvertiseMessage {
   char              MessageFrom[LEN_APPL_USERNAME + 1];
   char              MessageText[512];
};

struct TAdvertiseItemUpdate {
   NMHDR             pNMHDR;
   long              nItemId;
   long              nItemTypeId;
   char              szItemName[LEN_ITEM_NAME + 1];
   bool              bState;
};

struct TAdvertiseItemUpdateEx {
   NMHDR             pNMHDR;
   long              nItemId;
   bool              bState;
   bool              bBroadcast;
   DWORD             dwDataSize;
   void              *lpBuffer;
};

struct TOverlappedAdvertisement {
   int               iPacketId;
   BYTE              Data[1020];
};

DWORD WINAPI CAdvertiseServer::Go(void* tptr)
{
   CAdvertiseServer *pThis = (CAdvertiseServer*)tptr;

   /* Used and reused for Overlapped results, */
   DWORD BufferSize       = 0;
   BYTE *OverlappedBuffer = NULL;
   bool bOverlapped       = false;
   int  iOverlappedId     = 0;
   DWORD BufferPosition   = 0;
   DWORD BytesRecieved    = 0;
   TAdvertiseItemUpdateEx *itemex = NULL;
   UINT uiPacketNumber    = 0;

   bool Debug = false;
#ifdef _DEBUG
   Debug = true;
#endif
   {
      DWORD dwDebug = 0;
      dwDebug = GetParameter(ADVERTISE_SERVER_DEBUG); // GetParameter is part of the main program used to store running config values.
      if(dwDebug > 0)
      {
         Debug = true;
      }
   }
   WSAData wsaData;
   WSAStartup(MAKEWORD(1,1), &wsaData);
   ServerSocket = socket(PF_INET, SOCK_DGRAM, 0);
   if(ServerSocket == INVALID_SOCKET)
   {
      CLogging Log("Client.log");
      ServerSocket = NULL;
      Log.Log("Could not create server advertisement socket: %d", GetLastError());
      return -1;
   }
   sockaddr_in sin;
   ZeroMemory(&sin, sizeof(sin));
   sin.sin_family = AF_INET;
   sin.sin_port = htons(Port);
   sin.sin_addr.s_addr = INADDR_ANY;
   if(bind(ServerSocket, (sockaddr *)&sin, sizeof(sin)) != 0)
   {
      CLogging Log("Client.log");
      Log.Log("Could not bind server advertisement socket on port: %d Error: %d", Port, GetLastError());
      DWORD dwPort = 0;
      dwPort = GetParameter(ADVERTISE_SERVER_PORT); // Again, used to set the port number, if one could not be figured out.
      if(dwPort > 0)
      {
         return -1;
      }
      Port = 36221;
      sin.sin_port = htons(Port);
      if(bind(ServerSocket, (sockaddr *)&sin, sizeof(sin)) != 0)
      {
         CLogging Log("Client.log");
         Log.Log("Could not bind server advertisement socket on port: %d Error: %d Could not start AdvertiseServer after two attempts.  Server failed.", Port, GetLastError());
         return -1;
      }
   }

   SECURITY_ATTRIBUTES sa;
   sa.bInheritHandle = TRUE;
   sa.lpSecurityDescriptor = NULL;
   sa.nLength = sizeof(SECURITY_ATTRIBUTES);
   HANDLE mutex = CreateMutex(NULL, FALSE, "Client.Mutex"); // Used to keep and eye on the main program, if it shuts down, or dies, we need to die.
   while (1)
   {
      TAdvertiseServerPacket ap;
      sockaddr_in sin;
      int fromlen = sizeof(sin);
      fd_set fds;
      FD_ZERO(&fds);
      FD_SET(ServerSocket, &fds);
      timeval tv;
      tv.tv_sec = 15;
      tv.tv_usec = 0;
      int err = select(0, &fds, NULL, NULL, &tv);
      if(err == SOCKET_ERROR)
      {
         CLogging Log("Client.log");
         Log.Log("Advertise: Winsock error: %d", WSAGetLastError());
         Beep(800, 100);
         break;
      }
      if(err == 0)
      {
         if(WaitForSingleObject(mutex, 0) != WAIT_OBJECT_0)
         {
            continue; // Main app is still running
         }
         else
         {
            Beep(800, 100); // Main app has died, so exit our listen thread.
            break;
         }
      }

      int r = recvfrom(ServerSocket, (char *)&ap, sizeof(ap), 0, (sockaddr *)&sin, &fromlen);

      if(r != sizeof(TAdvertiseServerPacket))
      {
         continue;
      }
      switch(ap.uiAdvertisePacketType)
      {
         // This is where you respond to all your various broadcasts, etc.
         case ADVERTISE_BROADCAST_IDENTITY:
         {
            // None of this code is important, however you do it, is up to you.
            CDataAccess db(CDataAccess::DA_NONE);
            TCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
            ZeroMemory(ComputerName, sizeof(ComputerName));
            DWORD len = MAX_COMPUTERNAME_LENGTH;
            GetComputerName(ComputerName, &len);
            if(pThis->szActivity) {
               CAdvertiseServer::AdvertiseIdentity(ComputerName, CDataAccess::GetLoggedInUserName(), CDataAccess::DatabaseConfiguration(), CDataAccess::DatabaseConfiguration(), ACTIVITY_SPECIFIC, pThis->szActivity, false);
            } else {
               CAdvertiseServer::AdvertiseIdentity(ComputerName, CDataAccess::GetLoggedInUserName(), CDataAccess::DatabaseConfiguration(), CDataAccess::DatabaseConfiguration(), ACTIVITY_RUNNING, NULL, false);
            }
         }
         case ADVERTISE_IDENTITY:
         {
            TAdvertiseIdentity ident;
            memcpy((void*)&ident, (void*)ap.PacketData, ap.dwPacketLength);
            Listener::iterator theIterator;
            theIterator = pThis->m_Listeners.find(ap.uiAdvertisePacketType);
            if(theIterator == pThis->m_Listeners.end())
            {

               //We got an Identity Broadcast, but we're not listening for them.
               continue;
            }
            {
               itemex = new TAdvertiseItemUpdateEx;
               ZeroMemory(itemex, sizeof(TAdvertiseItemUpdateEx));
               memcpy((void*)&ident, ap.PacketData, ap.dwPacketLength);
               itemex->pNMHDR.code     = (*theIterator).first;
               itemex->pNMHDR.hwndFrom = (*theIterator).second;
               itemex->pNMHDR.idFrom   = ADVERTISE_SERVER;
               itemex->dwDataSize      = sizeof(TAdvertiseIdentity);
               itemex->lpBuffer        = (void*)&ident;
               SendMessage((*theIterator).second, WM_NOTIFY, 0, (LPARAM)itemex);
               delete itemex;
            }
         }
         case ADVERTISE_SHUTDOWN:
         {
            TCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
            ZeroMemory(ComputerName, sizeof(ComputerName));
            DWORD len = MAX_COMPUTERNAME_LENGTH;
            GetComputerName(ComputerName, &len);
            CString guid;
            guid.Format("%s%s", CDataAccess::DatabaseConfiguration(), ComputerName);
            if(stricmp(ap.GuidHash, CDataAccess::HashPassword(guid)) == 0)
            {
               return 1;
            }
         }
         case ADVERTISE_MESSAGE:
         {
            TAdvertiseMessage msg;
            memcpy((void*)&msg, (void*)ap.PacketData, ap.dwPacketLength);
            CString msgtext;
            msgtext.Format("Message from: %s\r\n\r\n%s", msg.MessageFrom, msg.MessageText);
            ::MessageBox(NULL, msgtext, "Broadcast Message", MB_ICONINFORMATION | MB_SYSTEMMODAL);
            break;
         }
         case ADVERTISE_OVERLAPPED:
         {
            // I left this code in here, as it's a good example of how you can send large amounts of data over a UDP socket, should you need to do it.
            BufferPosition = (1020 * ((ap.uiReplyType - 1) - 1));
            if(BufferPosition > BufferSize) {
               BufferPosition -= 1020;
            }
            TOverlappedAdvertisement item;
            ZeroMemory(&item, sizeof(TOverlappedAdvertisement));
            memcpy((void*)&item, (void*)ap.PacketData, ap.dwPacketLength);
            if(item.iPacketId == iOverlappedId)
            {
               DWORD ToCopy = (sizeof(item.Data) > (BufferSize - BytesRecieved) ? BufferSize - BytesRecieved : sizeof(item.Data));
               memcpy((void*)&OverlappedBuffer[BufferPosition], (void*)item.Data, ToCopy);
               BytesRecieved += ToCopy;
               if(BytesRecieved < BufferSize)
               {
                  continue;
               }
            }
         }
         default:
         {
            // What do we do if we get an advertisement we don't know about?
            Listener::iterator theIterator;
            if(bOverlapped == false)
            {
               theIterator = pThis->m_Listeners.find(ap.uiAdvertisePacketType);
               if(theIterator == pThis->m_Listeners.end())
               {
                  continue;
               }
            }

            // Or it could be a data packet
            TCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
            ZeroMemory(ComputerName, sizeof(ComputerName));
            DWORD len = MAX_COMPUTERNAME_LENGTH;
            GetComputerName(ComputerName, &len);
            CString guid;
            guid.Format("%s%s", CDataAccess::DatabaseConfiguration(), ComputerName);
            bool FromUs = stricmp(ap.GuidHash, CDataAccess::HashPassword(guid)) == 0;
            if(((FromUs && Debug) || !FromUs) || ap.bBroadcast)
            {
               if(ap.bOverlappedResult)
               {
                  if(ap.uiReplyType == 1)
                  {
                     itemex = new TAdvertiseItemUpdateEx;
                     ZeroMemory(itemex, sizeof(TAdvertiseItemUpdateEx));
                     memcpy(itemex, ap.PacketData, ap.dwPacketLength);
                     OverlappedBuffer = (BYTE*)malloc(itemex->dwDataSize);
                     BufferSize = itemex->dwDataSize;
                     ZeroMemory(OverlappedBuffer, itemex->dwDataSize);
                     bOverlapped = true;
                     iOverlappedId = ap.iPacketId;
                     uiPacketNumber = ap.uiReplyType;
                  }
                  continue;
               }
               if(bOverlapped)
               {
                  itemex->pNMHDR.code     = (*theIterator).first;
                  itemex->pNMHDR.hwndFrom = (*theIterator).second;
                  itemex->pNMHDR.idFrom   = ADVERTISE_SERVER;
                  itemex->dwDataSize      = BufferSize;
                  itemex->lpBuffer        = (void*)OverlappedBuffer;
                  SendMessage((*theIterator).second, WM_NOTIFY, 0, (LPARAM)itemex);
                  delete itemex;
                  free(OverlappedBuffer);
                  BufferSize       = 0;
                  OverlappedBuffer = NULL;
                  bOverlapped      = false;
                  iOverlappedId    = 0;
                  BufferPosition   = 0;
                  BytesRecieved    = 0;
                  itemex           = NULL;
                  uiPacketNumber   = 0;
                  break;
               }
               TAdvertiseItemUpdate *item = new TAdvertiseItemUpdate;
               ZeroMemory(item, sizeof(TAdvertiseItemUpdate));
               memcpy(item, ap.PacketData, ap.dwPacketLength);

               item->pNMHDR.code     = (*theIterator).first;
               item->pNMHDR.hwndFrom = (*theIterator).second;
               item->pNMHDR.idFrom   = ADVERTISE_SERVER;
               SendMessage((*theIterator).second, WM_NOTIFY, 0, (LPARAM)item);
               delete item;
            }
            break;
         }
      }
   }
   try {
      ResetEvent(ServerMutex);
      CloseHandle(pThis->ServerMutex);
      closesocket(ServerSocket);
      return 0;
   }
   catch(...) {
      closesocket(ServerSocket);
      return -2;
   }
}

// Here's a couple of the helper functions that do the sending...
bool CAdvertiseServer::SendAdvertisement(TAdvertiseServerPacket packet)
{
   TCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
   ZeroMemory(ComputerName, sizeof(ComputerName));
   DWORD len = MAX_COMPUTERNAME_LENGTH;
   GetComputerName(ComputerName, &len);
   CString guid;
   guid.Format("%s%s", CDataAccess::DatabaseConfiguration(), ComputerName);

   strcpy(packet.GuidHash, CDataAccess::HashPassword(guid));

   bool bRetval = false;
   SOCKET s = socket(PF_INET, SOCK_DGRAM, 0);
   if(s != INVALID_SOCKET)
   {
      BOOL tru = TRUE;
      setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&tru, sizeof(tru));
      sockaddr_in sin;
      ZeroMemory(&sin, sizeof(sin));
      sin.sin_family = PF_INET;
      sin.sin_port = htons(Port);
      sin.sin_addr.s_addr = INADDR_BROADCAST;
      if(sendto(s, (char *)&packet, sizeof(packet), 0, (sockaddr *)&sin, sizeof(sin)) > 0)
      {
         bRetval = true;
         if(packet.bRequestReply)
         {
           // Here is where your work comes in, in setting up a reply, or making a TCP connection back to the other client.
         }
      }
      closesocket(s);
   }
   return bRetval;
}

bool CAdvertiseServer::Advertise(UINT uiAdvertisement, long nItemId, bool bState, void *lpBuffer, DWORD dwDataSize, bool bBroadcast)
{
   TAdvertiseServerPacket packet;
   ZeroMemory(&packet, sizeof(packet));
   TAdvertiseItemUpdateEx   item;
   ZeroMemory(&item, sizeof(item));

   UINT packetnum = 1;
   packet.bOverlappedResult = true;
   packet.bRequestReply = false;
   packet.uiAdvertisePacketType = uiAdvertisement;
   packet.dwPacketLength = sizeof(item);
   packet.uiReplyType = packetnum;
   packet.bBroadcast = bBroadcast;
   item.nItemId = nItemId;
   item.bState  = bState;
   item.dwDataSize = dwDataSize;
   memcpy((void*)packet.PacketData, (void*)&item, sizeof(item));
   packet.iPacketId = GetTickCount();
   if(SendAdvertisement(packet))
   {
      BYTE *TempBuf = new BYTE[dwDataSize];
      memcpy(TempBuf, lpBuffer, dwDataSize);

      DWORD pos = 0;
      DWORD BytesLeft = dwDataSize;
      while(BytesLeft)
      {
         TOverlappedAdvertisement item;
         packet.uiAdvertisePacketType = ADVERTISE_OVERLAPPED;
         packet.bOverlappedResult = BytesLeft > 1020;
         item.iPacketId = packet.iPacketId;
         memcpy((void*)item.Data, (void*)&TempBuf[pos], (BytesLeft >= 1020 ? 1020 : BytesLeft));
         memcpy((void*)packet.PacketData, (void*)&item, sizeof(item));
         packet.dwPacketLength = sizeof(item);
         packet.uiReplyType++;
         if(SendAdvertisement(packet))
         {
            if(BytesLeft >= 1020)
            {
               BytesLeft -= 1020;
               pos += 1020;
            }
            else
            {
               BytesLeft = 0;
            }
         }
      }
      delete TempBuf;
   }
   return true;
}

void CAdvertiseServer::Shutdown()
{
   TAdvertiseServerPacket packet;
   packet.uiAdvertisePacketType = ADVERTISE_SHUTDOWN;
   SendAdvertisement(packet);
}

[OK]を - そうMQとオーバーキルのようなものの音のそのタイプ。

あなたのアプリの私の理解でます:

同一ネットワーク上の複数のマシン上で実行されている

デスクトップアプリ - 独自のデータベースを持って互いを発見する必要があります。

なぜます:

1)UDPブロードキャスト/「同一ネットワーク上の他のマシンを見つける」ために定期的に聞く - Javaでの例:<のhref = "http://java.sun.com/docs/books/tutorial/networking /datagrams/index.html」のrel = "nofollowをnoreferrer"> http://java.sun.com/docs/books/tutorial/networking/datagrams/index.html の

2)発見した後、実際の通信にSSLソケットを使用します。
http://stilius.net の/java/java_ssl.php ....
<のhref = "http://www.exampledepot.com/egs/javax.net.ssl/Client.html" のrel = "nofollowをnoreferrer" > http://www.exampledepot.com/egs/javax.net.ssl/Client.html の

ご採用を検討Bittorrent型のセットアップ?

の通信を主体に使用すべきかな基盤を構築します。すべての必要なものは二つのノードについて知ってそれを築いているからである。使ってい MonoTorrent にはプライベート(100ノード)データネットワークでは、RSSフィードを発表しどのファイルが必要な場(修正版のWordpress)のようSSHトンネル.いて、中央サーバを管理するネットワークも容易に生ずっ100ノード。を使用しダイナミックDNSサービスは、最初のノードの生存を設定するとともに独自のトラッカーとしてバックアップが私のサーバーなどがあります。

利用できるXMLファイルとしてメール、または改変、送信、Bittorrentネットワークデータを送信するパケットに直接アプリです。私の考えをお探しでBittorrent.最初のノードに火をつけるよう再生のダイナミックDNSエントリダイナミックdns はかなり使いやすい API 場合はそれほど広くはありませんが積極的ホストである、という点があります。が下振れ...思い入同期の問題がラッカーの火災ができない場合がありまTTLウィンドウ)

あへの参照 SSHトンネル あんこの楽しい図等がある。SSHトンネリングな最も効率的な方法が現在も使われている代替することprogramaticallyラップ通信にSSLます。

ピックアップしました。考えているような入り乱れにより、希望すすることなく、少し開くだけで自分自身を指すのは正しい方向を向いている。PS...のための完全な移植性の高い解決法がこのJavaいます。ネット(動モノ..していまAppleTVs走るモノでも).そのOSでも柔軟性の一部動作します。

あなたが分散キャッシュまたはオフラインDB機能を必要とするように

サウンド - あなたの言語に応じて、(のJava / C#/ ...)あなたに開いているさまざまなオプションがあります...

アマゾンとマイクロソフトの両方に接続でき、協調アプリケーションの任意の数の間のランデブーポイントとして使用することができますキューを開催しています。 Amazonのは無料、商用ではありません。 Microsoftのには現在無料ですが、いつまでも、そうであることを保証されません。 それはまさにあなたが直面している問題を解決します。接続しているクライアントのためのパブ/サブモデルを提供しています。

私はここで何かを見逃しているかもしれないが、私は、プログラミング言語の選択を見ることができませんでした。 Windowsベースの環境では、.NET Frameworkを使用して、最良の選択は、あなたが簡単な構成で、セキュリティ/堅牢性を追加することができますWCFを使用することです。 あなたが指向ネットでないWindowsベースのコンピュータとのソリューションをしたい場合は、私はこれらの基準に基づき建設された通信フレームワークであるMSMQを、使用してになります。

WCFでのP2Pについての良い記事がここにあります http://msdn.microsoft.com/en-us/magazine/cc188685。 ASPXする。 これは、コードを提供しますが、.Net3、WCF、Vistaおよび

の上を想定しています
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top