NSOperation:
1. 指定同一时间最大执行的操作数
queue.max……
2. 设定队列中的任务时间的依赖关系
task1 依赖于 task2: task2 —> task1
3. 回到主线程(找到如何获取主队列的方式)[NSOperation mainQueue]:

keyword: iOS main queue

Socket: 网络中的两个程序通过双向的通讯,达到交换数据的目的。

发送(客户端):终端控制台
接收(服务器端):  终端控制台(sever.py)

资源:网页(www.sina.com.cn)/图片/软件/.......

1. 服务器监听状态 standby (开机+应用程序启动)
2. 客户端发送请求Request给服务器端
3. 连接确认, 客户端接收服务器返回的数据

客户端:iOS应用程序

服务器端:启动server.py

#coding:utf-

from twisted.internet.protocol import Factory, Protocol
from twisted.internet import reactor class IphoneChat(Protocol):
def connectionMade(self):
self.factory.clients.append(self)
print "当前连线的客户端有", self.factory.clients def connectionLost(self, reason):
self.factory.clients.remove(self) def dataReceived(self, data):
a = data.split(':')
if len(a) > :
command = a[].strip()
content = a[].strip() msg = ""
if command == "iam":
self.name = content
msg = self.name + " 加入了聊天室" elif command == "msg":
msg = self.name + ": " + content print msg for c in self.factory.clients:
c.message(msg) def message(self, message):
self.transport.write(message + '\n') factory = Factory()
factory.clients = []
factory.protocol = IphoneChat
reactor.listenTCP(, factory)
print "Iphone Chat server started"
reactor.run()

脚本代码



NSInputStream:    读取数据
NSOutputStream:写数据

发送消息:
功能:
存放接收消息 —> NSArray —> UITableView

准备工作:
UITableView准备(datasource, delegate)
两个stream的delegate (NSStreamDelegate)

具体实现:

@interface ViewController () <UITableViewDataSource, UITableViewDelegate, NSStreamDelegate>
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (weak, nonatomic) IBOutlet UITextField *messageTextField; //输入流(读)
@property (nonatomic, strong) NSInputStream *inputStream; //输出流(写)
@property (nonatomic, strong) NSOutputStream *outputStream; //存放服务器返回消息的可变数组
@property (nonatomic, strong) NSMutableArray *messageArray; @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
//初始化可变数组对象
self.messageArray = [NSMutableArray array]; //设置delegate
self.tableView.dataSource = self;
self.tableView.delegate = self; //准备工作:和服务器端进行连接
[self createConnectionToServer]; } - (void)createConnectionToServer {
//telnet 196.112.122.11 1025 //创建两个stream相关的类
CFReadStreamRef readStream;
CFWriteStreamRef writeStream; //NSStream不具有连接服务器的功能
//创建和服务器的连接
/**
第二个参数:连接服务器的ip地址 (localhost)
第三个参数:指定端口
*/
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"localhost", , &readStream, &writeStream); //将底层的CFStream转换成NSStream相关的类
self.inputStream = (__bridge NSInputStream *)readStream;
self.outputStream = (__bridge NSOutputStream *)writeStream; //设置两个stream的delegate
self.inputStream.delegate = self;
self.outputStream.delegate = self; //把这两个stream添加到runloop中(原因:才可以响应对应的代理方法)
[self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[self.outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; //将两个stream打开
[self.inputStream open];
[self.outputStream open];
} - (IBAction)enterChatRoom:(id)sender {
//iam:xxxxx
NSString *text = @"iam:Maggie"; //NSString --> NSData
NSData *data = [text dataUsingEncoding:NSUTF8StringEncoding]; //写数据(OutputSteam)
[self.outputStream write:[data bytes] maxLength:[data length]];
} - (IBAction)sendMessage:(id)sender {
//发送消息到服务器端(msg:xxxxx)
NSString *messageStr = [NSString stringWithFormat:@"msg:%@", self.messageTextField.text]; //往outputStream中写数据
NSData *data = [messageStr dataUsingEncoding:NSUTF8StringEncoding];
[self.outputStream write:[data bytes] maxLength:[data length]]; //清空textField文本
self.messageTextField.text = nil;
} #pragma mark -- NSStreamDelegate
//针对两个管道Stream, 处理不同的事件
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode {
switch (eventCode) {
case NSStreamEventOpenCompleted:
NSLog(@"Stream打开");
break;
case NSStreamEventHasSpaceAvailable:
NSLog(@"Stream还有空间可以放数据");
break;
case NSStreamEventHasBytesAvailable:
NSLog(@"此时Stream有数据");
[self readBytes:aStream];
break;
case NSStreamEventErrorOccurred:
NSLog(@"有错误出现");
//把stream关掉
[self.inputStream close];
[self.outputStream close];
//从runloop中移除
[self.inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[self.outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
break; default:
break;
} } - (void)readBytes:(NSStream *)aStream {
//将数据显示在table view上
//首先判定是服务器返回的(将服务器消息显示在table view上)
if (aStream == self.inputStream) {
unsigned char readData[];
//读取输入流的数据(服务器返回来的数据)
while ([self.inputStream hasBytesAvailable]) {
//获取服务器返回的数据
/**
第一个参数:读取的数据存放对象
第二个参数:读取的最大bytes数量
*/
NSInteger length = [self.inputStream read:readData maxLength:sizeof(readData)];
if (length > ) {
//读取到数据
NSString *messageStr = [[NSString alloc] initWithBytes:readData length:length encoding:NSUTF8StringEncoding];
//将获取到的字符串添加到可变数组中
[self.messageArray addObject:messageStr];
//显示在table view上
[self.tableView reloadData]; }
}
}
} #pragma mark -- table view datasouce/delegate
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.messageArray.count;
} //设置cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//创建identifier
static NSString *cellID = @"messageCell"; //从缓存池中获取cell(Reuse可复用性)
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID]; //如果缓存池中没有,再重新创建
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
} //设置cell文本属性
cell.textLabel.text = self.messageArray[indexPath.row]; return cell;
} @end

