调用linux socket函数sendto:错误,不允许操作

时间:2014-11-28 06:45:00

标签: java android linux sockets android-ndk

环境:
PC sys:windows xp
JDK:1.6
NDK:采用Android NDK,R9B
编译环境:MinGW

Descrpiton: 我正在开发一个sip端点应用程序,该应用程序基于Android设备中的开源sip堆栈" doubango"套接字函数使用NDK调用,但不是直接使用JAVA调用。正常使用时,没问题。然后使用某些软件清洁设备的内存,或者手动停止服务,并使其异常退出。似乎它在没有调用函数关闭(套接字)的情况下停止。下次我使用时,会抛出错误调用套接字函数:sendto(),errno = 1表示"操作不允许"。
我已添加" uses-permission android:name =" android.permission.INTERNET""
有人可以帮我一把吗?

PS:我在没有ROOT权限的设备中进行测试,这个问题就会发生。但我测试了一个具有ROOT权限的设备,它并没有发生。这有关系吗?


工作完成。我在Java层中犯了一些错误。我在Sip堆栈中设置的一些参数是错误的。



以下是代码段:

int tnet_sockfd_sendto(tnet_fd_t fd, const struct sockaddr *to, const void* buf,     tsk_size_t size)
{
tsk_size_t sent = 0;
int ret = -1;

if(fd == TNET_INVALID_FD){
    TSK_DEBUG_ERROR("Using invalid FD to send data.");
    goto bail;
}
if(!buf || !size){
    TSK_DEBUG_ERROR("Using invalid BUFFER.");
    ret = -2;
    goto bail;
}

while(sent < size){
    int try_guard = 10;
#if TNET_UNDER_WINDOWS
    WSABUF wsaBuffer;
    DWORD numberOfBytesSent = 0;
    wsaBuffer.buf = ((CHAR*)buf) + sent;
    wsaBuffer.len = (size - sent);
try_again:
    ret = WSASendTo(fd, &wsaBuffer, 1, &numberOfBytesSent, 0, to, tnet_get_sockaddr_size(to), 0, 0); // returns zero if succeed
    if(ret == 0){
        ret = numberOfBytesSent;
    }
#else
try_again:
    ret = sendto(fd, (((const uint8_t*)buf)+sent), (size-sent), 0, to, tnet_get_sockaddr_size(to)); // returns number of sent bytes if succeed
#endif
    if(ret <= 0){
        if(tnet_geterrno() == TNET_ERROR_WOULDBLOCK){
            TSK_DEBUG_INFO("SendUdp() - WouldBlock. Retrying...");
            if(try_guard--){
                tsk_thread_sleep(10);
                goto try_again;
            }
        }
        else{
                                ***/* Just throw error here*/***
            TSK_DEBUG_INFO("errno: %d",tnet_geterrno());
            TNET_PRINT_LAST_ERROR("sendto() failed");

        }
        goto bail;
    }
    else{
        sent += ret;
    }
}

bail:
return (size == sent) ? sent : ret;
}


#define tnet_soccket(family, type, protocol) socket((family), (type), (protocol))


