1. 程式人生 > >[網路開發]ZeroMQ初體驗

[網路開發]ZeroMQ初體驗

群裡最近在說網路庫的東西,群主推薦說可以看看ØMQ,說非常精簡,而且支援多種語言,非常高效率,於是下載來看看。

ØMQ官網 www.zeromq.org

Guide還沒看完,大概先看了下,覺得很精簡,而且寫的非常清裡面包含了多種設計模式的應用,建議大家有時間看看。

所有網路互動所使用的API實際上是Berkeley套接字(BSD) 。這個源自1980年代早期的協議是TCP/IP協議的最原始實現。而且可以說,在當今各作業系統中,它是受到最廣泛支援的API,也是這些作業系統的核 心元件之一。人們對BSD套接字的瞭解較多的是點對點的連線。點對點連線需要顯式地建立連線、銷燬連線、選擇協議(TCP/UDP)和處理錯誤等。一旦你 解決了以上所有問題,你就進入應用協議層(如HTTP)的世界了,這裡需要的是組幀、快取和處理邏輯等。換言之,編寫高效能網路協議的應用程式一點兒也不 複雜。

如果我們能對各種套接字型別、連線處理、幀、甚至路由的底層細節進行抽象,這不是件很好的事情嗎?這正是ZeroMQ(ØMQ/ZMQ)網路庫的由來:“它提供一些跨多種傳輸協議(如程序內通訊、IPC、TCP和廣播)的套接字供你使用。你可使用多種方式實現N對N的套接字連線,譬如:扇出、釋出訂閱、任務分發以及請求響應。”

ØMQ是網路棧中新的一層,它是個可伸縮層,分散在分散式系統間。因此,它可支援任意大的應用程式。ØMQ不是簡單的點對點互動,相反,它定義了分散式系統的全域性拓撲。ØMQ應用程式沒有鎖,可並行執行。此外,它可在多個執行緒、核心和主機盒之間彈性伸縮。

  • ZeroMQ互動是面向訊息的。它將人們每天為應用程式周而復始地進行的例行訊息處理封裝起來。這意味著如果當客戶端套接字傳送一條150KB大小的訊息時,服務端套接字無需顯式處理任何快取(buffer)或組幀,即能接接收到一條完整而相同的訊息。
  • ZeroMQ套接字與傳輸協議無關:對於任何協議,只有單一且統一的傳送訊息和接收訊息API。預設情況下支援程序內通訊、IPC、廣播和TCP。此外,協議間切換非常簡單,僅需更改連線字串的字首即可。
  • ZeroMQ套接字能感知路由和網路拓撲。因為我們不再需要顯示地管理點對點的連線狀態——在上面我們已經看到,所有這些都已經由 ZeroMQ庫封裝好——所以單個ZeroMQ套接字可以繫結兩個獨立的埠並監聽他們的入站請求訊息;也可使用一個API呼叫向兩個獨立的套接字傳送數 據。
  • TCP:ZeroMQ基於訊息,訊息模式,而非位元組流。
  • XMPP:ZeroMQ更簡單、快速、更底層。Jabber可建在ØMQ之上。
  • AMQP:完成相同的工作,ZeroMQ要快100倍,而且不需要代理(規範更簡潔——少278頁)
  • IPC:ZeroMQ可以跨多個主機盒,而非單臺機器。
  • CORBA:ZeroMQ不會將複雜到恐怖的訊息格式強加於你。
  • RPC:ZeroMQ完全是非同步的,你可以隨時增加/刪除參與者。
  • RFC 1149:ZeroMQ比它快多了!
  • 29west LBM:ZeroMQ是自由軟體!
  • IBM低延遲:ZeroMQ是自由軟體!
  • Tibco:仍然是自由軟體!

看了第一部分的guide,試了試最簡單的hello world,覺得非常好用,完全可以用來做聊天軟體或者遊戲的訊息核心。

下載ØMQ最新版本,3.0.2Beta版本,zeromq-3.0.2\builds\msvc路徑下有一個msvc.sln檔案,這個是VS2008的解決方案檔案,我用的是VS2010,轉換完後編譯,我自己按照Debug和Release分開編譯生成的,方便工程使用,特別強調下,編譯完最外層資料夾Lib中會生成一個libzmq.dll的檔案,使用該庫編譯的程式必須得有該連結庫才可以執行。(不知道為什麼官網要這樣做,直接變成Lib檔案,然後使用就可以了,還得轉兩次,如果需要Lib檔案的同學可以自己將他編譯為Lib檔案。)

在自己工程中新增標頭檔案和庫檔案路徑,然後開始編寫測試程式碼。

建立兩個工程一個為ZMQServer 一個為ZMQTest

程式碼片段如下:
[cpp]
// hello world server
#include "zmq.h"
#include "zmq.hpp"
#include <iostream>

int _tmain(int argc, _TCHAR* argv[])
{
std::cout << "———Test Client Start… (C) www.cppfans.org———" <<std::endl;
std::cout << "———————Author:eliteYang———————" <<std::endl;

void* context = zmq_init( 1 );
void* responder = zmq_socket( context, ZMQ_REP );
zmq_bind( responder, "tcp://*:5555" );

while ( true )
{
zmq_msg_t msg;
zmq_msg_init( &msg );
zmq_recv( responder, &msg, 0 );
std::cout << "Recv Hello world! from Client" << std::endl;
zmq_msg_close( &msg );

Sleep( 100 );
}
zmq_close (responder);
zmq_term (context);
system( "Pause" );
return 0;
}
[/cpp]

[cpp]
// hello world client
#include "zmq.h"
#include "zmq.hpp"
#include <stdio.h>
#include <iostream>
#include <string>

int _tmain(int argc, _TCHAR* argv[])
{
std::cout << "———Test Client Start… (C) www.cppfans.org———" <<std::endl;
std::cout << "———————Author:eliteYang———————" <<std::endl;

void* context = zmq_init( 1 );
void* responder = zmq_socket( context, ZMQ_REQ );
int nRet = zmq_connect( responder, "tcp://localhost:5555" );
if ( nRet == 0 )
{ std::cout << "—————-Client Connect Server OK——————" <<std::endl; }

for ( int i = 0; i < 10; ++i )
{
zmq_msg_t msg;
zmq_msg_init_size( &msg, 32 );
memcpy( zmq_msg_data( &msg ), "Hello world!", 15);
zmq_send( responder, &msg, 0 );
zmq_msg_close( &msg );
std::cout << "Send Msg" << i << "Times" << std::endl;
}

zmq_close (responder);
zmq_term (context);
system( "Pause" );
return 0;
}
[/cpp]

這樣一個簡單的網路程式就寫好了,無需你對網路協議和網路程式設計多熟悉就可以完成,非常簡單實用,大家有興趣可以看下。後面我會對現有的幾個網路庫慢慢研究的(ZMQ RakNet IOCP LibEvent ICE等),希望大家繼續關注!