Libevent は素晴らしく、今のところ気に入っています。ただし、エコー サーバーでは、書き込みは 2 回目の書き込みでのみソケットに送信されます。私の執筆は別のスレッド、つまりデータベースと通信し、最小限のデータ マッサージを行うポンプ スレッドからのものです。
書き込み用のコールバックを設定して、これを確認しました。
bufferevent_setcb( GetBufferEvent(), DataAvailable, DataWritten, HandleSocketError, this );
bufferevent_flush( m_bufferEvent, EV_READ|EV_WRITE, BEV_NORMAL ) を呼び出しても効果がないようです。
どこかで吹き飛ばした場合に備えて、ここにセットアップがあります。ヘルプを得るために、コード ベースのオーバーヘッドを大幅に簡素化しました。これには、ソケットの初期化、スレッドの初期化などが含まれます。これはマルチスレッド アプリであるため、問題が発生する可能性があります。私はこれから始めます:
m_LibEventInstance = event_base_new();
evthread_use_windows_threads();
m_listener = evconnlistener_new_bind( m_LibEventInstance,
OnAccept,
this,
LEV_OPT_CLOSE_ON_FREE | LEV_OPT_CLOSE_ON_EXEC | LEV_OPT_REUSEABLE,
-1,// no maximum number of backlog connections
(struct sockaddr*)&ListenAddress, socketSize );
if (!m_listener) {
perror("Couldn't create listener");
return false;
}
evconnlistener_set_error_cb( m_listener, OnSystemError );
私の知る限り、これはサンプルからのコピーと貼り付けなので、うまくいくはずです。私の OnAccept は次のことを行います。
void OnAccept( evconnlistener* listenerObj, evutil_socket_t newConnectionId, sockaddr* ClientAddr, int socklen, void* context )
{
// We got a new connection! Set up a bufferevent for it.
struct event_base* base = evconnlistener_get_base( listenerObj );
struct bufferevent* bufferEvent = bufferevent_socket_new( base, newConnectionId, BEV_OPT_CLOSE_ON_FREE );
bufferevent_setcb( GetBufferEvent(), DataAvailable, DataWritten,
HandleSocketError, this );
// We have to enable it before our callbacks will be called.
bufferevent_enable( GetBufferEvent(), EV_READ | EV_WRITE );
DisableNagle( m_connectionId );
}
ここでは、入ってくるデータに応答し、後で処理するためにバッファに格納するだけです。これはマルチスレッド アプリケーションなので、後でデータを処理したり、メッセージを送信したり、クライアントに応答を返したりします。
void DataAvailable( struct bufferevent* bufferEventObj, void* arg )
{
const U32 MaxBufferSize = 8192;
MyObj* This = (MyObj*) arg;
U8 data[ MaxBufferSize ];
size_t numBytesreceived;
/* Read 8k at a time and send it to all connected clients. */
while( 1 )
{
numBytesreceived = bufferevent_read( bufferEventObj, data, sizeof( data ) );
if( numBytesreceived <= 0 ) // nothing to send
{
break;
}
if( This )
{
This->OnDataReceived( data, numBytesreceived );
}
}
}
最後に、データを検索したら、バッファにパッケージ化し、スレッド化されたタイムスライスでこれを行います。
bufferevent_write( m_bufferEvent, buffer, bufferOffset );
初めて送信することはありません。送信するには、データでいっぱいの 2 番目のバッファーを送信する必要があります。
この振る舞いは私を殺し、私はそれに多くの時間を費やしました. 何か案は?
//------------------------------------------------ -------
私は最終的にあきらめて、代わりにこのハックを使用しました... libevent がソケットに書き込んでいない理由を説明するのに十分な情報がありませんでした。これはうまくいきます。
int result = send( m_connectionId, (const char* )buffer, bufferOffset, 0 );