iOS socket网络编程实例详解

代码下载

服务端代码下载地址

客户端代码下载地址

相关概念

socket是一个针对TCP和UDP编程的接口,你可以借助它建立TCP连接等。socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。Socket的出现只是使得程序员更方便地使用TCP/IP协议栈而已,是对TCP/IP协议的抽象,从而形成了我们知道的一些最基本的函数接口。

socket连接:socket连接就是所谓的长连接,理论上客户端和服务器端一旦建立起连接将不会主动断掉;但是由于各种环境因素可能会是连接断开,比如说:服务器端或客户端主机down了,网络故障,或者两者之间长时间没有数据传输,网络防火墙可能会断开该连接以释放网络资源。所以当一个socket连接中没有数据的传输,那么为了维持连接需要发送心跳消息~~具体心跳消息格式是开发者自己定义的。

TCP连接的三次握手:

第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。

握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。断开连接时服务器和客户端均可以主动发起断开TCP连接的请求,断开过程需要经过“四次握手”。

socket建立网络连接的步骤

建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket ,另一个运行于服务器端,称为ServerSocket 。

套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。

1。服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。

2。客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。

3。连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。

BSD socket

BSD socket:完全由c语言实现,并且可以在Objective-C代码中使用。

优点:不同平台中易于移植

缺点:

无法访问操作系统内建的网络特性(比如系统范围的VPN)。
更糟糕的是初始化socket连接并不会自动打开设备的Wi-Fi或是蜂窝网络,无线网络会智能的关闭以节省电池电量,任何通信连接都会失败,除非其他网络进程激活了无线网。

CFNetwork对BSD Socket的分装可以激活设备的无线网,所以几乎所有场景都建议使用CFNetwork而不是BSD Socket.

最常用的API:

1.int socket(int, int, int):创建并初始化新的socket,如果成功放回一个文件描述符,如果失败返回0。

2.int bind(int, const struct sockaddr *, socklen_t):为指定的地址与端口号分配socket。

3.int listen(int, int) __DARWIN_ALIAS(listen):用于服务端监听客户端

4.int accept(int, struct sockaddr * __restrict, socklen_t * __restrict):接受连接请求,将客户端地址存储到clientAddress中。

5.int connect(int, const struct sockaddr *, socklen_t):连接到指定的服务器。

6.ssize_t send(int, const void *, size_t, int):在socket上最多发送XX数据。

7.ssize_t recv(int, void *, size_t, int):在socket上最多读取XX数据。

……

服务端逻辑:如果接收到客户端发送过来”1”,那么回复”你猜!”;客户端发送过来”2”,那么回复”谢谢!”;客户端发送过来”3”,那么回复”对不起!”;客户端发送过来”4”,那么回复”好的!”;客户端发送过来其他的内容,那么一半概率原样回复,一半概率回复”不知道你在说什么!”。

创建服务端:

1.创建socket

struct sockaddr_in server_addr;
 server_addr.sin_len = sizeof(struct sockaddr_in);
 server_addr.sin_family = AF_INET;//AF_INET互联网地址簇
 server_addr.sin_port = htons(port);
 server_addr.sin_addr.s_addr = inet_addr(address);
 bzero(&server_addr.sin_zero, 8);
 //创建socket
 int server_socket = socket(AF_INET, SOCK_STREAM, 0);//SOCK_STREAM 有链接
 if (server_socket == -1) {
  perror("socket error!");
  return 1;
 }

2.绑定socket:将创建的socket绑定到本地的IP地址和端口,此socket是半相关的,只是负责侦听客户端的连接请求,并不能用于和客户端通信

 int bind_result = bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr));
 if (bind_result == -1) {
  perror("bind error!");

  return 1;
 }

3.listen侦听

 if (listen(server_socket, 5)) {
  perror("listen error!");
  return 1;
 }

4.接受客户端连接

