【问题标题】:Simple posix server can't set UILabel from loop简单的 posix 服务器无法从循环中设置 UILabel
【发布时间】:2015-11-27 05:55:22
【问题描述】:

我正在尝试向我的 iOS 应用程序添加一个 posix 套接字服务器,该服务器将允许 TCP 连接并将缓冲区写入 UILabel 对象作为测试。

我可以让它工作......一次。然后它完成并关闭连接。好的,很容易解决,我会把它放在一个循环中。现在,每当我将完全相同的代码放入循环中时,由于某种原因它不会更新 UILabel。我实际上并不需要它来更新 UILabel,这只是一个测试以确保服务器正常工作.......但这让我很紧张。我把它从while循环中取出,它可以工作,我把它放回去,除了UILabel setText调用之外的所有东西都可以工作。

另外,还有两个小问题:在客户端断开连接后我无法弄清楚如何退出循环,并且我不确定退出时如何正确关闭端口,我必须不断更改端口编号,因为它无法绑定。

-(void)viewDidLoad

    NSThread *listenThread = [[NSThread alloc] initWithTarget:self selector:@selector(createPosixServer) object:nil];
    [listenThread start];

-(void)createPosixServer

    //declarations
    int sockfd, newsockfd, portno;
    socklen_t clilen;
    char buffer[256];
    struct sockaddr_in serv_addr, cli_addr;
    int n;
    NSString *nsbuffer;

    //bind and listen on socket
    sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sockfd < 0) {
        NSLog(@"Error while calling socket()");
    }
    bzero((char *) &serv_addr, sizeof(serv_addr));
    portno = 1818;
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(portno);
    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
        NSLog(@"ERROR on binding");
    }
    listen(sockfd, 5);
    NSLog(@"Begin listen loop");
    clilen = sizeof(cli_addr);
    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
    if (newsockfd < 0) {
        NSLog(@"ERROR on accept");
    }
    while(true) {
        bzero(buffer,256);

        n = read(newsockfd,buffer,255);
        if (n < 0) {
            NSLog(@"ERROR reading from socket");

        }
        if (n > 0) {
            nsbuffer = [NSString stringWithCString:buffer encoding:NSASCIIStringEncoding];
            [_lblStatus setText:nsbuffer];
            NSLog(@"You sent %@", nsbuffer);
        }

        NSLog(@"Finished listen loop");
        sleep(1);
    }
    close(newsockfd);
    close(sockfd);
    NSLog(@"Socket closed");

【问题讨论】:

  • 昨天忘记包含代码了。经过漫长的编码日后真的很煎熬!

标签: ios c sockets posix


【解决方案1】:

createPosixServer 正在后台线程上运行。从后台线程更新 UI 永远不会安全。 UIKit 有时会工作,有时会忽略你。您需要调度调用以将标签更新到主线程,如下所示:

typeof(self) __weak weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
    weakSelf.lblStatus.text = nsbuffer;
});

回答附带问题:当客户端断开连接时,您想关闭您为该连接接受的套接字(您的newsockfd),但您不想关闭您的侦听器sockfd,直到您拆除整个服务。

要退出循环,只需这样做:

if (n < 0) {
    NSLog(@"ERROR reading from socket");
    break;
}

虽然您可能也想检查该块中的errno,因为您可能会根据错误需要不同的行为。

删除sleep(1),这对你没有任何好处。 read 调用会阻塞,不需要休眠。

【讨论】:

  • 啊,谢谢!我怀疑从单独的线程更新 UI 是不行的,但我不确定如何混合 C 和 Objective-C 来正确调用。我正在向后关闭它,看起来,我认为sockfd 对象将是我上次创建它后第一个出现的对象。我从来没有想过这是我缺少的部分。你是什​​么意思read() 调用会阻塞? sleep() 调用是为了确保我不会使处理器过载,每秒检查一百万次。我根本不需要那个?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-21
  • 1970-01-01
  • 2012-03-20
相关资源
最近更新 更多