练习:
1. 点中UITextFiled,键盘弹出,table view和其他控件上移
2. 让table view最后一行,始终显示用户发送的最新的消息

官方socket实例代码链接:
https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Conceptual/Streams/Articles/NetworkStreams.html#//apple_ref/doc/uid/20002277-BCIDFCDI

URL: (Uniform Resource Locator) 统⼀资源定位符
最完整格式:
协议://IP地址:端口/路径/文件名字
一般格式:
IP地址(域名)/路径/文件名字

协议的通俗说法:发送数据方和接收数据方规定的传送数据的规则

File协议:从本地查找相应的文件
URL —>
file:///Users/tarena/Downloads/testImages/aa.jpg

HTTP协议内部数据

小例子:
把本地mac机器改装成提供web服务(Apache软件)的服务器步骤:
1. 查看Apache软件是否安装
sudo apachectl -v
输入mac系统的密码
2. 启动apache软件
sudo apachectl start
3. 在浏览器中输入localhost,显示It works!就表示mac机器成为了可以提供网页服务的机器

http://IP地址:端口/路径/文件名字

MIME: 客户端(浏览器)指定服务器返回的类型(xxx.html)
文本类型:
text/html:不仅包含文本,也包含.jpg/.gif/.....
text/xml
text/plain: 只能包含文本

http协议的规则:
1. 指定MIME类型: text/html
2. 方法:
    a. GET (获取资源:html文件)
    b. DELETE (删除资源:图片)
    c. POST: 登录(用户名/密码)
    d. PUT: 上传文件/上传信息
3. status code: 服务返回的状态码
     a. 成功:200/OK
     c. 失败:
     404 -> 未找到资源(html文件)
     400 -> 客户端的请求,服务器端无法解析
     501 -> 服务器错误
4.响应Response (服务器返回):
content-length: 总长度多少
content-range (****): 默认服务器会返回客户端请求的资源的总数据

iOS中发送网络请求的方案:
方案一:
NSURLConnection (相对麻烦/更加理解http原理):
方案二
NSURLSession (简单/封装性高):

此案例主要以方案一来实现:
样例:界面上输入任意一个网址(URL), 将返回的网页显示到界面上(xxx.html) (NSURLConnection)
UI界面:UITextField; UIButton; UIWebView(内嵌浏览器)

具体实现:

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIWebView *webView;
@property (weak, nonatomic) IBOutlet UITextField *urlTextField; //界面输入的URL
@property (nonatomic, strong) NSURL *url; @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad]; }
//发送请求Request ---> 接收响应Response
- (IBAction)sendSyncRequest:(id)sender {
//NSURLConnection
//1.创建一个客户端发送请求对象
self.url = [NSURL URLWithString:self.urlTextField.text];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:self.url];
//2.开始执行发送的同步请求
//3.获取服务器返回的html文件
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:&error];
if (error) {
NSLog(@"发送请求失败:%@", error.userInfo);
return;
} //4.并显示在UIWebView上
[self.webView loadData:data
MIMEType:@"text/html"
textEncodingName:@"utf-8"
baseURL:nil]; NSLog(@"请求执行完毕%@; 数据的大小%lu", [NSThread currentThread], (unsigned long)data.length);
} - (IBAction)sendAsyncRequest:(id)sender { //1.创建客户端发送请求对象
self.url = [NSURL URLWithString:self.urlTextField.text];
NSURLRequest *request = [NSURLRequest requestWithURL:self.url]; //2.异步执行请求
//创建非主队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
//获取response的状态码(判定服务器是否返回成功200)
//data:服务器返回的数据
//connectionError:具体的错误
NSLog(@"返回%@", [NSThread currentThread]);
NSInteger retStatusCode = [(NSHTTPURLResponse *)response statusCode];
if (retStatusCode == ) {
//回到主线程更新界面UIWebView
dispatch_async(dispatch_get_main_queue(), ^{
//3.显示服务器返回的数据到UIWebView
[self.webView loadData:data MIMEType:@"text/html" textEncodingName:@"utf-8" baseURL:nil];
});
} else {
NSLog(@"失败%@",connectionError.userInfo);
}
}];
} @end

