CocoSocket分享
cocos2dx 3.1都出了,但依然沒有發現與它原生的SOCKET支持,于是,這幾天在家,手工擼了一個。
目前版本對IOS,ANDROID,WINDOWS支持良好。且為異步SOCKET,不需要再開任何線程。
特點
1、異步SOCKET,無需任何線程
2、只有一個頭文件,使用方便
3、支持IOS,ANDROID,WINDOWS
下載連接 v0.0.1
示例:
//自定義消息處理器 class CSessionHandler :public ISocketHandler { virtual void onConnected() { printf("connected.\n"); } virtual void onConnectFailed() { printf("connect failed.\n"); } virtual void onMessage(const char* msg, int len) { printf("%s",msg); } virtual void onDisconnected() { printf("disconnected.\n"); } }; //使用 CSessionHandler oo; CocoSocket cSocket; cSocket.setHandler(&oo); cSocket.create(AF_INET, SOCK_STREAM, 0); cSocket.connect("192.168.1.7", 8643);
各位可以嘗試使用,若有什么坑,可以回復此貼,或者來信告訴我,一起完善,謝謝。 GMAIL:boyuegame
遇上的問題
由于對socket和select不是太熟悉,那先說說遇上的坑吧。
1、WINDOWS上的返回錯誤碼與IOS,ANDROID不一樣。
這才是最坑爹的,因此,不得不重新定義。 好在每一種返回,表示OK的就那一個兩個,其它都無視,還算好搞。
2、非阻塞的SOCKET在進行connect的時候,成功與失敗的判定問題
POSIX有一個規則,就是當connect成功的時候, 可寫,當connect失敗的時候,即可讀又可寫。
但這并不能作為判定標準,因為當SOCKET連接成功,服務器有數據過來的時候,也會變成即可讀,又可寫。
WINDOWS下并沒有遵守這個規則, 通過MSDN的查看,才發現,在WDINWOS上,當connect連接成功時,可寫,當連接失敗時,是通過fd_set* error返回的。 因此,在WINDOWS上就很容易處理。
那在LINUX和MAC下如何呢。 LINUX和UNIX的 MAN PAGE上介紹是通過getsocketopt的返回值才判定。 還有一種是嘗試再次connect,看是否返回值為EISCONN來判定。 網上有一篇貼子說這在LINUX下不靠譜,所以我就沒有嘗試。
轉而,使用另一個規則。
不管是connect成功還是失敗,總是可寫的。所以,當可寫的時候,我們嘗試從緩沖區里read 0字節,如果返回值為0,則表示連接成功,如果返回-1,那肯定就是連接失敗了。 這個在IOS和ANDROID下工作良好。
3、網上很多人說 recv(fd,buf,buf_len,MSG_NOSIGNAL)可以防止SIGPIPE信號的產生
這簡直就是放屁,看看最后一個參數的意思吧。
4、如何正確忽略SIGPIPE信號
struct sigaction sa; sa.sa_handler = SIG_IGN; sa.sa_flags = 0; if (sigemptyset(&sa.sa_mask) == -1 || sigaction(SIGPIPE, &sa, 0) == -1) { perror("failed to ignore SIGPIPE; sigaction"); exit(EXIT_FAILURE); } }
由于在WINDOWS上,要進行SOCKET SETUP,在ANDOIRD,IOS上,要進行SIGPIPE忽略,所以我弄了一個SocketPrepare類,當有SOCKET初始化的時候,構造一個靜態對象,比較方便。 避免CPP依賴,所有東西,都放到了.H里。
5、ANDROID
ANDROID上面,檢測是否連接成功,還是得用getsockopt,但連接失敗的檢查不是太容易。
新增的超時檢查,可以用于任意平臺的連接失敗檢查。畢竟游戲里面,都是會做連接超時的。
由于我希望外面使用干凈,所以,我使用了cocos的shcedule來調度事件檢測,這樣就隱藏了Reactor 外面使用只需要這樣。
//實現自己的消息Handler class MyHandler:public ISocketHandler { //實現方法 } //如何使用 //實例化一個CocoSocket CocoSocket socket; //實例化一個Handler MyHandler handler; //綁定 socket.setHandler(&handler); //分配Socket系統資源 socket.create(...); //連接目標地址 socket.connect(....);
結術語
無。
文章列表