AsyncSocket
这个开源网络连接库用起来很简单,很方便
对于客户端来说 思路很简单:
1,链接到目的地。
[socket connectToHost:@"www.baidu.com" onPort:80 error:nil];//tcp 协议
回调 - (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
2,设置读属性。
[socket readDataWithTimeout:-1 tag:3];
回调 - (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
3,向目的地发送消息。
[socket writeData:[[ self makeHttpHeader:@"www.baidu.com"] dataUsingEncoding:NSUTF8StringEncoding] withTimeout:1 tag:2];
回调 - (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag
简单的列出3个方法。更多的方法可以看原文件,每种方法都有tag值,方便区分和使用异步操作。
这里给出拼接http头的方法,忘记是那位高人写的了,方便测试。
#define HTTPMETHOD @"GET"
#define HTTPVERSION @"HTTP/1.1"
#define HTTPHOST @"Host"
#define KENTER @"\r\n"
#define KBLANK @" "
-(NSMutableString*)makeHttpHeader:(NSString*) hostName
{
NSMutableString *header = [[NSMutableString alloc] init];
[header appendFormat:HTTPMETHOD];
[header appendFormat:KBLANK];
[header appendFormat:@"/index.html"];
[header appendFormat:KBLANK];
[header appendFormat:HTTPVERSION];
[header appendFormat:KENTER];
[header appendFormat:HTTPHOST];
[header appendFormat:@":"];
[header appendFormat:@"%@",hostName];
[header appendFormat:KENTER];
[header appendFormat:KENTER];
return header;
}
BSD Socket
bsd socket 创建和使用的思路和 AsyncSocket 的使用思路大体一样的,稍微复杂些
1,创建socket
sockfd = socket(AF_INET, SOCK_STREAM, 0)) //传入参数和返回值转载了一片高手的文章,有介绍
2,链接目的地
connect(sockfd, (struct sockaddr*)&their_addr, sizeof(struct sockaddr));
其中参数如下:
struct sockaddr_in their_addr;
struct hostent *host = gethostbyname([hostName UTF8String]);
their_addr.sin_addr = *(struct in_addr*)(*(host->h_addr_list));
their_addr.sin_family = AF_INET;
their_addr.sin_port = htons(80);
bzero(&(their_addr.sin_zero), 8);
3,发送数据
send(sockfd, [data bytes], [data length], 0);
其中参数如下:
NSMutableString* httpContent = [self makeHttpHeader:@"www.baidu.com"];
NSData *data = [httpContent dataUsingEncoding:NSISOLatin1StringEncoding];
4,接受数据
recv(sockfd, readBuffer, sizeof(readBuffer);
其中参数如下:
char readBuffer[512];
while((br = recv(sockfd, readBuffer, sizeof(readBuffer), 0))>0)
CFSocket
ios 封装了 CFSocket,其使用方法和其他的socket思路差不多
1,创建socket
CFSocketContext socketContext;
bzero(&socketContext, sizeof(socketContext));
socketContext.info = self;
CFSocketRef _socket;
_socket = CFSocketCreate(kCFAllocatorDefault,
PF_INET,//协议族
SOCK_STREAM, //socket类型数据包
IPPROTO_TCP, //协议tcp
kCFSocketDataCallBack | kCFSocketConnectCallBack | kCFSocketReadCallBack,//回调类型
&_cfsocketCallback,//回调函数
&socketContext);
//必须加入消息循环队列,否则不能回调
CFRunLoopSourceRef listenSourceRef = CFSocketCreateRunLoopSource(kCFAllocatorDefault, _socket, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), listenSourceRef, kCFRunLoopCommonModes);
2,链接到目的地
CFSocketError error;
error = CFSocketConnectToAddress(_socket, _address, 5);//链接超时时间5秒
其参数如下:
struct hostent *host = gethostbyname([@"www.baidu.com" UTF8String]);
struct sockaddr_in newaddress;
newaddress.sin_family = AF_INET;
newaddress.sin_port = htons(80);
newaddress.sin_addr = *(struct in_addr *)*(host->h_addr_list);
CFDataRef _address = CFDataCreate(kCFAllocatorDefault, (void*)&newaddress, sizeof(struct sockaddr_in));
3,发送数据
error = CFSocketSendData(_socket, _address, (CFDataRef)[[ self makeHttpHeader:@"www.baidu.com"] dataUsingEncoding:NSUTF8StringEncoding], 20);
这里给出回调函数
void _cfsocketCallback(CFSocketRef inCFSocketRef, CFSocketCallBackType inType, CFDataRef inAddress, const void* inData, void* inContext )
{//回调函数
NSLog(@"inType==%d",(int)inType);
if (inData!=NULL) {
NSLog(@"inDataLength====%d",(int)CFDataGetLength(inData));
}
NSString * str = nil;
str = [[[NSString alloc] initWithData:inData encoding:NSISOLatin1StringEncoding] autorelease];
NSLog(@"%@,",str);
if(!inContext)
return;
switch(inType)
{
case kCFSocketDataCallBack:
//Incoming data will be read in chunks in the background and the callback is called with the data argument being a CFData object containing the read data.
NSLog(@"kCFSocketDataCallBack");
if (inData!=NULL)
{
int lenth = (int)CFDataGetLength(inData);
if (lenth == 0)
{// 连接断开
NSLog(@"连接断开");
}
else
{ //收到数据
NSLog(@"收到数据");
}
}
break;
case kCFSocketReadCallBack:
NSLog(@"kCFSocketReadCallBack");
// he callback is called when data is available to be read or a new connection is waiting to be accepted. The data is not automatically read; the callback must read the data itself.
break;
case kCFSocketAcceptCallBack:
{
NSLog(@"kCFSocketAcceptCallBack");
// New connections will be automatically accepted and the callback is called with the data argument being a pointer to a CFSocketNativeHandle of the child socket. This callback is usable only with listening sockets.
break;
}
case kCFSocketConnectCallBack:
NSLog(@"kCFSocketConnectCallBack");
//If a connection attempt is made in the background by calling CFSocketConnectToAddress or CFSocketCreateConnectedToSocketSignature with a negative timeout value, this callback type is made when the connect finishes
break;
default:
break;
}
}
CFStream
cfstream 分为两种read 和write
其实是创建输入输出流,然后进行读写,如下:
CFReadStreamRef readStream = NULL;
CFWriteStreamRef writeStream = NULL;
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
(CFStringRef)@"www.baidu.com",
80,
&readStream,
&writeStream);
CFReadStreamScheduleWithRunLoop(readStream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
CFWriteStreamScheduleWithRunLoop(writeStream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
CFStreamClientContext readclient ={0, NULL, NULL, NULL} ;
CFReadStreamSetClient(readStream, kCFStreamEventOpenCompleted|
kCFStreamEventHasBytesAvailable|
kCFStreamEventCanAcceptBytes|
kCFStreamEventErrorOccurred |
kCFStreamEventEndEncountered , &readCallBack, &readclient);
CFStreamClientContext writeclient = {0, NULL, NULL, NULL} ;
CFWriteStreamSetClient(writeStream, kCFStreamEventOpenCompleted|
kCFStreamEventHasBytesAvailable|
kCFStreamEventCanAcceptBytes|
kCFStreamEventErrorOccurred |
kCFStreamEventEndEncountered , &writeCallBack, &writeclient);
CFReadStreamOpen(readStream);
CFWriteStreamOpen(writeStream);
CFWriteStreamWrite(writeStream, [[[ self makeHttpHeader:@"www.baidu.com"] dataUsingEncoding:NSUTF8StringEncoding] bytes], 1024);
回调函数如下:
void readCallBack (CFReadStreamRef stream, CFStreamEventType eventType,void *clientCallBackInfo)
{
switch (eventType) {
case kCFStreamEventOpenCompleted:
NSLog(@"kCFStreamEventOpenCompleted");
break;
case kCFStreamEventHasBytesAvailable:
NSLog(@"kCFStreamEventHasBytesAvailable");
UInt8 buff[255];
CFReadStreamRead(stream, buff, 255);
NSLog(@"--%s",buff);
break;
case kCFStreamEventCanAcceptBytes:
NSLog(@"kCFStreamEventCanAcceptBytes");
break;
case kCFStreamEventErrorOccurred:
NSLog(@"kCFStreamEventErrorOccurred");
break;
case kCFStreamEventEndEncountered:
NSLog(@"kCFStreamEventEndEncountered");
break;
default:
break;
}
}
void writeCallBack( CFWriteStreamRef stream, CFStreamEventType eventType,void *clientCallBackInfo )
{
}
文档上给出句话,如下:CFWriteStream is “toll-free bridged” with its Cocoa Foundation counterpart, NSOutputStream.
其实 可以对应转换成NSOutputStream,和NSInputStream。
对于NSOutputStream,和NSInputStream 用气来比较简单,不介绍了
NSURLConnection
这个用起来会简单些,如下:
NSURLRequest * requese = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://wwww.baidu.com"]];
NSURLConnection * contion = [[NSURLConnection alloc] initWithRequest:requese delegate:self];
[contion start];
然后设置代理方法就可以了。
ASIHTTP
这个用的比较多,也简单。
其实对于网络链接,没有特殊的需求使用封装好的,还是要方便的多的。