Ios CFSocket数据回调

Ios CFSocket数据回调,ios,iphone,sockets,cfsocket,Ios,Iphone,Sockets,Cfsocket,在iPhone应用程序中,我从现有的本机UDP套接字创建了一个CFSocket对象,并在套接字接收到一些数据时设置一个数据回调。然后我将其添加到我的主程序循环中: //Set socket descriptor field cbData.s = udpSocket.getSocketDescriptor(); CFSocketContext udpSocketContext; memset(&udpSocketContext, 0, sizeof(udp

在iPhone应用程序中,我从现有的本机UDP套接字创建了一个CFSocket对象,并在套接字接收到一些数据时设置一个数据回调。然后我将其添加到我的主程序循环中:

    //Set socket descriptor field
    cbData.s = udpSocket.getSocketDescriptor();

    CFSocketContext udpSocketContext;
    memset(&udpSocketContext, 0, sizeof(udpSocketContext));
    udpSocketContext.info = &cbData;

    cbData.socketRef = CFSocketCreateWithNative(NULL, cbData.s, kCFSocketDataCallBack, &getSocketDataCallBack, &udpSocketContext);
    cbData.runLoopSourceRef = CFSocketCreateRunLoopSource( NULL, cbData.socketRef, 0);
    CFRunLoopAddSource(CFRunLoopGetMain(), cbData.runLoopSourceRef, kCFRunLoopCommonModes);
我每5毫秒从一个单独的Mac服务器应用程序通过WiFi发送1024字节的数据报,并在iPhone上的getSocketDataCallBack例程中接收它们

我希望getSocketDataCallBack每5毫秒调用一次(以匹配从Mac发送的数据报的周期),这在大多数情况下都会发生。但是,这些调用通常会延迟10秒或100毫秒。此后,我会得到一个快速的回调序列(毫秒的分数),以检索在延迟期间堆积的多个数据报

由于iOS显然保留了延迟的数据报

  • 有没有办法从系统中获取所有延迟的数据报 一次而不是一次又一次地调用getSocketDataCallBack 接二连三地

    [我确实查询回调ala中有多少字节可用:

           CFDataRef dataRef = (CFDataRef)data;
           numBytesReceived = CFDataGetLength(dataRef);
    
    但“numBytesReceived”始终报告为1024。]

  • 或者,有没有办法改进/减少套接字回调 通过其他方式的时间可变性

我使用套接字回调与UNIX套接字进行进程间通信(实际上是线程间通信)。我们使用套接字的方式与TCP/UDP相同

下面的代码是用c/obj-c编写的,并使用posix线程。将其转换为Swift/NSThread应该不难

注意,下面的程序作为服务器端工作,这意味着该程序将创建客户端连接到的套接字。一旦客户机连接到套接字,系统将自动接受连接并进行分配 另一个要读/写的文件描述符。套接字回调反映了这两个阶段的操作。最初,我们创建套接字,然后添加为运行循环源,这样当客户端尝试连接时,系统可以回调调用。系统接受,然后分配并告知回拨 要与客户端一起读/写的文件描述符。然后,我们从读/写fd创建另一个运行循环源,并添加到运行循环。当rx/tx数据就绪时,调用第二次回调

主线程:

主线程创建UNIX套接字和工作线程。套接字fd作为工作线程的参数传递

#import <stdio.h>
#import <string.h>
#import <stdlib.h>
#import <unistd.h>
#import <pthread.h>
#import <sys/socket.h>
#import <sys/un.h>
#import <sys/stat.h>
#import <sys/types.h>
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
int setup(const char *ipcNode) {
    int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (sockfd == -1) {
        return -1;
    }
    struct sockaddr_un sa = {0};
    sa.sun_len = sizeof(sa);
    sa.sun_family = AF_UNIX;
    strcpy(sa.sun_path, ipcNode);
    remove(sa.sun_path);
    if (bind(sockfd, (struct sockaddr*)&sa, sizeof(struct sockaddr_un)) == -1) {
        close(sockfd);
        return -1;
    }
    // start up worker thread
    pthread_attr_t at;
    pthread_attr_init(&at);
    pthread_attr_setdetachstate(&at, PTHREAD_CREATE_DETACHED);
    pthread_t th;
    pthread_create(&th, &at, workerThread, (void *)(long)(sockfd));
    return 1;
}
如果您在客户端工作,事情会变得容易一些。您将通过connect()调用获得一个读/写fd。然后使用fd创建CFSockeRef并添加到run循环