int client_socket;
 socklen_t address_len;
 struct sockaddr_in client_address;
 for (; ; ) {
  address_len = sizeof(client_address);
  client_socket = accept(server_socket, (struct sockaddr*)&client_address, &address_len);
  //1.使用多线程
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
   //这个函数进行数据操作
   str_echo(client_socket);
  });
 }

5.接收和发送数据

 char buf[1024];
 while (1) {
  bzero(buf, 1024);
  long byte_num = recv(socket, buf, 1024, 0);
  if (byte_num < 0) {
   return;
  }
  buf[byte_num] = '\0';
  printf("client said:%s\n", buf);
  char *result;
  NSString *str = [NSString stringWithCString:buf encoding:NSUTF8StringEncoding];
  if ([str isEqualToString:@"1"]) {
   result = "你猜!";
  }
  else if ([str isEqualToString:@"2"])
  {
   result = "谢谢!";
  }
  else if ([str isEqualToString:@"3"])
  {
   result = "对不起!";
  }
  else if ([str isEqualToString:@"4"])
  {
   result = "好的!";
  }
  else
  {
   if (arc4random()%2 == 0) {
    result = "不知道你在说什么!";
   }
   else
   {
    result = buf;
   }
  }
  send(socket, result, 1024, 0);
 }

创建客户端:

struct sockaddr_in server_addr;
 server_addr.sin_len = sizeof(struct sockaddr_in);
 server_addr.sin_family = AF_INET;
 server_addr.sin_port = htons(11332);
 server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
 bzero(&(server_addr.sin_zero), 8);
 int server_socket = socket(AF_INET, SOCK_STREAM, 0);
 if (server_socket == -1) {
  perror("socket error");
  return 1;
 }
 char receive_msg[1024];
 char reply_msg[1024];
 if (connect(server_socket, (struct sockaddr*)&server_addr, sizeof(struct sockaddr_in)) == 0) {
  //connect 成功之后,其实系统将你创建的socket绑定到一个系统分配的端口上,且其为全相关,包含服务器端的信息,可以用来和服务器端进行通信。
  while (1) {
   bzero(reply_msg, 1024);
   printf("replay:");
   scanf("%s", reply_msg);
   if (send(server_socket, reply_msg, 1024, 0) == -1) {
    perror("send error!");
    return 1;
   }
   bzero(receive_msg, 1024);
   long byte_num = recv(server_socket, receive_msg, 1024, 0);
   receive_msg[byte_num] = '\0';
   printf("server said:%s\n", receive_msg);
  }
 }
 return 0;

NSStream 读写文件

Cocoa Streams包含三个相关的类: NSStream、NSInputStream 和NSOutputStream。

NSStream:是个抽象类,定义了一些基本属性和方法;

NSInputStream:是NSStream的子类,可通过它从NSData、File和socket中读取数据流;

NSOutputStream:也是NSStream的子类,可通过它将数据流写入NSData、File和socket。

还可以给stream对象设置Delegate(NSStreamDelegate),如果没有精确了给stream指定Delegate,那么默认将Delegate设置为其自己。

NSStreamDelegate只有一个方法
(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode

NSStreamEventNone :改默认值不代表任何事件

NSStreamEventOpenCompleted :socket被成功打开

NSStreamEventHasBytesAvailable :有可以读取的字节

NSStreamEventHasSpaceAvailable :缓存中可以写入字节

NSStreamEventErrorOccurred :操作出现错误CFReadStreamCopyError()和CFWriteStreamCopyError()会提供更多错误细节

NSStreamEventEndEncountered :socket达到字节流的末尾

通过NSStream对象读数据,可以分为如下步骤完成:

a) 从数据源创建和初始化一个NSStream对象;

b) 配置run loop,并打开stream对象;

c) 响应NSInputStream事件(NSStreamDelegate);

d) 关闭NSInputStream对象。

