iphone开发之轻松搞定原生socket 编程,阻塞与非阻塞,收发自如

简介:

iphone socket 开发

 

iphone的平台下,要进行socket开发其实有很多种的方法,开源的库Asyncsocket,官方的CFSocket,还有BSDsocket

这里要做一个简单的socket普及,这里包含在socket的设置非阻塞喝超时的控制逻辑,心跳包和线程的启动时间同步的控制。

 

这里都是标准的linux的流程

先创建一个socket

 

- (int)CSocket

{

    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)

    {

      perror("socket");

      exit(errno);    

    }

    return sockfd;

}

然后是链接

//////////////////

- (BOOL)ConnectToServer:(NSString*)addr port:(int)port

{

    their_addr.sin_family = AF_INET;

    their_addr.sin_addr.s_addr = inet_addr([addr UTF8String]);

    their_addr.sin_port = htons(port);

    bzero(&(their_addr.sin_zero), 8);

    int conn = connect(sockfd, (struct sockaddr*)&their_addr, sizeof(struct sockaddr));

    NSLog(@"Connect error no is %d:",conn);

    return misConnect;

}

 

这样子的链接是阻塞的,这样子就比较不好,可以设置成非阻塞的方式来控制超时

    /***************************************************/

    //connect之前,设成非阻塞模式

    int flags = fcntl(sockfd, F_GETFL,0);

    fcntl(sockfd,F_SETFL, flags | O_NONBLOCK);

    /***************************************************

    //这是另外一种设置成非阻塞的方式

     int flags;

     if((flags = fcntl(sockfd, F_GETFL)) < 0 )

     {

     perror("fcntl F_SETFL");

     }

     flags |= O_NONBLOCK;

     if(fcntl(sockfd, F_SETFL,flags) &lt; 0)

     {

     perror("fcntl");

     }

    ****************************************************/

设置connect后可以设置用select设置超时

/***************************************************/

    //设置超时

    fd_set          fdwrite;

    struct timeval  tvSelect;

   

    FD_ZERO(&fdwrite);

    FD_SET(sockfd, &fdwrite);

    tvSelect.tv_sec = 2;

    tvSelect.tv_usec = 0;

    int retval = select(sockfd + 1,NULL, &fdwrite, NULL, &tvSelect);

    if(retval &lt; 0)

    {

      if ( errno == EINTR )

      {

        NSLog(@"select error");

      }

      else

      {

        NSLog(@"error");

        close(sockfd);

      }

    }

    else if(retval == 0)

    {

      NSLog(@"select timeout........");

    }

    else if(retval > 0)

    {

      misConnect = YES;

    }

 

 

 

    /***************************************************/

    //connect成功之后,设成阻塞模式

    flags = fcntl(sockfd, F_GETFL,0);

    flags &= ~ O_NONBLOCK;

    fcntl(sockfd,F_SETFL, flags);

 

    /***************************************************/

    //设置不被SIGPIPE信号中断,物理链路损坏时才不会导致程序直接被Terminate

    //在网络异常的时候如果程序收到SIGPIRE是会直接被退出的。

    struct sigaction sa;

    sa.sa_handler = SIG_IGN;

    sigaction( SIGPIPE, &sa, 0 );

    /***************************************************/

 

 

然后就可以收发数据了

sendwrite两种方法都可以,你需要自己维护一个队列,控制时间等等

    NSString *str = [SendCmdArray objectAtIndex:0];

    NSData *data = [str dataUsingEncoding:NSISOLatin1StringEncoding];

//  ssize_t datalen = send(sockfd,[data bytes],[data length],0);

    ssize_t datalen = write(sockfd, [data bytes], [data length]);

    if(datalen == [data length])

    {

      NSLog(@"Send str:%@",str);

    }

 

 

如何接收数据,readrecv都可以,这是方法,你需要自己维护一个队列,控制时间等等。

    char readBuffer[512] = {0};

    NSString* readString = nil;

    int br = 0; 

    while (br = read(sockfd, readBuffer, sizeof(readBuffer)) < sizeof(readBuffer))

//  while((br = recv(sockfd, readBuffer, sizeof(readBuffer), 0)) &lt; sizeof(readBuffer))

    {

      NSLog(@"Received CMD:%s",readBuffer);

      readString = [NSString stringWithUTF8String:readBuffer];

      memset(readBuffer,0,sizeof(readBuffer));

    }

    NSLog(@"br is %d,receive exit.",br);

 

 

获取时间后就可以进行时间同步了,具体的时间同步协议要根据自己平台来设计

      time_t timep;

      struct tm *p;

      time(&timep);

      p = localtime(&timep);

      int wday = -1;//return num is (0,6),the weekday range is (1,7)

      if(p->tm_wday == 0)

        wday = 7;

      else

        wday = p-&gt;tm_wday;

      char data[256] = {0};

      sprintf(data,"0E4007%02x%02x%02x%02x%02x%02x%02x",(1900+p-&gt;tm_year)%100,(1+p-&gt;tm_mon),p-&gt;tm_mday,p-&gt;tm_hour,p-&gt;tm_min,p-&gt;tm_sec,wday);

      NSString *msgtime = [NSString stringWithUTF8String:data];

 