希望这有帮助

编辑:如何使用POSIX select()等待。在工作线程上使用POSIX select()等待比套接字回调更简单。如果您在客户端,则:

int sockfd = socket(...);
bind(sockfd, ...)
connect(sockfd, ...);
while (1) {
    int nfds = sockfd+1;
    fd_set rfds;
    FD_ZERO(&rfds);
    FD_SET(sockfd, &rfds);
    int retval = select(nfds, &rfds, NULL, NULL, NULL);
    if (retval == -1)  break;
    if (retval > 0) {
        uint8_t rxdata[1024];
        size_t nr = read(sockfd, rxdata, 1024);
        if (!nr) {
            // socket closed.
            break;
        }
        // do your rx process here
    }
}

在工作线程上运行上述代码。

这可能不是真的,但如果要添加到主线程的运行循环,请尝试创建另一个线程,然后在该线程中运行运行循环,看看是否仍有偶尔的延迟。请多加一条注释。可能开销最小的“回调”方案应该是等待w/posix select()。如果上面的方法不起作用,我会在另一个线程中尝试select()。谢谢,贝西奥。我正在考虑创建另一个线程。我的回调函数如下:
void getSocketDataCallBack(CFSocketRef CFSocketRef,CFSocketCallBackType cbType,CFDataRef address,const void*data,void*info)
。如何使用NSThread实现这一点?在上面的相关问题中,对CFRunLoopGetCurrent()的调用是否会返回与CFRunLoopAddSource()调用中的CFRunLoopGetMain()相同的结果?我在想,在这种情况下,他们会返回相同的东西,但我想了解它多一点。谢谢由于评论时间太长,我在下面的回答中写道。非常感谢,贝希奥!当我在客户端对整个设置进行编程时,我能够删除中间步骤(您的
socketDataCallback
),并从
workerThread
设置我的客户端回调版本,我有更多的测试要做,但回调时间的可变性似乎更小。有时,系统仍然会延迟套接字读取回调,但我可能无法完全缓解这个问题,因为我正在尝试在非实时IOSO中进行实时音频播放。因此,在测试之后,回调的时间变化仍然比我希望的要大。我尝试按如下方式设置新线程的策略和优先级,但没有效果:
pthread\u attr\u setinheritsched(&at,pthread\u EXPLICIT\u SCHED);pthread_attr_setschedpolicy(&at,SCHED_FIFO)然后:
int策略;结构sched_param param;pthread_getschedparam(th、策略和参数);param.sched_优先级=32//默认值=31 pthread_setschedparam(th、policy和param)还有其他想法吗?用POSIX select()调用代替工作线程中的套接字回调来等待怎么样?如果增加工作线程的调度优先级并使用select()调用等待,我认为这是我们能做的最好的事情。我相信使用select()等待比套接字回调开销小。
#import <stdio.h>
#import <string.h>
#import <stdlib.h>
#import <unistd.h>
#import <pthread.h>
#import <sys/socket.h>
#import <sys/un.h>
#import <sys/stat.h>
#import <sys/types.h>
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
int setup(const char *ipcNode) {
    int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (sockfd == -1) {
        return -1;
    }
    struct sockaddr_un sa = {0};
    sa.sun_len = sizeof(sa);
    sa.sun_family = AF_UNIX;
    strcpy(sa.sun_path, ipcNode);
    remove(sa.sun_path);
    if (bind(sockfd, (struct sockaddr*)&sa, sizeof(struct sockaddr_un)) == -1) {
        close(sockfd);
        return -1;
    }
    // start up worker thread
    pthread_attr_t at;
    pthread_attr_init(&at);
    pthread_attr_setdetachstate(&at, PTHREAD_CREATE_DETACHED);
    pthread_t th;
    pthread_create(&th, &at, workerThread, (void *)(long)(sockfd));
    return 1;
}