文章出處

CocoSocket分享


cocos2dx 3.1都出了,但依然沒有發現與它原生的SOCKET支持,于是,這幾天在家,手工擼了一個。

目前版本對IOS,ANDROID,WINDOWS支持良好。且為異步SOCKET,不需要再開任何線程。

特點
1、異步SOCKET,無需任何線程
2、只有一個頭文件,使用方便
3、支持IOS,ANDROID,WINDOWS

下載連接 v0.0.1

下載連接 v0.0.2

 

示例:

//自定義消息處理器
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(....);

 

結術語


無。


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()