iOS网络编程
来源:互联网 发布:php 提示非法字符串 编辑:程序博客网 时间:2024/06/07 23:03
没想到CSDN的两种编辑器不能进行同篇文章的切换!只能再整理一下了
1 . 使用CFNetwork
(精简模式)
定义一个
URL
使用NSRUL
创建一个url
使用
NSURLRequest
来创建一个请求,要将上层创建的URL
作为参数传递进去。如果用NSMutableURLRequest
来创建,可以修改其请求的参数创建一个
NSURLConnection
在方法中需要将请求作为参数传递,并添加代理为本身 如果连接不为空则为连接成功,否则,连接不成功。- 代理方法:
NSURLConnectionDelegate
,NSURLConnectionDataDelegate
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { // 可通过下面方法来得到编码方式/* NSLog(@"%@",[response textEncodingName]); // 返回编码名称*/}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data // 要在其中设置编码格式,将其进行转化/* NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingUTF8); NSString *str = [[NSString alloc] initWithData:data encoding:enc];*/
2 . 使用socket
方式来进行网络编程
iOS网络编程层次结构也分为三层:
- Cocoa层:
NSURL
,Bonjour
,Game Kit
,WebKit
- Core Foundation层:基于 C 的
CFNetwork
和CFNetServices
- OS层:基于 C 的
BSD socket
Cocoa层是最上层的基于 Objective-C 的 API,比如 URL
访问,NSStream
,Bonjour
,GameKit
等,这是大多数情况下我们常用的 API。Cocoa 层是基于 Core Foundation`实现的。
Core Foundation层:因为直接使用 socket
需要更多的编程工作,所以苹果对 OS 层的 socket
进行简单的封装以简化编程任务。该层提供了 CFNetwork
和 CFNetServices
,其中 CFNetwork
又是基于 CFStream
和 CFSocket
。
OS层:最底层的 BSD socket
提供了对网络编程最大程度的控制,但是编程工作也是最多的。因此,苹果建议我们使用 Core Foundation
及以上层的 API 进行编程。
本文将介绍如何在 iOS 系统下使用最底层的 socket
进行编程,这和在 window 系统下使用 C/C++ 进行 socket
编程并无多大区别。
BSD socket ARI
简介
接口详解:
- int socket(int addressFamily, int type, int protocol)
socket
创建并初始化socket
,返回该socket
的文件描述符,如果描述符为-1表示创建失败。
通常参数addressFamily
是IPv4(AF_INET)
或IPv6(AF_INET6)
。type
表示socket的类型,通常是流stream(SOCK_STREAM)
或数据报文 datagram(SOCK_DGRAM)
。 protocol
参数通常设置为0,以便让系统自动选择我们合适的协议(IPPROTO_TCP
),而对于datagram
来说会是UDP
协议(IPPROTO_UDP
)。
- int close(int socketFileDescriptor)
close关闭socket
- int bind(int socketFileDescriptor, sockaddr *addressToBind, int
addressStructLength)
将socket
与特定主机地址与端口号绑定,成功绑定返回0,失败返回-1.
成功绑定后,根据协议(TCP
/UDP
)的不同,我们可以对socket
进行不同的操作: UDP
:因为UDP
是无连接的,绑定之后就可以利用UPD socket
传送数据了。 TCP
:TCP
是需要建立端到端的连接的,为了建立TCP
连接服务器必须调用listen(int socketFileDescriptor, int backlogSize)
来设置服务器的缓冲区队列以接收客户端的连接请求,backlogSize
表示客户端连接请求缓冲区队列的大小。当调用listen设置之后,服务器等待客户端请求,然后调用下面的accept
来接受客户端的连接请求。
- int accept(int socketFileDescriptor, sockaddr *clientAddress, int
clientAddressSturctLength)
接受客户端连接请求并将客户端的网络地址信息保存到clientAddress
中。当客户端连接请求被服务器接受之后,客户端和服务器之间的链路就建立好了,两者就可以通信了。
- int connect(int socketFileDescriptor, sockaddr *serverAddress, int
serverAddressLength)
客户端向特定网络地址的服务器发送连接请求,连接成功返回0,失败返回-1.
当服务器建立好之后,客户端通过调用该接口向服务器发起建立连接请求,对于 UDP
来说,该接口是可选的,如果调用了该接口,表明设置了该UDP
socket
默认的网络地址。对TCP socket
来说这就是传说中三次握手建立连接发生的地方。
注意:该接口调用会阻塞当前线程直到服务器返回。
- hostent *gethostbyname(char *hostname)
其作用就是找到主机地址,将其作为远程主机地址传送给socketAddr
,作为连接参数的一部分。
使用DNS
查找特定主机名字对应的IP
地址。如果找不到对应的IP地址则返回NULL
。
- int send(int socketFileDescriptor, char *buffer, int bufferLength,
int flags)
通过socket
发送数据,发送成功返回成功发送的字节数,否则返回-1.
一旦连接建立好之后,就可以通过send
/receive
接口发送或接收数据了。注意调用connect
设置了默认网络地址的UDP
socket
也可以调用该接口来接收数据。
- int receive(int socketFileDescriptor, char *buffer, int bufferLength,
int flags)
从socket
中读取数据,读取成功返回成功读取的字节数,否则返回-1.
一旦连接建立好后,就可以通过send
/receive
接口发送或接收数据了。注意调用connect
设置了默认网络地址的UDP
socket
也可以调用该接口来发送数据。
- int sento(int socketFileDescriptor, char *buffer, int bufferLength,
int flags, sockaddr *destinationAddress, int
destinationAddressLength)
通过UDP socket
发送数据到特定的网络地址,发送成功返回成功发送的字节数,否则返回-1。
由于UDP
可以身多个网络地址发送数据,所以可以指定特定网络地址,以向其发送数据。
- int recvfrom(int socketFileDescriptor, char *buffer, int
bufferLength, int flags, sockaddr *fromAddress, int
*fromAddressLength)
从UDP socket
中读取数据,并保存发送者的网络地址信息,读取成功返回成功读取的字节数,否则返回-1。
由于UDP
可以接收来自多个网络地址的数据,所以需要提供额外的参数,以保存该数据的发送者身份。
服务器工作流程:
1> 服务器调用socket(…)
创建socket
;
2> 服务器调用listen(…)
设置缓存区;
3> 服务器通过accept(…)
接受客户端请求建立连接;
4> 服务器与客户端建立连接之后,就可以通过send(…)
/receive(…)
向客户端发送或从客户接收数据;
5> 服务器调用close
关闭socket
;
客户端工作流程:
1> 客户端调用socket(…)
创建socket
;
2> 客户端调用connect(…)
向服务器发起连接请求以建立连接;
3> 客户端与服务器建立连接之后,就可以通过send(…)
/receive(…)
向客户端发送或从客户端接收数据;
4> 客户端调用close
关闭socket
;
客户端实例:
1> 创建socket
获取文件描述符:
int socketFileDescriptor = socket(AF_INET, SOCK_STREAM, 0);
2> 获取远程主机的名称(需要注意 两个头文件#include <sys/socket.h> #include<netdb.h>
)
struct in_addr *remoteInAddr = (struct in_addr *)remoteHostEnt->h_addr_list[0];struct sockaddr_in socketParameters; // 套接字内部格式类型 socketParameters.sin_family = AF_INET; // socket internet family socketParameters.sin_addr = *remoteInAddr; // 远程网络地址 socketParameters.sin_port = htons([port intValue]); // 远程网络地址端口 htons的就是host to net short的意思,这个函数就是把以电脑上数据存储顺序的无符号短整型数转换成以网络上的数据存储顺序的短整型数
3> 与服务器进行socket
连接,需要传入socket
参数
int ret = connect(socketFileDescriptor, (struct sockaddr *) &socketParameters, sizeof(socketParameters));
4> 接收服务器发送来的数据 返回值大于0则表示为成功
int result = recv(socketFileDescriptor, &buffer, length, 0);
5> 关闭socket
close(socketFileDescriptor);
代码整体为:
NSString *host = [url host]; NSNumber *port = [url port];// 创建Socket // creat socket int socketFileDescriptor = socket(AF_INET, SOCK_STREAM, 0); if (socketFileDescriptor == -1) { NSLog(@"fail to create socket"); return; }// 获取远程主机的名称 // get ip address from host struct hostent *remoteHostEnt = gethostbyname([host UTF8String]); if (NULL == remoteHostEnt) { close(socketFileDescriptor); [self networkFailedWithErrorMessage:@":Unable to resolve the hostname of warehouse server."]; return; }// 取得远程主机的IP地址 struct in_addr *remoteInAddr = (struct in_addr *)remoteHostEnt->h_addr_list[0]; // set the socket parameters struct sockaddr_in socketParameters; // 套接字内部格式类型 socketParameters.sin_family = AF_INET; // socket internet family socketParameters.sin_addr = *remoteInAddr; // 远程网络地址 socketParameters.sin_port = htons([port intValue]); // 远程网络地址端口 htons的就是host to net short的意思,这个函数就是把以电脑上数据存储顺序的无符号短整型数转换成以网络上的数据存储顺序的短整型数// 与服务器进行socket连接 需要传入socket参数 // connect the socket sizeof(socketParameters)); int ret = connect(socketFileDescriptor, (struct sockaddr *) &socketParameters, sizeof(socketParameters)); if (-1 == ret) { close(socketFileDescriptor); NSString *errorInfo = [NSString stringWithFormat:@">> faile to connect to %@:%@",host,port]; [self networkFailedWithErrorMessage:errorInfo]; return; } NSLog(@">> Successfully connected to %@:%@", host, port); NSMutableData *data = [[NSMutableData alloc] init]; BOOL waitingForData = YES; // continually receive data until we reach the end of the data int maxCount = 5; int i = 0; while (waitingForData && i < maxCount ) { const char *buffer[1024]; int length = sizeof(buffer);//接收到服务器发送过来的数据 // read a buffer's amount of data from the socket; the number of bytes read is returned int result = recv(socketFileDescriptor, &buffer, length, 0); if (result > 0) { [data appendBytes:buffer length:length]; } else { waitingForData = NO; } ++i; }// 关闭Socket // Close the socket close(socketFileDescriptor); [self networkSucceedWithData:data];
- iOS网络编程总结
- iOS网络编程总结
- ios网络编程
- ios网络编程
- IOS网络编程
- ios网络编程
- IOS网络编程介绍
- ios网络编程
- ios 网络编程总结
- ios网络编程
- IOS 网络编程总结
- iOS 网络编程小结
- iOS网络编程总结
- iOS 网络编程摘要
- IOS网络编程:HTTP
- iOS网络编程
- iOS网络编程
- iOS网络编程
- iOS中的round/ceil/floorf函数略解
- equals函数
- Tomcat下配置数据库连接池
- iOS---限制UITextView中的字数
- 数据库之存储过程
- iOS网络编程
- memset和wmemset微软官网解释
- JAVA虚拟机之六:虚拟机性能监控和故障处理工具
- Html5添加移动触摸设备的在线签名和涂鸦插件教程
- WebView的一些属性
- 图像处理2 --图像形状
- swing 之FlowLayout 实现自动换行和滚动条添加
- Oracle的rollup、cube、grouping sets函数
- 浅析JVM及其调优(一)