Android版本客户端调用close socket后recv不返回问题求教

客户端用socket+protobuf的通信方式,封装了一个GameSocket客户端连接类,其中接受后台数据的处理是单独的一个线程

connect处理时初始化receive线程

_recv_thread = new std::thread(std::bind(&GameSocket::process_receive, this));

处理函数如下,为了避免cpu忙等和空转,socket/recv均采用阻塞方式。

void GameSocket::process_receive(void)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)

if (_recv_thread) {
    JavaVM *vm;
    JNIEnv *env;
    vm = JniHelper::getJavaVM();


    JavaVMAttachArgs thread_args;


    thread_args.name = "ReceiveThread";
    thread_args.version = JNI_VERSION_1_4;
    thread_args.group = NULL;


    vm->AttachCurrentThread(&env, &thread_args);
}

#endif

log("init receive process thread");
while (true) {
    unsigned char  buffer;
    log("###before receive invoke");


    int recv_size = ::recv(_socket, buffer, BUFFER_SIZE, 0);

    log("###receive thread size:%d", recv_size);



}

注意代码中红色部分,正常情况下服务器的数据发送(send),客户端recv的数据接收也是一切正常(IOS & ANDROID).
但在我需要客户端主动关闭socket时,按道理正常情况下在socket关闭时,recv调用应该返回, recv_size == 0。
socket关闭包括服务器关闭 或者客户端主动close(_socket) 或者 网络原因的断链。

但实际测试用下来这套逻辑在IOS下运行一切正常,但在android环境我测试下发只有服务器主动close,例如关闭服务器进程,客户端recv会返回0。但客户端上其他线程close(_socket),或者wifi信号掉线等原因下
recv始终不返回,一直处于挂死状态。

因为之前移植android版本时,就查到jni环境下的多线程要加上类似下面这段处理才能正常,我初步猜测这是否和jni下的多线程机制有什么关系?

但由于本人对android环境底层了解不足,这个问题google后也没明确答案,希望得到各位大拿的指点,多谢多谢!

if (_recv_thread) {
JavaVM *vm;
JNIEnv *env;
vm = JniHelper::getJavaVM();

    JavaVMAttachArgs thread_args;


    thread_args.name = "ReceiveThread";
    thread_args.version = JNI_VERSION_1_4;
    thread_args.group = NULL;


    vm->AttachCurrentThread(&env, &thread_args);
}

#endif

你先shutdown,然后在close,否则close延迟生效,祝好运。:14:

有道理,以前写服务端只有父子进程关闭socket句柄才使用SHUT_RDWR, android搞不好进程管理也有点类似的窍门,我来试试看,多谢多谢~!

这是我踩过的坑,要是可以的话你可以分享给别人。