socket网络间通信初识的更多相关文章

  1. Linux下TCP网络编程与基于Windows下C#socket编程间通信

    一.linux下TCP网络编程基础,需要了解相关函数 Socket():用于套接字初始化. Bind():将 socket 与本机上的一个端口绑定,就可以在该端口监听服务请求. Listen():使s ...

  2. Python socket网络编程(通信介绍)

      socket通信介绍 通信介绍(一) 1.所有网络协议的基础就是:socket 2.socket对TCP与UDP协议封装,让用户进行简单操作. 3.socket只做两件事:发 send,收 rec ...

  3. [OSI]网络间通信流程

    PC 连接交换机A,组成内网.DNS Serv 和 Web Serv 连接交换机B 组成外网. 示意图: 内网通信 PC1 到 PC2: PC1 发送的数据先到交换机A,交换机A没有ARP地址缓存表, ...

  4. Python--day38---进程间通信--初识队列(multiprocess.Queue)

    初识队列: 进程间通信IPC(Inter-Process Communication) 1,队列的方法: q = Queue(5)1,q.put(1) #把1放进队列 2,print(q.full() ...

  5. Python--day38---进程间通信--初识队列(multiprocess.Queue)之生产者,消费者模型

    1,生产者消费者模型.py import random import time from multiprocessing import Queue, Process def producer(name ...

  6. Java 网络编程(五) 使用TCP/IP的套接字(Socket)进行通信

    链接地址:http://www.cnblogs.com/mengdd/archive/2013/03/10/2952616.html 使用TCP/IP的套接字(Socket)进行通信 套接字Socke ...

  7. [Socket]Socket进程间的通信

    转自:http://blog.csdn.net/giantpoplar/article/details/47657303 前面说到的进程间的通信,所通信的进程都是在同一台计算机上的,而使用socket ...

  8. Python网络编程02 /基于TCP、UDP协议的socket简单的通信、字符串转bytes类型

    Python网络编程02 /基于TCP.UDP协议的socket简单的通信.字符串转bytes类型 目录 Python网络编程02 /基于TCP.UDP协议的socket简单的通信.字符串转bytes ...

  9. socket 网络编程高速入门(一)教你编写基于UDP/TCP的服务(client)通信

    由于UNIX和Win的socket大同小异,为了方便和大众化,这里先介绍Winsock编程. socket 网络编程的难点在入门的时候就是对基本函数的了解和使用,由于这些函数的结构往往比較复杂,參数大 ...

随机推荐

  1. MongoDB的基础知识

    本人只是软件开发的一个菜鸟,在学习MongoDB,总结了一点自己学习的知识,监督自己学习. 如果文章中有不足的地方,还请大神指点迷津,纠正改错,谢谢. 一.MongoDB简介 MongoDB是一个基于 ...

  2. nagios二次开发(六)---nagiosql原理及主要文件的介绍

    nagiosql的入口文件:index.php,这也是所有php程序的入口文件.是由apache指定的. index.php 文件的开始引入了 require("functions/prep ...

  3. 学习制作第一个 openfire 插件

    本文地址:http://www.cnblogs.com/jying/p/3683409.html 蛋疼的自学路~~~ 开始想法是修改openfire源码,但修改后发现不好测试,不会发布,不会使用,各种 ...

  4. js手机号码和电话号码验证正则表达式

    /******************** 函数名称:IsTelephone 函数功能:固话,手机号码检查函数,合法返回true,反之,返回false 函数参数:obj,待检查的号码 检查规则: (1 ...

  5. Windows服务二:测试新建的服务、调试Windows服务

    一.测试Windows服务 为了使Windows服务程序能够正常运行,我们需要像创建一般应用程序那样为它创建一个程序的入口点.像其他应用程序一样,Windows服务也是在Program.cs的Main ...

  6. mysql - join two derived tables

    select t1.uid from (select uid from table1) t1 inner join (select uid from table2) t2 where t1.uid=t ...

  7. java的Map及Map.Entry解析

    Map<K,V>是以键-值对存储的(key-value), 而Entry<K,V>是Map中的一个接口,Map.Entry<K,V>接口主要用于获取.比较 key和 ...

  8. 转:C# WinForm获取 当前执行程序路径的几种方法

    1.获取和设置当前目录的完全限定路径. string str = System.Environment.CurrentDirectory; Result: C:xxxxxx 2.获取启动了应用程序的可 ...

  9. json对象

    //数组var arr=[1,2,3,3];//json对象var obj={width:'200px',height:'200px',background:'green'}; alert(obj[' ...

  10. SAP 采购订单行项目中科目分配被隐藏,发现行项目设置中显示字段长度为0

    1.sm30 维护 视图 TCVIEW 修改对应字段的显示长度