tnet_socket_t* tnet_socket_create_2(const char* host, tnet_port_t port_,tnet_socket_type_t type, tsk_bool_t nonblocking, tsk_bool_t bindsocket)
{
tnet_socket_t *sock;

if((sock = tsk_object_new(tnet_socket_def_t))){
    int status;
    tsk_istr_t port;
    struct addrinfo *result = tsk_null;
    struct addrinfo *ptr = tsk_null;
    struct addrinfo hints;
    tnet_host_t local_hostname;

    sock->port = port_;
    tsk_itoa(sock->port, &port);
    sock->type = type;

    memset(local_hostname, 0, sizeof(local_hostname));

    /* Get the local host name */
    if(host != TNET_SOCKET_HOST_ANY && !tsk_strempty(host)){
        memcpy(local_hostname, host, tsk_strlen(host)>sizeof(local_hostname)-1 ? sizeof(local_hostname)-1 : tsk_strlen(host));
    }
    else{
        if(TNET_SOCKET_TYPE_IS_IPV6(sock->type)){
            memcpy(local_hostname, "::", 2);
        }
        else{
            memcpy(local_hostname, "0.0.0.0", 7);
        }
    }


    TSK_DEBUG_INFO("local_hostname: %s",local_hostname);

    /* hints address info structure */
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = TNET_SOCKET_TYPE_IS_IPV46(sock->type) ? AF_UNSPEC : (TNET_SOCKET_TYPE_IS_IPV6(sock->type) ? AF_INET6 : AF_INET);
    hints.ai_socktype = TNET_SOCKET_TYPE_IS_STREAM(sock->type) ? SOCK_STREAM : SOCK_DGRAM;
    hints.ai_protocol = TNET_SOCKET_TYPE_IS_STREAM(sock->type) ? IPPROTO_TCP : IPPROTO_UDP;
    hints.ai_flags = AI_PASSIVE
#if !TNET_UNDER_WINDOWS || _WIN32_WINNT>=0x600
        | AI_ADDRCONFIG
#endif
        ;

    /* Performs getaddrinfo */
    if((status = tnet_getaddrinfo(local_hostname, port, &hints, &result))){
        TNET_PRINT_LAST_ERROR("tnet_getaddrinfo(family=%d, hostname=%s and port=%s) failed: [%s]", 
            hints.ai_family, local_hostname, port, tnet_gai_strerror(status));
        goto bail;
    }

    /* Find our address. */
    for(ptr = result; ptr; ptr = ptr->ai_next){
        sock->fd = tnet_soccket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
        if(ptr->ai_family != AF_INET6 && ptr->ai_family != AF_INET){
            continue;
        }
        /* To avoid "Address already in use" error
        * Check issue 368 (https://code.google.com/p/doubango/issues/detail?id=368) to understand why it's not used for UDP/DTLS.
        */
        //
        if (TNET_SOCKET_TYPE_IS_STREAM(sock->type)) {
            TSK_DEBUG_INFO("Socket Type: Stream");
            if ((status = tnet_sockfd_reuseaddr(sock->fd, 1))) {
                // do not break...continue
            }
        }


        if(bindsocket){
            /* Bind the socket */

            if((status = bind(sock->fd, ptr->ai_addr, ptr->ai_addrlen))){
                TNET_PRINT_LAST_ERROR("bind to [%s:%s]have failed", local_hostname, port);
                tnet_socket_close(sock);
                continue;
            }

            /* Get local IP string. */
            if((status = tnet_get_ip_n_port(sock->fd , tsk_true/*local*/, &sock->ip, &sock->port))) /* % */
            //if((status = tnet_getnameinfo(ptr->ai_addr, ptr->ai_addrlen, sock->ip, sizeof(sock->ip), 0, 0, NI_NUMERICHOST)))
            {
                TNET_PRINT_LAST_ERROR("Failed to get local IP and port.");
                tnet_socket_close(sock);
                continue;
            }
        }

        /* sets the real socket type (if ipv46) */
        if(ptr->ai_family == AF_INET6) {
            TNET_SOCKET_TYPE_SET_IPV6Only(sock->type);
        }
        else{
            TNET_SOCKET_TYPE_SET_IPV4Only(sock->type);
        }
        break;
    }

    /* Check socket validity. */
    if(!TNET_SOCKET_IS_VALID(sock)) {
        TNET_PRINT_LAST_ERROR("Invalid socket.");
        goto bail;
    }

#if TNET_UNDER_IPHONE || TNET_UNDER_IPHONE_SIMULATOR
    /* disable SIGPIPE signal */
    {
        int yes = 1;
        if(setsockopt(sock->fd, SOL_SOCKET, SO_NOSIGPIPE, (char*)&yes, sizeof(int))){
            TNET_PRINT_LAST_ERROR("setsockopt(SO_NOSIGPIPE) have failed.");
        }
    }
#endif /* TNET_UNDER_IPHONE */

    /* Sets the socket to nonblocking mode */
    if(nonblocking){
        if((status = tnet_sockfd_set_nonblocking(sock->fd))){
            goto bail;
        }
    }

bail:
    /* Free addrinfo */
    tnet_freeaddrinfo(result);

    /* Close socket if failed. */
    if(status){
        if(TNET_SOCKET_IS_VALID(sock)){
            tnet_socket_close(sock);
        }
        return tsk_null;
    }
}

return sock;
}


int tnet_sockfd_reuseaddr(tnet_fd_t fd, int reuseAddr)
{
if (fd != TNET_INVALID_FD) {
    int ret;
    #if defined(SOLARIS)
        static const char yes = '1';
        static const char no = '0';
    #else
        static const int yes = 1;
        static const int no = 0;
    #endif
        if ((ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char*)(reuseAddr ? &yes : &no), sizeof(int)))) {
            TNET_PRINT_LAST_ERROR("setsockopt(SO_REUSEADDR, fd=%d) have failed", fd);
            return ret;
        }
//      #if defined(SO_REUSEPORT)
        if ((ret = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char*)(reuseAddr ? &yes : &no), sizeof(int)))) {
            TNET_PRINT_LAST_ERROR("setsockopt(SO_REUSEPORT, fd=%d) have failed", fd);
            return ret;
        }
//      #endif
    return 0;
}
return -1;
}


#define tnet_sockfd_set_nonblocking(fd) tnet_sockfd_set_mode(fd, 1)
int tnet_sockfd_set_mode(tnet_fd_t fd, int nonBlocking)
{
if(fd != TNET_INVALID_FD)
{
#if TNET_UNDER_WINDOWS
ULONG mode = nonBlocking;
if(ioctlsocket(fd, FIONBIO, &mode))
//if(WSAIoctl(fd, FIONBIO, &nonblocking, sizeof(nonblocking), NULL, 0, NULL, NULL, NULL) == SOCKET_ERROR)
{
    TNET_PRINT_LAST_ERROR("ioctlsocket(FIONBIO) have failed.");
    return -1;
}
#else
int flags;
if((flags = fcntl(fd, F_GETFL, 0)) < 0) { 
    TNET_PRINT_LAST_ERROR("fcntl(F_GETFL) have failed.");
    return -1;
} 
if(fcntl(fd, F_SETFL, flags | (nonBlocking ? O_NONBLOCK : ~O_NONBLOCK)) < 0){ 
    TNET_PRINT_LAST_ERROR("fcntl(O_NONBLOCK/O_NONBLOCK) have failed.");
    return -1;
} 
#endif

// int on = 1;
// ioctl(fd, FIONBIO, (char *)&on);

}
return 0;
}


0 个答案:

没有答案