- (void)viewDidLoad {
 [super viewDidLoad];
 NSString *documentStr = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
 NSString *dataPath = [documentStr stringByAppendingPathComponent:@"data.txt"];
 NSFileManager *manager = [NSFileManager defaultManager];
 if ([manager fileExistsAtPath:dataPath]) {
  self.read = YES;
  NSLog(@"string:%@", [NSString stringWithContentsOfFile:dataPath encoding:NSUTF8StringEncoding error:nil]);
  NSInputStream *inStream = [[NSInputStream alloc] initWithFileAtPath:dataPath];
  [inStream setDelegate:self];
  [inStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
  [inStream open];
 }
 else
 {
  if ([manager createFileAtPath:dataPath contents:nil attributes:nil]) {
   self.read = NO;
   NSOutputStream *outStream = [[NSOutputStream alloc] initToFileAtPath:dataPath append:YES];
   [outStream setDelegate:self];
   [outStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
   [outStream open];
  }
  else
  {
   NSLog(@"文件创建失败!");
  }
 }
}
#pragma mark - <NSStreamDelegate>代理方法
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
 if (self.read) {
  NSInputStream *inStream = (NSInputStream *)aStream;
  switch (eventCode) {
   case NSStreamEventHasBytesAvailable:
   {
    uint8_t data[1024];
    [inStream read:data maxLength:1024];
    printf("%s", data);
    [inStream close];
    [inStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    inStream = nil;
   }
    break;
   case NSStreamEventEndEncountered:
   {
    [inStream close];
    [inStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    inStream = nil;
   }
    break;
   default:
    break;
  }
 }
 else{
  NSOutputStream *outStream = (NSOutputStream *)aStream;
  switch (eventCode) {
   case NSStreamEventHasSpaceAvailable:
   {
    uint8_t data[] = "{name:'张三', age:10}";
    [outStream write:data maxLength:strlen((char *)data)];
    [outStream close];
    [outStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    outStream = nil;
   }
    break;
   case NSStreamEventEndEncountered:
   {
    [outStream close];
    [outStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    outStream = nil;
   }
    break;
   default:
    break;
  }
 }
}

NSStream Socket

NSStream类不支持在IOS平台上创建socket连接,而CFStream支持在IOS平台的socket行为。所以若知道远程主机的DNS或者是IP地址,可以使用CFStreamCreatePairWithSocketToHost函数来创建socket连接,通过该函数创建了CFStream类型为全双工的socket连接,接着可以利用toll-free bridge,将CFStream对象转换为NSStream对象。

通过NSStream对象进行Socket通信,与通过NSStream进行IO操作的步骤基本一样:

a) 创建NSStream对象,通过CFStreamCreatePairWithSocketToHost函数创建CFReadStreamRef 和CFWriteStreamRef 对象;继而将两者转换为NSInputStream 和NSOutputStream 对象;

b) 配置run loop,并打开NSInputStream 和NSOutputStream对象;

c) 响应事件,在Delegate中响应不同的信号;

d) 关闭NSStream对象。

服务端:服务端依然使用上面例子的服务端

客户端的实现:点击1~5这五个按钮,分别从服务端返回不同的数据,进而展示出来。

由于实现相对简单,就不加阐述说明了,实现代码如下:

- (void)viewDidLoad {
 [super viewDidLoad];
 [self startSocket:@"127.0.0.1" andPort:11332];
}
- (void)startSocket:(NSString *)address andPort:(int)port
{
 CFReadStreamRef readRef;
 CFWriteStreamRef writeRef;
 CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)address, port, &readRef, &writeRef);
 NSInputStream *inputStream = (__bridge NSInputStream *)readRef;
 NSOutputStream *outputStream = (__bridge NSOutputStream *)writeRef;
 inputStream.delegate = self;
 outputStream.delegate = self;
 [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
 [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
 [inputStream open];
 [outputStream open];
 self.outputStream = outputStream;
}
- (IBAction)sendMsg:(UIButton *)sender {
 if (sender.currentTitle > 0) {
  const char *output = sender.currentTitle.UTF8String;
  [self.outputStream write:(const uint8_t *)output maxLength:strlen(output)];
 }
}
- (void)showMessage:(NSString *)msg
{
 if (!self.msgLabel) {
  UIFont *font = [UIFont systemFontOfSize:14];
  UIColor *color = [UIColor blackColor];
  UIColor *backColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.2];
  UILabel *label = [[UILabel alloc] init];
  label.textColor = color;
  label.font = font;
  label.textAlignment = NSTextAlignmentCenter;
  label.backgroundColor = backColor;
  self.msgLabel = label;
 }
 CGFloat screenW = [UIScreen mainScreen].bounds.size.width;
 CGFloat screenH = [UIScreen mainScreen].bounds.size.height;
 CGFloat W = screenW - 16;
 CGSize size = [msg boundingRectWithSize:CGSizeMake(W, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:self.msgLabel.font} context:nil].size;
 W = size.width;
 CGFloat H = size.height;
 CGFloat X = (screenW - W)/2;
 CGFloat Y = (screenH - H)/2;
 self.msgLabel.frame = CGRectMake(X, Y, W, H);
 self.msgLabel.text = msg;
 [self.view addSubview:self.msgLabel];
 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  [self.msgLabel removeFromSuperview];
 });
}
#pragma mark - <NSStreamDelegate>代理方法
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
 switch (eventCode) {
  case NSStreamEventNone:
   break;
  case NSStreamEventOpenCompleted:
   break;
  case NSStreamEventHasBytesAvailable:
  {
   uint8_t buf[1024];
   NSInteger len = 0;
   NSInputStream *inputStream = (NSInputStream *)aStream;
   len = [inputStream read:buf maxLength:1024];
   if (len) {
    [self showMessage:[NSString stringWithCString:(const char *)buf encoding:NSUTF8StringEncoding]];
   }
   break;
  }
  case NSStreamEventHasSpaceAvailable:
   break;
  case NSStreamEventErrorOccurred:
  {
   [aStream close];
   break;
  }
  case NSStreamEventEndEncountered:
  {
   [aStream close];
   [aStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
   aStream = nil;
   break;
  }
  default:
   break;
 }

以上所述是小编给大家介绍的iOS socket网络编程,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大的!

(0)

相关推荐

  • IOS 出现问题POST网络请求状态code:500的解决方法

    IOS 出现问题POST网络请求状态code:500的解决方法 前言: iOS 10 用 [NSURLSession uploadTaskWithRequest:request fromData:jsondata completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error){}]; 进行post网络请求时 出现 500 错误 出现500 的错误

  • IOS 网络请求中设置cookie

    IOS 网络请求中设置cookie 1. ASIHTTPRequest ASIHTTPRequest 是一款极其强劲的 HTTP 访问开源项目.让简单的 API 完成复杂的功能,如:异步请求,队列请求,GZIP 压缩,缓存,断点续传,进度跟踪,上传文件,HTTP 认证. cookie的支持 如果 Cookie 存在的话,会把这些信息放在 NSHTTPCookieStorage 容器中共享,并供下次使用.你可以用 [ ASIHTTPRequest setSessionCookies:nil ] ;

  • Vue.js教程之axios与网络传输的学习实践

    前言 在学习了之前的路由vue-router和状态管理vuex之后,就应该是网络交互了.就学习尤大推荐的axios了.刚好本人对网络请求这块除了会get.put.post和delete这四个方法之外知之甚少,刚好补全上. 注意:Vue官方推荐的网络通信库不再是vue-resource了,推荐使用axios. 为何放弃vue-resource? 尤大的原话: 最近团队讨论了一下,Ajax 本身跟 Vue 并没有什么需要特别整合的地方,使用 fetch polyfill 或是 axios.super

  • iOS中设置网络超时时间+模拟的方法详解

    设置方法如下: 在封装的网络请求类里面如下设置 AFWEBAPI_REQUEST_TIMEOUT 这个参数为超时时间 #define AFWEBAPI_REQUEST_TIMEOUT 20 #pragma mark - 单例 & 构造函数 + (instancetype)sharedTools { static WXNetworkTools *instance; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ i

  • 详解iOS中多个网络请求的同步问题总结

    场景描述:我们同时发出了a.b.c 3个网络请求,我们希望在a.b.c 3个网络请求都结束的时候获得一个通知. 常见解决方法:通过度娘目前找到两种做法:1.通过添加标识来判断请求是否全部结束 2.dispatch_group + 信号量 本篇文章demo 1.添加标识的解决方法 在遇到这个问题时首先想到了唐巧大大的猿题库团队开源的网络框架YTKNetwork,然后阅读源码发现YTKNetwork是通过添加标识来实现网络请求的批量请求处理: 话不多说直接上代码在YTKNetwork里负责进行网络批

  • iOS判断网络请求超时的方法

    本文介绍了iOS判断网络请求超时的方法,代码具体如下: + (AFHTTPRequestOperation *)requestOperationWithUrl:(NSString *)url requetMethod:(NSString *)method paramData:(NSDictionary *)aParamData constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block success

  • IOS开发中异步网络请求上实现同步逻辑

    IOS开发中异步网络请求上实现同步逻辑 前提: 可能遇到一些问题,比如上传多个数据,需要等多个数据上传成功后做一定的处理,而且一个个上传,万一哪个上传失败了,后面就不需要上传了,直接报错. 之前ASI的网络库中是有同步请求的接口,所以很好处理,AFNetwork的网络库只有异步的网络请求,该怎么实现呢? 1.循环异步拼组 - (void)uploadFile:(NSArray *)imageArray atIndex:(NSInteger)index imagesCount:(NSInteger

  • iOS利用AVPlayer播放网络音乐的方法教程

    前言 假如你现在打算做一个类似百度音乐.豆瓣电台的在线音乐类APP,你会怎样做? 首先了解一下音频播放的实现级别: (1) 离线播放:这里并不是指应用不联网,而是指播放本地音频文件,包括先下完完成音频文件再进行播放的情况,这种使用AVFoundation里的AVAudioPlayer可以满足 (2) 在线播放:使用AVFoundation的AVPlayer可以满足 (3) 在线播放同时存储文件:使用AudioFileStreamer + AudioQueue 可以满足 (4) 在线播放且带有音效

  • iOS socket网络编程实例详解

    代码下载 服务端代码下载地址 客户端代码下载地址 相关概念 socket是一个针对TCP和UDP编程的接口,你可以借助它建立TCP连接等.socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议.Socket的出现只是使得程序员更方便地使用TCP/IP协议栈而已,是对TCP/IP协议的抽象,从而形成了我们知道的一些最基本的函数接口. socket连接:socket连接就是所谓的长连接,理论上客户端和服务器端一旦

  • C++中Socket网络编程实例详解

    C++中Socket网络编程实例详解 现在几乎所有C/C++的后台程序都需要进行网络通讯,其实现方法无非有两种:使用系统底层socket或者使用已有的封装好的网络库.本文对两种方式进行总结,并介绍一个轻量级的网络通讯库ZeroMQ.  1.基本的Scoket编程 关于基本的scoket编程网络上已有很多资料,作者在这里引用一篇文章中的内容进行简要说明. 基于socket编程,基本上就是以下6个步骤: 1.socket()函数 2.bind()函数 3.listen().connect()函数 4

  • Java基于Socket实现网络编程实例详解

    一,网络编程中两个主要的问题 一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输. 在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可以唯一地确定Internet上的一台主机. 而TCP层则提供面向应用的可靠(tcp)的或非可靠(UDP)的数据传输机制,这是网络编程的主要对象,一般不需要关心IP层是如何处理数据的. 目前较为流行的网络编程模型是客户机/服务器(C/S)结构.即通信双方一方作为服务器等待客户提出请求并予以响应.客户则

  • python socket网络编程步骤详解(socket套接字使用)

    一.套接字套接字是为特定网络协议(例如TCP/IP,ICMP/IP,UDP/IP等)套件对上的网络应用程序提供者提供当前可移植标准的对象.它们允许程序接受并进行连接,如发送和接受数据.为了建立通信通道,网络通信的每个端点拥有一个套接字对象极为重要.套接字为BSD UNIX系统核心的一部分,而且他们也被许多其他类似UNIX的操作系统包括Linux所采纳.许多非BSD UNIX系统(如ms-dos,windows,os/2,mac os及大部分主机环境)都以库形式提供对套接字的支持.三种最流行的套接

  • C++ 中 socket编程实例详解

    C++ 中 socket编程实例详解 sockets(套接字)编程有三种,流式套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM),原始套接字(SOCK_RAW):基于TCP的socket编程是采用的流式套接字.在这个程序中,将两个工程添加到一个工作区.要链接一个ws2_32.lib的库文件. 服务器端编程的步骤: 1:加载套接字库,创建套接字(WSAStartup()/socket()): 2:绑定套接字到一个IP地址和一个端口上(bind()): 3:将套接字设置为监听模式

  • IOS 获取网络图片大小实例详解

    IOS 获取网络图片大小实例详解 在iOS开发过程中经常需要通过网络请求加载图片,有时,需要在创建UIImageView或UIButton来显示图片之前需要提前知道图片的尺寸,根据图片尺寸创建对应大小的控件.但是对于网络图片来说,要想通过最优的方法获得尺寸就略微有点困难,大体思路就是下面这种: 如果有使用SDWebImage,则首先检查是否缓存过该图片,如果没有,先通过文件头获取图片大小(针对格式为png.gif.jpg文件获取其尺寸大小),如果获取失败,则下载完整的图片data,然后计算大小,

  • iOS UITableView 与 UITableViewController实例详解

    很多应用都会在界面中使用某种列表控件:用户可以选中.删除或重新排列列表中的项目.这些控件其实都是UITableView 对象,可以用来显示一组对象,例如,用户地址薄中的一组人名. UITableView 对象虽然只能显示一行数据,但是没有行数限制. •编写新的应用程序 JXHomepwner 应用 创建应用,填写基本信息 •UITableViewController UITableView 是视图.我们知道 模型-视图-控制器(Model-View-Controller),他是我们必须遵守的一种

  • linux下的C\C++多进程多线程编程实例详解

    linux下的C\C++多进程多线程编程实例详解 1.多进程编程 #include <stdlib.h> #include <sys/types.h> #include <unistd.h> int main() { pid_t child_pid; /* 创建一个子进程 */ child_pid = fork(); if(child_pid == 0) { printf("child pid\n"); exit(0); } else { print

  • IOS 绘制三角形的实例详解

    IOS 绘制三角形的实例详解 先上效果图 上面三角形的代码 - (void)ljTestView { CGPoint piont1; piont1.x = 170; piont1.y = 100; CGPoint piont2; piont2.x = 50; piont2.y = 200; CGPoint piont3; piont3.x = 220; piont3.y = 200; ljDrawRect *_ljView = [[ljDrawRect alloc]initStartPoint:

  • Android 动态注册监听网络变化实例详解

    Android 动态注册监听网络变化实例详解 新建一个BroadcastTest项目,然后修改MainActivity中的代码,如下: public class MainActivity extends AppCompatActivity { private IntentFilter intentFilter; private NetworkChangeReceiver networkChangeReceiver; @Override protected void onCreate(Bundle

随机推荐