可以开一个线程来进行收发,处理相关的操作,想要多线程控制需要注意这个socket必须是全局可用的,因为新线程已经不在主循环了

还有如果有界面更新也需要在主线程更新

 

[NSThread detachNewThreadSelector:@selector(OnNewThread) toTarget:self withObject:nil];

 

可以用timer做一个心跳包维持通讯

 

timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(OnHeartBeatTimer:) userInfo:nil repeats:YES];

 

结束的时候记得关掉定时器和socket

[timer invalidate];

close(sockfd);










本文转自 arthurchen 51CTO博客,原文链接:http://blog.51cto.com/arthurchen/577911,如需转载请自行联系原作者
目录
相关文章
|
1月前
|
安全 Java 数据处理
Python网络编程基础(Socket编程)多线程/多进程服务器编程
【4月更文挑战第11天】在网络编程中,随着客户端数量的增加,服务器的处理能力成为了一个重要的考量因素。为了处理多个客户端的并发请求,我们通常需要采用多线程或多进程的方式。在本章中,我们将探讨多线程/多进程服务器编程的概念,并通过一个多线程服务器的示例来演示其实现。
|
1月前
|
程序员 开发者 Python
Python网络编程基础(Socket编程) 错误处理和异常处理的最佳实践
【4月更文挑战第11天】在网络编程中,错误处理和异常管理不仅是为了程序的健壮性,也是为了提供清晰的用户反馈以及优雅的故障恢复。在前面的章节中,我们讨论了如何使用`try-except`语句来处理网络错误。现在,我们将深入探讨错误处理和异常处理的最佳实践。
|
1月前
|
Python
Python网络编程基础(Socket编程) 使用try-except处理网络错误
【4月更文挑战第11天】在网络编程中,错误处理和异常管理是非常重要的部分。网络操作经常因为各种原因而失败,比如网络断开、服务器无响应、地址不正确等。因此,学会如何使用Python的异常处理机制来捕获和处理这些错误,是编写健壮的网络应用的关键。
|
1月前
|
网络协议 网络安全 Python
Python网络编程基础(Socket编程) 错误处理和异常
【4月更文挑战第10天】网络编程涉及到很多复杂的操作和潜在的风险,如连接失败、数据丢失、超时等问题。因此,正确的错误处理和异常捕获是确保网络程序稳定性和可靠性的关键。本章将介绍网络编程中常见的错误和异常,并探讨如何在Python中进行有效的错误处理。
|
1月前
|
存储 Python
Python网络编程基础(Socket编程) UDP 发送和接收数据
【4月更文挑战第10天】对于UDP客户端而言,发送数据是一个相对简单的过程。首先,你需要构建一个要发送的数据报,这通常是一个字节串(bytes)。然后,你可以调用socket对象的`sendto`方法,将数据报发送到指定的服务器地址和端口。
|
1月前
|
存储 Python
Python网络编程基础(Socket编程)UDP客户端编程
【4月更文挑战第9天】在UDP通信中,客户端负责发送数据到服务器,并接收来自服务器的响应。与服务器不同,客户端通常不需要绑定到特定的地址和端口,因为它可以临时使用任何可用的端口来发送数据。下面,我们将详细讲解UDP客户端编程的基本步骤。
|
1月前
|
Python
Python网络编程基础(Socket编程)绑定地址和端口
【4月更文挑战第9天】在UDP服务器编程中,我们首先需要创建一个UDP套接字,然后绑定一个本地地址和端口,以便客户端可以通过这个地址和端口与我们的服务器进行通信。下面,我们将详细讲解如何绑定地址和端口。
|
1月前
|
网络协议 Python
Python网络编程基础(Socket编程)创建UDP socket对象
【4月更文挑战第8天】在Python中创建UDP服务器涉及使用`socket`模块创建socket对象,如`udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)`,然后绑定到特定IP地址和端口,如`udp_socket.bind((&#39;localhost&#39;, 12345))`。服务器通过`recvfrom`在无限循环中监听和接收数据报。这只是基础,实际应用还需处理接收、解析、响应及错误处理等。接下来可学习如何利用socket对象进行数据交互以构建完整服务器。
|
1月前
|
网络协议 网络性能优化 开发者
Python网络编程基础(Socket编程)UDP Socket编程
【4月更文挑战第8天】Python网络编程中,UDP与TCP协议各有特点。TCP提供可靠连接,确保数据顺序与完整性,适合文件传输等;UDP则无连接,速度快,常用于实时音视频,牺牲了数据可靠性。Python的socket库支持两者,开发者可根据需求选择。
|
29天前
|
网络协议 Linux Python
Python网络编程基础(Socket编程)epoll在Linux下的使用
【4月更文挑战第12天】在上一节中,我们介绍了使用`select`模块来实现非阻塞IO的方法。然而,`select`模块在处理大量并发连接时可能会存在性能问题。在Linux系统中,`epoll`机制提供了更高效的IO多路复用方式,能够更好地处理大量并发连接。