さて、私はちょうど当分の間フレームワークを選んでいるので、私はまだ実際にコードを持っていませんが、まだ少しですどのように私はこのことについて行きたいと思うのか、困惑した:。winsock、メッセージ指向のネットワーキング、およびrecvからバッファをタイプキャスト
サーバー側では、各インスタンスにソケットと各接続を識別するさまざまな情報があるクラスを作成したいと考えています。各オブジェクトにはデータを受け取るためのスレッドがあります。私はそのほとんどを実装する方法を理解していますが、サーバーとクライアントの間で実際にデータをやりとりするように私の混乱が始まります。私は、特定のケース(例えば、CONNECT_MSG、DISCONNECT_MSG、POSTTEXT_MSG、など)のための異なるメッセージ構造体の束をしたいと思うし、私がしなければならないのは、その構造体でchar *ポイントを持っているし、 () 関数。
しかし、私はそれを考えると、その時点で少し複雑になります。これらの異なるメッセージタイプのいずれかが送信される可能性があり、受信側では、受信バッファをどのようにキャストすべきか分かりません。私が望んでいたのは、各接続オブジェクトのスレッドでは、メッセージを含むパケットを受信するまでブロックし、サーバによって管理される単一のキューオブジェクトにダンプします(mutexesは貪欲を防ぎます)。次にサーバ接続オブジェクトとは独立したFIFO順序で各メッセージを処理します。
まだ何も書かれていませんが、セットアップを説明するために少し書いてみましょう。
#define CONNECT 1000
struct GENERIC_MESSAGE
{
int id;
}
struct CONNECT_MESSAGE : public GENERIC_MESSAGE
{
m_username;
}
void Connection::Thread()
{
while(1)
{
char buffer[MAX_BUFFER_SIZE]; // some constant(probably 2048)
recv(m_socket, buffer, MAX_BUFFER_SIZE, 0);
MESSAGE_GENERIC * msg = reinterpret_cast<MESSAGE_GENERIC *> (buffer);
server->queueMessage(msg);
}
}
void Server::QueueMessage(MESSAGE_GENERIC * msg)
{
messageQueue.push(msg);
}
void Server::Thread()
{
while(1)
{
if(!messageQueue.empty())
ProcessMessages();
else
Sleep(1);
}
}
void Server::ProcessMessages()
{
for(int i = 0; i < messageQueue.size(); i++)
{
switch(messageQueue.front()->id)
{
case CONNECT:
{
// the part i REALLY don't like
CONNECT_MESSAGE * msg = static_cast<CONNECT_MESSAGE *>(messageQueue.front());
// do the rest of the processing on connect
break;
}
// other cases for the other message types
}
messageQueue.pop();
}
}
今、あなたがこれまでフォローしてきたのであれば、これはどのようにSTUPIDと壊れやすいのかを実感します。それは基本クラスにキャストし、そのポインタをキューに渡して、ポインタが他のスレッドから依然として有効であると仮定し、残りのバッファが派生クラスの残りのポインタの後に常に存在するかどうかを仮定します後でキャスティングで有効になりますが、これを行う正しい方法をまだ見つけていません。私は、この仕事をするか、まったく異なるメッセージングデザインを作るかのいずれの提案に対しても広くオープンしています。
私は実際にこれのほとんどをアイロンで出しました。すべてのメッセージはメッセージタイプのIDで構成され、残りはIDの内容に応じて可変になります。どちらか一方が最初に送信され、他方が同時に受信できます。メッセージが認識されるように、それはtcp/ipになります。メッセージの境界がどういう意味なのかはわかりません。 Connectメッセージは切断メッセージが受信されるまでアクティブに保たれ、クライアント側またはサーバー側は切断メッセージを送信し、それに従ってメッセージを処理します。現在、唯一のハングアップは、送信されたメッセージとのデータタイプの可変性です。 – FatalCatharsis
各メッセージペイロードをバイトレベルで定義します。受信者がメッセージ間の境界をどのように見つけるかを定義します(1つのメッセージが終了し、次のメッセージが開始される場所)。 –
これは実際に私がキャスティングやメッセージを避けようとしていることです。以前はいくつかのwinsockプログラミングを行っていましたが、バイトレベルで精巧な構文解析スキームが今私がしようとしているものほど不安定でした。 1つのchar *バッファを複数のオブジェクトに分割しようとすると、常にヒットしてしまいました。今私は1つのメッセージオブジェクトをバッファごとにしか持たないように制限しようとしています。これは型とデータを1つの準拠オブジェクトに配置することができますが、どちらも動作していないようです。 – FatalCatharsis