iOS - AsyncSocket 的使用
1、AsyncSocket
基于 CFSocket、GCD 进行的封装(OC)。
支持 TCP 和 UDP。
完整的回调函数(用于处理各种回调事件,连接成功,断开连接,收到数据等)。
需要注意的问题:
- 1、Socekt 连接成功回调方法中主动调用:
[self.socket readDataWithTimeout:-1 tag:0];
,相当于主动添加一个读取请求,不然不会执行读取信息回调方法。 - 2、读取信息回调方法中,读取完信息后,主动调用一下
[self.socket readDataWithTimeout:-1 tag:0];
,读取完信息后,重新向队列中添加一个读取请求,不然当收到信息后不会执行读取回调方法。
- 1、Socekt 连接成功回调方法中主动调用:
2、基本使用
2.1 Client 客户端
TCP 客户端
#import "GCDAsyncSocket.h" @interface ViewController () <GCDAsyncSocketDelegate> @property (weak, nonatomic) IBOutlet UITextField *addrTF;
@property (weak, nonatomic) IBOutlet UITextField *portTF; @property (weak, nonatomic) IBOutlet UITextField *msgTF;
@property (weak, nonatomic) IBOutlet UITextView *logTV; @property (nonatomic, strong) GCDAsyncSocket *clientSockfd; @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad]; // 创建 Socket,在主队列中处理,所有的回执都在主队列中执行。
self.clientSockfd = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
} - (IBAction)connectBtnClick:(id)sender { NSError *error = nil; // Socket 连接
if (![self.clientSockfd isConnected]) {
[self.clientSockfd connectToHost:_addrTF.text onPort:_portTF.text.intValue error:&error];
} if (error != nil) {
[self showLogMessage:@"连接失败..."];
}
} #pragma mark - GCDAsyncSocketDelegate 协议方法 // 连接成功,协议方法
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port { // 读取数据,必须添加,相当于主动添加一个读取请求,不然不会执行读取信息回调方法
[self.clientSockfd readDataWithTimeout:-1 tag:0]; [self showLogMessage:[NSString stringWithFormat:@"连接服务器地址:%@, 端口:%d 成功", host, port]];
[self showLogMessage:[NSString stringWithFormat:@"本地地址:%@, 端口:%d", sock.localHost, sock.localPort]];
} // 已经断开链接,协议方法
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err { [self showLogMessage:@"socket 断开连接..."];
} // 读取到数据,协议方法
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag { // 注意:要想长连接,必须还要在 DidReceiveData 的 delegate 中再写一次 [_udpSocket receiveOnce:&error] // 读取数据,读取完信息后,重新向队列中添加一个读取请求,不然当收到信息后不会执行读取回调方法。
[self.clientSockfd readDataWithTimeout:-1 tag:0]; NSString *strMsg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
[self showLogMessage:[NSString stringWithFormat:@"recv:%@", strMsg]];
} #pragma mark - 发送数据 - (IBAction)sendBtnClick:(id)sender { // Socket 发送数据
[self.clientSockfd writeData:[_msgTF.text dataUsingEncoding:NSUTF8StringEncoding] withTimeout:30 tag:0]; [self showLogMessage:[NSString stringWithFormat:@"send:%@", _msgTF.text]];
} // 显示信息
- (void)showLogMessage:(NSString *)msg { _logTV.text = [_logTV.text stringByAppendingFormat:@"%@\n", msg];
} // 键盘回收
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self.view endEditing:YES];
} @end
2.2 Server 服务端
TCP 服务端
#import <arpa/inet.h>
#import <ifaddrs.h> #import "GCDAsyncSocket.h" @interface ViewController () <GCDAsyncSocketDelegate> @property (weak, nonatomic) IBOutlet UITextField *addrTF;
@property (weak, nonatomic) IBOutlet UITextField *portTF; @property (weak, nonatomic) IBOutlet UITextField *msgTF;
@property (weak, nonatomic) IBOutlet UITextView *logTV; @property (nonatomic, strong) GCDAsyncSocket *serverSocketfd;
@property (nonatomic, strong) GCDAsyncSocket *clientSocketfd; @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad]; NSString *ip_addr = [self getIPAddress];
_addrTF.text = ip_addr; // 创建 Socket,在主队列中处理,所有的回执都在主队列中执行。
self.serverSocketfd = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
} - (IBAction)listenBtnClick:(id)sender { NSError *error = nil; // Socket 监听
[self.serverSocketfd acceptOnPort:_portTF.text.intValue error:&error]; if (error != nil) {
NSLog(@"监听出错:%@", error);
} else{
[self showLogMessage:@"正在监听..."];
}
} #pragma mark - GCDAsyncSocketDelegate 协议方法 // 接收到连接请求,协议方法
- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket { // 读取数据,必须添加,相当于主动添加一个读取请求,不然不会执行读取信息回调方法
[newSocket readDataWithTimeout:-1 tag:0]; [self showLogMessage:@"收到客户端连接...."];
[self showLogMessage:[NSString stringWithFormat:@"客户端地址:%@, 端口:%d", newSocket.connectedHost, newSocket.connectedPort]]; self.clientSocketfd = newSocket;
} // 已经断开链接,协议方法
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err { [self showLogMessage:@"socket 断开连接..."];
} // 读取到数据,协议方法
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag { // 读取数据,读取完信息后,重新向队列中添加一个读取请求,不然当收到信息后不会执行读取回调方法。
[sock readDataWithTimeout:-1 tag:0]; NSString *strMsg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
[self showLogMessage:[NSString stringWithFormat:@"recv:%@",strMsg]];
} #pragma mark - 发送数据 - (IBAction)sendBtnClick:(id)sender { // Socket 发送数据
[self.clientSocketfd writeData:[_msgTF.text dataUsingEncoding:NSUTF8StringEncoding] withTimeout:30 tag:0]; [self showLogMessage:[NSString stringWithFormat:@"send:%@", _msgTF.text]];
} #pragma mark - 获取本地 IP 地址 - (NSString *)getIPAddress { NSString *address = @"error";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0; // retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces); if (success == 0) { // Loop through linked list of interfaces
temp_addr = interfaces; while (temp_addr != NULL) { if (temp_addr->ifa_addr->sa_family == AF_INET) { // Check if interface is en0 which is the wifi connection on the iPhone
if ([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) { // Get NSString from C String
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
}
}
temp_addr = temp_addr->ifa_next;
}
} // Free memory
freeifaddrs(interfaces);
return address;
} // 显示信息
- (void)showLogMessage:(NSString *)msg { _logTV.text = [_logTV.text stringByAppendingFormat:@"%@\n", msg];
} // 键盘回收
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self.view endEditing:YES];
} @end
2.3 UDP 通信
UDP 通信
#import <arpa/inet.h>
#import <ifaddrs.h> #import "GCDAsyncUdpSocket.h" @interface ViewController () <GCDAsyncUdpSocketDelegate> @property (weak, nonatomic) IBOutlet UITextField *desAddrTF;
@property (weak, nonatomic) IBOutlet UITextField *desPortTF; @property (weak, nonatomic) IBOutlet UITextField *locAddrTF;
@property (weak, nonatomic) IBOutlet UITextField *locPortTF; @property (weak, nonatomic) IBOutlet UITextField *msgTF;
@property (weak, nonatomic) IBOutlet UITextView *logTV; @property (nonatomic, strong) GCDAsyncUdpSocket *udpSocketfd; @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad]; NSString *ip_addr = [self getIPAddress];
_locAddrTF.text = ip_addr; // 创建 Socket,在主队列中处理,所有的回执都在主队列中执行
self.udpSocketfd = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
} - (IBAction)connectBtnClick:(id)sender { NSError *error = nil; // 绑定端口
[self.udpSocketfd bindToPort:_locPortTF.text.intValue error:&error]; if (error != nil) {
NSLog(@"绑定端口出错:%@", error);
return;
} else{
[self showLogMessage:[NSString stringWithFormat:@"绑定端口 %d 成功...", _locPortTF.text.intValue]];
} // 开始接收数据
[self.udpSocketfd beginReceiving:&error]; if (error != nil) {
NSLog(@"开始接收数据出错:%@", error);
} else{
[self showLogMessage:@"开始接收数据..."];
}
} #pragma mark - GCDAsyncUdpSocketDelegate 协议方法 // 接收到的数据,协议方法
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
fromAddress:(NSData *)address
withFilterContext:(id)filterContext { NSString *strMsg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; [self showLogMessage:[NSString stringWithFormat:@"recv:%@", strMsg]];
} #pragma mark - 发送数据 - (IBAction)sendBtnClick:(id)sender { // Socket 发送数据
[self.udpSocketfd sendData:[_msgTF.text dataUsingEncoding:NSUTF8StringEncoding]
toHost:_desAddrTF.text
port:_desPortTF.text.intValue
withTimeout:30 tag:0]; [self showLogMessage:[NSString stringWithFormat:@"send:%@", _msgTF.text]];
} #pragma mark - 获取本地 IP 地址 - (NSString *)getIPAddress { NSString *address = @"error";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0; // retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces); if (success == 0) { // Loop through linked list of interfaces
temp_addr = interfaces; while (temp_addr != NULL) { if (temp_addr->ifa_addr->sa_family == AF_INET) { // Check if interface is en0 which is the wifi connection on the iPhone
if ([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) { // Get NSString from C String
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
}
}
temp_addr = temp_addr->ifa_next;
}
} // Free memory
freeifaddrs(interfaces);
return address;
} // 显示信息
- (void)showLogMessage:(NSString *)msg { _logTV.text = [_logTV.text stringByAppendingFormat:@"%@\n", msg];
} // 键盘回收
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self.view endEditing:YES];
} @end
2.4 Socket 长连接
PublicTool.h
@interface PublicTool : NSObject // 字典转换成 JSON 字符串
+ (NSString *)JSONStringWithDic:(NSDictionary *)dic; // JSON 字符串转换成字典
+ (NSDictionary *)dictionaryWithJSON:(NSString *)json; @end
PublicTool.m
@implementation PublicTool // 字典转成成 JSON 字符串
+ (NSString *)JSONStringWithDic:(NSDictionary *)dic { NSError *error = nil; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dic
options:0
error:&error]; if (jsonData == nil) {
NSLog(@"fail to get JSON from dictionary: %@, error: %@", self, error); return nil;
}
NSString *jsonString = [[NSString alloc] initWithData:jsonData
encoding:NSUTF8StringEncoding]; return jsonString;
} // JSON 字符串转换成字典
+ (NSDictionary *)dictionaryWithJSON:(NSString *)json { NSError *error = nil; NSData *jsonData = [json dataUsingEncoding:NSUTF8StringEncoding]; NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingMutableContainers |
NSJSONReadingAllowFragments
error:&error]; if (jsonDict == nil) {
NSLog(@"fail to get dictioanry from JSON: %@, error: %@", json, error); return nil;
} return jsonDict;
} @end
SocketSingleTon.h
@interface SocketSingleTon : NSObject @property (nonatomic, copy) NSString *hostAddr;
@property (nonatomic, copy) NSString *port; @property (nonatomic, copy) void(^msgLog)(NSString *); + (instancetype)shareInstance; // 连接到服务器
- (void)connectToServer; // 断开连接
- (void)cutOffSocket; // 发送数据到服务器
- (void)sendDataToServer:(NSData*)data; @end
SocketSingleTon.m
#import "GCDAsyncSocket.h"
#import <netdb.h>
#import <arpa/inet.h> #import "PublicTool.h" typedef NS_ENUM(NSInteger, SocketOffline) {
SocketOfflineByServer,
SocketOfflineByUser
}; @interface SocketSingleTon () <GCDAsyncSocketDelegate> @property (nonatomic, strong) GCDAsyncSocket *socket; @property (nonatomic, strong) NSTimer *beatTimer; @end @implementation SocketSingleTon + (instancetype)shareInstance { static SocketSingleTon *shareInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
shareInstance = [[self alloc] init];
});
return shareInstance;
} // 连接到服务器
- (void)connectToServer { NSError *error = nil; if (self.socket != nil) { if ([self.socket isConnected]) { // 断开后再连接
self.socket.userData = @(SocketOfflineByUser);
[self cutOffSocket]; [self.socket connectToHost:self.hostAddr onPort:self.port.intValue error:&error]; } else { [self.socket connectToHost:self.hostAddr onPort:self.port.intValue error:&error];
} } else {
self.socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()]; [self.socket connectToHost:self.hostAddr onPort:self.port.intValue error:&error];
} if (error != nil) {
NSLog(@"socket 连接失败:%@", error);
} else {
NSLog(@"socket 连接成功");
}
} // 断开连接
- (void)cutOffSocket { self.socket.userData = @(SocketOfflineByUser);
[self.socket disconnect];
} #pragma mark - GCDAsyncSocketDelegate 协议方法 // 连接成功,协议方法
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port { [sock readDataWithTimeout:-1 tag:0]; NSString *logStr = [NSString stringWithFormat:@"连接主机:%@:%d 成功\n", host, port];
NSLog(@"%@", logStr); if (self.msgLog) {
self.msgLog(logStr);
} // 创建定时器,定时发送 beat 包
self.beatTimer = [NSTimer scheduledTimerWithTimeInterval:5
target:self
selector:@selector(longConnectToServer)
userInfo:nil
repeats:YES];
} // 连接断开,协议方法
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err { self.socket = nil; [self.beatTimer invalidate];
self.beatTimer = nil; if ([sock.userData isEqual: @(SocketOfflineByUser)]) { NSLog(@"the socket have been cutted off by user"); if (self.msgLog) {
self.msgLog(@"the socket have been cutted off by user");
} } else if (sock.userData == SocketOfflineByServer) { NSLog(@"the socket have been cutted off by server"); if (self.msgLog) {
self.msgLog(@"the socket have been cutted off by server");
} // reconnect
[self connectToServer]; } else { NSLog(@"%@", err.localizedDescription); if (self.msgLog) {
self.msgLog([NSString stringWithFormat:@"%@", err.localizedDescription]);
} [self connectToServer];
}
} // 收到消息,协议方法
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag { [sock readDataWithTimeout:-1 tag:0]; char buf[1024];
[data getBytes:buf length:1024]; NSString *receivedData = [NSString stringWithCString:buf encoding:NSUTF8StringEncoding];
NSLog(@"receivedData:%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); if (receivedData.length > 0) { NSDictionary *dataDic = [PublicTool dictionaryWithJSON:receivedData]; if ([dataDic[@"msgType"] isEqualToString:@"beta"]) {
NSString *strMsg = [NSString stringWithFormat:@"收到心跳确认的数据:%@\n", receivedData];
if (self.msgLog) {
self.msgLog(strMsg);
}
} else if ([dataDic[@"msgType"] isEqualToString:@"normal"]) {
NSString *strMsg = [NSString stringWithFormat:@"收到正常的数据:%@\n", receivedData];
if (self.msgLog) {
self.msgLog(strMsg);
}
} else if ([dataDic[@"msgType"] isEqualToString:@"exit"]) {
NSString *strMsg = [NSString stringWithFormat:@"收到关闭的数据:%@\n", receivedData];
if (self.msgLog) {
self.msgLog(strMsg);
}
[self cutOffSocket];
}
}
} // 发送数据
- (void)longConnectToServer {
[self sendDataToServer:[@"hello" dataUsingEncoding:NSUTF8StringEncoding]];
} // 发送数据到服务器
- (void)sendDataToServer:(NSData*)data { NSString *dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSMutableDictionary *dicParams = [NSMutableDictionary dictionary]; if ([dataStr isEqualToString:@"hello"]) {
[dicParams setValue:dataStr forKey:@"msg"];
[dicParams setValue:@"beta" forKey:@"msgType"];
} else {
[dicParams setValue:dataStr forKey:@"msg"];
[dicParams setValue:@"normal" forKey:@"msgType"];
} NSData *sendData = [[PublicTool JSONStringWithDic:dicParams] dataUsingEncoding:NSUTF8StringEncoding]; NSString *strMsg = [NSString stringWithFormat:@"发送数据: %@\n", [PublicTool JSONStringWithDic:dicParams]];
if (self.msgLog) {
self.msgLog(strMsg);
} [self.socket writeData:sendData withTimeout:30 tag:0];
} @end
ViewController.m
#import "SocketSingleTon.h"
#import "PublicTool.h" @interface ViewController () @property (weak, nonatomic) IBOutlet UITextField *addressTF;
@property (weak, nonatomic) IBOutlet UITextField *portTF; @property (weak, nonatomic) IBOutlet UITextField *msgTF;
@property (weak, nonatomic) IBOutlet UITextView *logTV; @end @implementation ViewController - (IBAction)connectToServer:(id)sender { // 创建 Socket
SocketSingleTon *socketInstance = [SocketSingleTon shareInstance]; socketInstance.hostAddr = _addressTF.text;
socketInstance.port = _portTF.text; __weak __typeof (self)weakSelf = self;
socketInstance.msgLog = ^(NSString *log){ dispatch_async(dispatch_get_main_queue(), ^{
weakSelf.logTV.text = [weakSelf.logTV.text stringByAppendingString:log];
});
}; // 连接到服务器
[socketInstance connectToServer];
} - (IBAction)cutOffConnect:(id)sender { SocketSingleTon *socketInstance = [SocketSingleTon shareInstance]; // 断开连接
[socketInstance cutOffSocket];
} - (IBAction)sendDataToServer:(id)sender { SocketSingleTon *socketInstance = [SocketSingleTon shareInstance]; // 发送数据到服务器
[socketInstance sendDataToServer:[_msgTF.text dataUsingEncoding:NSUTF8StringEncoding]];
} - (IBAction)sendBetaDataToServer:(id)sender { SocketSingleTon *socketInstance = [SocketSingleTon shareInstance]; NSMutableDictionary *dicParams = [NSMutableDictionary dictionary];
[dicParams setValue:@"beta" forKey:@"msgType"];
[dicParams setValue:@"hello" forKey:@"msg"];
NSString *strMsg = [PublicTool JSONStringWithDic:dicParams]; // 发送心跳数据到服务器
[socketInstance sendDataToServer:[strMsg dataUsingEncoding:NSUTF8StringEncoding]];
} - (IBAction)clearLog:(id)sender {
_logTV.text = nil;
} // 键盘回收
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self.view endEditing:YES];
} @end
iOS - AsyncSocket 的使用的更多相关文章
- IOS AsyncSocket
导入AsyncSocket.h AsyncSocket.m AsyncUdpSocket.h AsyncUdpSocket.m 以及 CFNetWork.framework async ...
- iOS开发之AsyncSocket使用教程
用socket可以实现像QQ那样发送即时消息的功能.客户端和服务端需要建立长连接,在长连接的情况下,发送消息.客户端可以发送心跳包来检测长连接. 在iOS开发中使用socket,一般都是用第三方库As ...
- iOS开发之即时通讯之Socket(AsyncSocket)
1.AsyncSocket介绍 如果需要在项目中像QQ微信一样做到即时通讯,必须使用socket通讯. iOS中Socket编程的方式: BSD Socket: BSD Socket 是UNIX系统中 ...
- iOS学习之Socket使用简明教程- AsyncSocket
转载自:http://my.oschina.net/joanfen/blog/287238 如果需要在项目中像QQ微信一样做到即时通讯,必须使用socket通讯,本人也是刚学习,分享一下,有什么不对的 ...
- IOS使用Asyncsocket进行socket编程
iphone的标准推荐CFNetwork C库编程.但是编程比较烦躁.在其它OS往往用类来封装的对Socket函数的处理.比如MFC的CAsysncSocket.在iphone也有类似于开源项目.co ...
- iOS socket编程 第三方库 AsyncSocket(GCDAsyncSocket)
Socket描述了一个IP.端口对.它简化了程序员的操作,知道对方的IP以及PORT就可以给对方发送消息,再由服务器端来处理发送的这些消息.所以,Socket一定包含了通信的双发,即客户端(Clien ...
- iOS Socket第三方开源类库 ----AsyncSocket
假如你也是一个java程序员,而你又不是很懂Socket. 下面我的这篇文章也许能帮助你一些. http://xiva.iteye.com/blog/993336 首先我们写好上面文章中的server ...
- iOS Socket第三方开源类库 ----AsyncSocket 分类: ios相关 ios技术 2015-03-11 22:14 59人阅读 评论(0) 收藏
假如你也是一个java程序员,而你又不是很懂Socket. 下面我的这篇文章也许能帮助你一些. http://xiva.iteye.com/blog/993336 首先我们写好上面文章中的server ...
- IOS socket编程--Asyncsocket
iPhone的标准推荐是CFNetwork 库编程,其封装好的开源库是 cocoa AsyncSocket库,用它来简化CFNetwork的调用,它提供了异步操作 主要特性有: 队列的非阻塞的读和写, ...
随机推荐
- 系统运维技巧(三)——利用dd命令临时增加交换分区
有时会遇到内存不够用的情况,可以使用本文提供的方法进行临时增加交换分区. #制作交换分区——得到文件 [root@serv01 linux-2.6.38]# dd if=/dev/zero of=/s ...
- 玩转OpenStack
一.OpenStack包含那些内容 1.预备知识 首先会有虚拟化和云计算的“预备知识”,会介绍 KVM,IaaS 等技术. 2.OpenStack核心 包含OpenStack的架构和和各个核心组件. ...
- SQL Server AlwaysOn Setup Step-By-Step Guide
Step-By-Step: Creating a SQL Server 2012 AlwaysOn Availability Group http://blogs.technet.com/b/cani ...
- Android常用http请求框架 简介及现状
JDK支持的HttpUrlConnection HttpUrlConnection是JDK里提供的联网API,是最原始最基本的API,大多数开源的联网框架基本上也是基于此进行的封装的.HttpUrlC ...
- 向量的表示及协方差矩阵 (PCA的理论基础)
原文:http://blog.csdn.net/songzitea/article/details/18219237 引言 当面对的数据被抽象为一组向量,那么有必要研究一些向量的数学性质.而这些数学性 ...
- Hyper-V如何应用新的网卡
最近新装了块网卡,可是在Hyper-V的虚拟机设置里怎么也找不到如何应用这个新网卡. 把我郁闷坏了. 偶尔点点,才发现原来不是在虚拟机的设置里面,而是在上面的一级设置. 新建完后就可以在虚拟机的网 ...
- 如何使用FLASHGOT下载网页FLASH
1 注意火狐的广告屏蔽插件可能将一些有用的东西屏蔽掉,从而无法得到广告FLASH, 2 随后即可在桌面上找到所需文件 你也可以按住A/T并单击FLASH文件(不论鼠标是否被替换为其他图形)迅雷会自动探 ...
- jQuery和CSS3超酷表单美化插件
这是一款效果很精美炫酷的jQuery和CSS3联系方式表单美化插件.大多数站点上都有让用户填写的联系方式表单,一个设计良好的表单可以大大的提升用户的体验度.该表单美化插件在原生HTML表单的基础上进 ...
- MVC 之 <%%>相关内联代码块用法
1.<%@ ... %> 添加引用; 2.<% ... %> <%%>之间可以执行服务端代码,如<% foreach (DataRow dataRow in ...
- Android网络:开发浏览器(二)——功能完善之书签功能
经过上述的编写,基本的功能已经完成了,不过工具栏里面基本还是一片空白,只有一个刷新的功能,现在咱们就先完善这些功能(之前有朋友说来点图,那么这次我会截些图更好的来描述). 既然是浏览器,怎么能没有书签 ...