ios socket开发

来源:互联网 发布:罗技键盘g310知乎 编辑:程序博客网 时间:2024/05/21 17:01


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

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

这里都是标准的linux的流程

先创建一个socket

  1. - (int)CSocket
  2. {
  3.     if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  4.     {
  5.       perror("socket");
  6.       exit(errno);   
  7.     }
  8.     return sockfd;
  9. }
复制代码

然后是链接

  1. //////////////////

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

  3. {

  4.    their_addr.sin_family = AF_INET;

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

  6.     their_addr.sin_port = htons(port);

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

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

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

  10.     return misConnect;
  11. }
复制代码

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

  1. /***************************************************/

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

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

  4.     fcntl(sockfd,F_SETFL, flags | O_NONBLOCK);

  5.     /***************************************************

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

  7.      int flags;

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

  9.      {

  10.      perror("fcntl F_SETFL");

  11.      }

  12.      flags |= O_NONBLOCK;

  13.      if(fcntl(sockfd, F_SETFL,flags) < 0)

  14.      {

  15.      perror("fcntl");

  16.      }

  17.      ****************************************************/
复制代码

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

  1. /***************************************************/

  2.     //设置超时

  3.     fd_set          fdwrite;

  4.     struct timeval  tvSelect;

  5.     FD_ZERO(&fdwrite);

  6.     FD_SET(sockfd, &fdwrite);

  7.     tvSelect.tv_sec = 2;

  8.     tvSelect.tv_usec = 0;

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

  10.     if(retval < 0)

  11.     {

  12.       if ( errno == EINTR )

  13.       {

  14.         NSLog(@"select error");

  15.       }

  16.       else

  17.       {

  18.         NSLog(@"error");

  19.         close(sockfd);

  20.       }

  21.     }

  22.     else if(retval == 0)

  23.     {

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

  25.     }

  26.     else if(retval > 0)

  27.     {

  28.       misConnect = YES;
  29. }

  30.    /***************************************************/
  31. //在connect成功之后,设成阻塞模式

  32.     flags = fcntl(sockfd, F_GETFL,0);

  33.     flags &= ~ O_NONBLOCK;

  34.     fcntl(sockfd,F_SETFL, flags);

  35.     /***************************************************/

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

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

  38.     struct sigaction sa;

  39.     sa.sa_handler = SIG_IGN;

  40.     sigaction( SIGPIPE, &sa, 0 );

  41.     /***************************************************/
复制代码


然后就可以收发数据了

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

  1. NSString *str = [SendCmdArray objectAtIndex:0];

  2.     NSData *data = [str dataUsingEncoding:NSISOLatin1StringEncoding];

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

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

  5.     if(datalen == [data length])

  6.     {

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

  8.     }
复制代码

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

  1. char readBuffer[512] = {0};

  2.     NSString* readString = nil;

  3.     int br = 0;

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

  5. //  while((br = recv(sockfd, readBuffer, sizeof(readBuffer), 0)) < sizeof(readBuffer))

  6.     {

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

  8.       readString = [NSString stringWithUTF8String:readBuffer];

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

  10.     }

  11.     NSLog(@"br is %d,receive exit.",br);
复制代码

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

  1. time_t timep;

  2.       struct tm *p;

  3.       time(&timep);

  4.       p = localtime(&timep);

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

  6.       if(p->tm_wday == 0)

  7.         wday = 7;

  8.       else

  9.         wday = p->tm_wday;

  10.       char data[256] = {0};

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

  12.       NSString *msgtime = [NSString stringWithUTF8String:data];
复制代码


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

  1. [NSThread detachNewThreadSelector:@selector(OnNewThread) toTarget:self withObject:nil];
复制代码


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

  1. timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(OnHeartBeatTimer:) userInfo:nil repeats:YES];
复制代码

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

  1. [timer invalidate];

  2. close(sockfd);
0 0
原创粉丝点击