标签:http服务器 高并发 oc 多线程 socket编程
在上一篇文章《iOS从零开始学习socket编程——HTTP1.0服务器端》中我们已经简单的接触了OC搭建的HTTP服务器。
(地址http://blog.csdn.net/abc649395594/article/details/45131373)
出于用户体验和鲁棒性考虑,这里把这个HTTP服务器改进成多线程的。
首先,AnsycSocket这个类是基于OC的Runloop实现的,Runloop实现了方法的异步调用但并不支持多线程。
在这里首先简单区分一下多线程和方法异步调用的区别。他们都可以避免线程的阻塞,只不过多线程是新开一个线程处理任务,处理完成之后通知主线程;而方法异步调用本质上还是在主线程里调用方法,只不过主线程并不会阻塞着等待方法的执行结果,而是继续执行原有的任务,直到方法执行完成之后才进行相应的处理。从某种意义上来说,socket编程并不总需要服务器支持多线程,因为新增一个线程本身也会增加CPU的负担,而他们的执行效果也基本类似。
然而,考虑一下这种情况,我们就应该发现多线程也有他必不可少的理由:假设用户上传一张图片并且请求对这个图片进行处理,假设图片的处理非常复杂并且涉及到大量计算,此时如果任然在主线程中执行处理图片的方法,系统的执行效率会大幅度下降,用户体验变差。如果新增一个线程,那么多核处理器的处理优势将会被充分发挥,大大提高用户体验。
因此总结起来就是:我们并不需要为每一个新的socket连接新增一个线程,确应该在处理数据的时候,充分发挥多核处理器的优势,新增线程,提高执行速度。
也正因为如此,AnsycSocket本身的回调函数是异步调用,并不支持多线程,如果在子线程中调用AnsycSocket类对象的writeData方法(向socket中写入数据)将不会起任何作用。解决方法是,将数据的处理放在新的线程,并在主线程中执行writeData方法和UI相关的改变。
重点需要修改的函数是didReadData方法:
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
//处理数据
}
我们只用将这个方法进行简单地修改就可以支持多线程处理数据。
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
__block AsyncSocket *localSocket = sock;
__block NSData *localData = data;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"thread = %@",[NSThread currentThread]);
[self dealWithData:localSocket Data:localData];
});
}
这里创建了三个block类型的对象避免在block中出现循环引用的问题。
接下来实现dealWithData方法:
- (void)dealWithData:(AsyncSocket *)sock Data:(NSData *)data{
//这个方法和AnsycSocket的didReadData方法极为类似
/*
处理相关数据
*/
dispatch_async(dispatch_get_main_queue(), ^{
[sock writeData:data withTimeout:-1 tag:ECHO_MSG];
[sock disconnectAfterWriting];
});
}
可以看出,只是简单的新增了一个线程并且把原来需要在didReadData方法中实现的内容搬到了自定义的函数中。处理完成数据后,记得在主线程中写入数据即可。
PS:didReadData可能会出现无法获取数据或多次获取数据的问题。处理方法见我的另一篇博客《AsyncSocket didReadData函数详解》
地址:http://blog.csdn.net/abc649395594/article/details/45046871
最后唠叨一句:OC并不适合做服务区开发,这里写了很多只是为了加深对Socket编程本质的理解。
标签:http服务器 高并发 oc 多线程 socket编程
原文地址:http://blog.csdn.net/abc649395594/article/details/45154055