libupnp下的ios多线程套接字挂起在send()上

libupnp下的ios多线程套接字挂起在send()上,ios,multithreading,sockets,freeze,dlna,Ios,Multithreading,Sockets,Freeze,Dlna,在我的iOS应用程序(DLNA media player)中,我看到了一个我不明白的问题……我希望有人能对此有所了解 我的应用程序是在C++中的目标C中构建的,其中一部分是LIUPBNP。查看下面的代码时,将为记录设置编译标志SO_NOSIGPIPE 从广义上讲,该应用程序运行得相当好,至少在iPod和我的iPad上是如此,两者都运行iOS 6。它可以做各种各样的媒体播放器 编辑:我对iPhone4上的操作系统的看法是错误的,我以为它是6.x,但就其价值而言,它是5.1.1。 当我开始在iPho

在我的iOS应用程序(DLNA media player)中,我看到了一个我不明白的问题……我希望有人能对此有所了解

我的应用程序是在C++中的目标C中构建的,其中一部分是LIUPBNP。查看下面的代码时,将为记录设置编译标志SO_NOSIGPIPE

从广义上讲,该应用程序运行得相当好,至少在iPod和我的iPad上是如此,两者都运行iOS 6。它可以做各种各样的媒体播放器

编辑:我对iPhone4上的操作系统的看法是错误的,我以为它是6.x,但就其价值而言,它是5.1.1。

当我开始在iPhone4(iOS 5.1.1)和iPhone5(iOS 6)上测试我的应用程序时,问题就出现了……这告诉我,我的代码中有一个计时问题

用户选择要在远程数字媒体接收器(DMR)上播放/显示的媒体项

我的代码调用libupnp,创建soap命令来实现这一点。然后它调用http_RequestAndResponse(),它创建套接字,将()连接到主机,并调用http_SendMessage,它调用sock_read_write(我稍后将在消息中包含此函数)来发送我生成的请求(在DMR上播放媒体的POST命令)。然后,使用相同的套接字调用http_RecvMessage(再次调用sock_read_write()以接收字节)。此时,它被称为select(),等待DMR响应Play命令

在另一个线程上,libupnp的web服务器收到一个请求,请求我们刚才说要播放的媒体文件的位。因此,在另一个线程上,我用字节调用http_SendMessage来响应请求,调用sock_read_write()将字节写入客户端

sock\u read\u write中的send()挂起。它不仅挂起libupnp,而且意味着在任何线程的套接字上都没有更多的通信

这些挂起的套接字似乎不会超时、死亡或以其他方式终止。当然,我正在构建的是一个DLNA媒体播放器,很多关于世界状况的命令和报告都是通过这些插座发送的,所以我的应用程序实际上变成了一个僵尸:它会响应鼠标点击之类的,但你不能做任何有意义的事情

我已尝试将send()设为非阻塞。我尝试调用fcntll(sock、F_SETFL、O_NONBLOCK)将其设置为非阻塞,并在调用send()之前返回(如果由于任何原因失败)

我尝试在send()上使用标志send(),比如MSG_NOWAIT(对iOS没有影响)

这似乎是一个时间问题。在iPad和iPod上,我可以播放音乐直到奶牛回家。在iPhone4和iPhone5上,我会挂起

有什么建议吗?(如果您告诉我哪些建议明确回答了这个问题,我们将欣然接受对RTFM、阅读手册页、阅读书籍等的建议…)

噢,sock_read_write()的代码(来自libupnp 1.6.18):

/*!
*\brief接收或发送数据。还返回接收或接收所需的时间
*发送数据。
*
*\返回
*\li\c numBytes-成功时,接收或发送的字节数或
*\li\c UPNP\u E\u TIMEDOUT-超时
*\li\c UPNP\u E\u套接字\u错误-套接字调用错误
*/
静态int-sock\u读写(
/*![in]套接字信息对象*/
SOCKINFO*信息,
/*![out]缓冲区,用于获取数据或从中发送数据*/
字符*缓冲区,
/*![in]缓冲区的大小*/
大小,
/*![in]超时值*/
int*timeoutSecs,
/*![in]指定读或写选项的布尔值*/
(面包)
{
int-retCode;
fd_集readSet;
fd_集写集;
结构timeval超时;
长麻木细胞;
时间\u t开始\u时间=时间(空);
SOCKET sockfd=info->SOCKET;
发送的长字节数=0;
大小\u t字节\u左=(大小\u t)0;
写下的数字;
如果(*timeoutSecs<0)
返回UPNP_E_TIMEDOUT;
FD_零(读取集和读取集);
FD_ZERO(写入集和写入集);
如果(面包)
FD_集(sockfd和readSet);
其他的
FD_集(sockfd和writeSet);
timeout.tv_sec=*timeoutSecs;
timeout.tv_usec=0;
while(TRUE){
如果(*timeoutSecs==0)
retCode=select(sockfd+1,&readSet,&writeSet,
空,空);
其他的
retCode=select(sockfd+1,&readSet,&writeSet,
空,超时(&T);
如果(retCode==0)
返回UPNP_E_TIMEDOUT;
如果(retCode==-1){
如果(errno==EINTR)
继续;
返回UPNP_E_套接字_错误;
}否则
/*读或写*/
打破
}
#ifdef SO_NOSIGPIPE
{
int old;
int set=1;
socklen_t olen=尺寸(旧);
getsockopt(sockfd、SOL_SOCKET、SO_NOSIGPIPE、old和olen);
setsockopt(sockfd、SOL_SOCKET、SO_NOSIGPIPE和set、sizeof(set));
#恩迪夫
如果(面包){
/*读取数据*/
numBytes=(长)recv(sockfd、buffer、bufsize、MSG_NOSIGNAL);
}否则{
字节_left=bufsize;
发送的字节数=0;
而(字节\u左!=(大小\u t)0){
/*写数据*/
num_write=send(sockfd,
缓冲区+已发送字节,剩余字节,
MSG_DONTROUTE | MSG_NOSIGNAL);
如果(写入的数量==-1){
#ifdef SO_NOSIGPIPE
setsockopt(插座FD、SOL_插座、,
索乌·诺西普和奥尔德·奥伦);
#恩迪夫
返回(int)写入的num_;
}
字节\u left-=(大小\u t)写入的数量;
发送的字节数+=写入的字节数;
}
numBytes=发送的字节数;
}
#ifdef SO_NOSIGPIPE
setsockopt(插座FD、SOL_插座、SO_NOSIGPIPE和old、olen);
}
#恩迪夫
如果(单位<0)
返回UPNP_E_套接字_错误;
/*减去用于阅读/写作的时间*/
如果(*timeoutSecs!=0)
*timeoutSecs-=(int)(时间(NULL)-开始时间);
返回(int)个字节;
}
/*!
 * \brief Receives or sends data. Also returns the time taken to receive or
 * send data.
 *
 * \return
 *  \li \c numBytes - On Success, no of bytes received or sent or
 *  \li \c UPNP_E_TIMEDOUT - Timeout
 *  \li \c UPNP_E_SOCKET_ERROR - Error on socket calls
 */
static int sock_read_write(
    /*! [in] Socket Information Object. */
    SOCKINFO *info,
    /*! [out] Buffer to get data to or send data from. */
    char *buffer,
    /*! [in] Size of the buffer. */
    size_t bufsize,
    /*! [in] timeout value. */
    int *timeoutSecs,
    /*! [in] Boolean value specifying read or write option. */
    int bRead)
{
    int retCode;
    fd_set readSet;
    fd_set writeSet;
    struct timeval timeout;
    long numBytes;
    time_t start_time = time(NULL);
    SOCKET sockfd = info->socket;
    long bytes_sent = 0;
    size_t byte_left = (size_t)0;
    ssize_t num_written;

    if (*timeoutSecs < 0)
        return UPNP_E_TIMEDOUT;
    FD_ZERO(&readSet);
    FD_ZERO(&writeSet);
    if (bRead)
        FD_SET(sockfd, &readSet);
    else
        FD_SET(sockfd, &writeSet);
    timeout.tv_sec = *timeoutSecs;
    timeout.tv_usec = 0;
    while (TRUE) {
        if (*timeoutSecs == 0)
            retCode = select(sockfd + 1, &readSet, &writeSet,
                NULL, NULL);
        else
            retCode = select(sockfd + 1, &readSet, &writeSet,
                NULL, &timeout);
        if (retCode == 0)
            return UPNP_E_TIMEDOUT;
        if (retCode == -1) {
            if (errno == EINTR)
                continue;
            return UPNP_E_SOCKET_ERROR;
        } else
            /* read or write. */
            break;
    }
#ifdef SO_NOSIGPIPE
    {
        int old;
        int set = 1;
        socklen_t olen = sizeof(old);
        getsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &old, &olen);
        setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof(set));
#endif
        if (bRead) {
            /* read data. */
            numBytes = (long)recv(sockfd, buffer, bufsize, MSG_NOSIGNAL);
        } else {
            byte_left = bufsize;
            bytes_sent = 0;
            while (byte_left != (size_t)0) {
                /* write data. */
                num_written = send(sockfd,
                    buffer + bytes_sent, byte_left,
                    MSG_DONTROUTE | MSG_NOSIGNAL);
                if (num_written == -1) {
#ifdef SO_NOSIGPIPE
                    setsockopt(sockfd, SOL_SOCKET,
                        SO_NOSIGPIPE, &old, olen);
#endif
                    return (int)num_written;
                }
                byte_left -= (size_t)num_written;
                bytes_sent += num_written;
            }
            numBytes = bytes_sent;
        }
#ifdef SO_NOSIGPIPE
        setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &old, olen);
    }
#endif
    if (numBytes < 0)
        return UPNP_E_SOCKET_ERROR;
    /* subtract time used for reading/writing. */
    if (*timeoutSecs != 0)
        *timeoutSecs -= (int)(time(NULL) - start_time);

    return (int)numBytes;
}
void sighandler(int signum)
{
    NSLog(@"Caught signal %d",signum);
}

int main(int argc, char *argv[])
{
    signal(SIGPIPE,sighandler);

    ...