iOS开发教程Socket的原理和使用.doc_第1页
iOS开发教程Socket的原理和使用.doc_第2页
iOS开发教程Socket的原理和使用.doc_第3页
iOS开发教程Socket的原理和使用.doc_第4页
iOS开发教程Socket的原理和使用.doc_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

/iOS开发教程Socket的原理和使用1. iOS网络编程层次结构iOS网络编程层次结构分为三层,从上往下依次为:- Cocoa层:NSURL,Bonjour,Game Kit,WebKit- Core Foundation层:基于C 的CFNetwork 和CFNetServices- OS层:基于C 的BSD SocketCocoa层:是最上层的基于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 进行编程。2. 什么是SocketSocket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。2.1 TCP和UDP的区别TCP:面向连接、传输可靠(保证数据正确性,保证数据顺序)、用于传输大量数据(流模式)、速度慢,建立连接需要开销较多(时间,系统资源)。UDP:面向非连接、传输不可靠、用于传输少量数据(数据包模式)、速度快。关于TCP是一种流模式的协议,UDP是一种数据包模式的协议,这里要说明一下,TCP是面向连接的,也就是说,在连接持续的过程中,Socket中收到的数据都是由同一台主机发出的(劫持什么的不考虑),因此,知道保证数据是有序的到达就行了,至于每次读取多少数据自己看着办。而UDP是无连接的协议,也就是说,只要知道接收端的IP和端口,且网络是可达的,任何主机都可以向接收端发送数据。这时候,如果一次能读取超过一个报文的数据,则会乱套。比如,主机A向发送了报文P1,主机B发送了报文P2,如果能够读取超过一个报文的数据,那么就会将P1和P2的数据合并在了一起,这样的数据是没有意义的。2.2 常用的Socket类型有两种:流式Socket(SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。流式是一种面向连接的Socket,针对于面向连接的TCP服务应用;数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用。2.2.1 TCP C/S架构程序设计基本框架2.2.2 TCP 三次握手最形象理解:你瞅啥?瞅你咋地?来咱俩唠唠。然后就唠上了。2.2.3 TCP 四次挥手2.2.4基于TCP的套接字代码实现相关头文件。#include #include #include #include #include 服务端实现代码。- (void)socketServer int err; / 1. 创建socket套接字 / 原型:int socket(int domain, int type, int protocol); / domain:协议族type:socket类型protocol:协议 int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); BOOL success = (fd != -1); if (success) NSLog(Socket 创建成功); / 地址结构体 struct sockaddr_in addr; / 内存清空 memset(&addr, 0, sizeof(addr); / 内存大小 addr.sin_len=sizeof(addr); / 地址族,在socket编程中只能是AF_INET addr.sin_family=AF_INET; / 端口号 addr.sin_port=htons(1024); / 按照网络字节顺序存储IP地址 addr.sin_addr.s_addr=INADDR_ANY; / 2. 建立地址和套接字的联系(绑定) / 原型:bind(sockid, local addr, addrlen) err=bind(fd, (const struct sockaddr *)&addr, sizeof(addr); success=(err=0); / 3. 服务器端侦听客户端的请求 if (success) NSLog(绑定成功); / listen( Sockid ,quenlen) quenlen 并发队列 err=listen(fd, 5);/开始监听 success=(err=0); if (success) NSLog(监听成功); / 4. 一直阻塞等到客户端的连接 while (true) struct sockaddr_in peeraddr; int peerfd; socklen_t addrLen; addrLen = sizeof(peeraddr); NSLog(等待客户端的连接请求); / 5. 服务器端等待从编号为Sockid的Socket上接收客户端连接请求 / 原型:newsockid=accept(Sockid,Clientaddr, paddrlen) peerfd = accept(fd, (struct sockaddr *)&peeraddr, &addrLen); success=(peerfd!=-1); / 接收客户端请求成功 if (success) NSLog(接收客户端请求成功,客户端地址:%s, 端口号:%d,inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port); send(peerfd, 欢迎进入Socket聊天室, 1024, 0); / 6. 创建新线程接收客户端发送的消息 NSThread detachNewThreadSelector:selector(reciveMessage:) toTarget:self withObject:(peerfd); - (void)reciveMessage:(id) peerfd int fd = peerfd intValue; char buf1024; ssize_t bufLen; size_t len=sizeof(buf); / 循环阻塞接收客户端发送的消息 do bufLen = recv(fd, buf, len, 0); / 当返回值小于等于零时,表示socket异常或者socket关闭,退出循环阻塞接收消息 if (bufLen = 0) break; / 接收到的信息 NSString* msg = NSString stringWithCString:buf encoding:NSUTF8StringEncoding; NSLog(来自客户端,消息内容:%, msg); memset(buf, 0, sizeof(buf); while (true); / 7. 关闭 close(fd);客户端代码。- (void)createSocketClient int err; / 创建socket套接字 int fd =socket(AF_INET, SOCK_STREAM, 0); BOOL success=(fd!=-1); struct sockaddr_in addr; if (success) NSLog(Socket创建成功); memset(&addr, 0, sizeof(addr); addr.sin_len = sizeof(addr); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; / 建立地址和套接字的联系 err = bind(fd, (const struct sockaddr *)&addr, sizeof(addr); success = (err=0); if (success) struct sockaddr_in serveraddr; memset(&serveraddr, 0, sizeof(serveraddr); serveraddr.sin_len=sizeof(serveraddr); serveraddr.sin_family=AF_INET; / 服务器端口 serveraddr.sin_port=htons(1024); / 服务器的地址 serveraddr.sin_addr.s_addr=inet_addr(); socklen_t addrLen; addrLen =sizeof(serveraddr); NSLog(连接服务器中.); err=connect(fd, (struct sockaddr *)&serveraddr, addrLen); success=(err=0); if (success) / getsockname 是对tcp连接而言。套接字socket必须是已连接套接字描述符。 err =getsockname(fd, (struct sockaddr *)&addr, &addrLen); success=(err=0); if (success) NSLog(连接服务器成功,本地地址:%s,端口:%d,inet_ntoa(addr.sin_addr),ntohs(addr.sin_port); NSThread detachNewThreadSelector:selector(reciveMessage:) toTarget:self withObject:(fd); else NSLog(connect failed); - (void)reciveMessage:(id) peerfd int fd = peerfd intValue; char buf1024; ssize_t bufLen; size_t len=sizeof(buf); / 循环阻塞接收消息 do bufLen = recv(fd, buf, len, 0); / 当返回值小于等于零时,表示socket异常或者socket关闭,退出循环阻塞接收消息 if (bufLen = 0) break; / 接收到的信息 NSString* msg = NSString stringWithCString:buf encoding:NSUTF8StringEncoding; NSLog(来自服务端,消息内容:%, msg); while (true); / 7. 关闭 close(fd);2.2.5 UDP C/S架构程序设计基本框架2.2.6 字节顺序计算机数据表示存在两种字节顺序:NBO与HBO网络字节顺序NBO(Network Byte Order):按从高到低的顺序存储,在网络上使用统一的网络字节顺序,可以避免兼容性问题。主机字节顺序(HBO,Host Byte Order):不同的机器HBO不相同,与CPU设计有关,数据的顺序是由cpu决定的,而与操作系统无关。不同的CPU有不同的字节顺序类型,这些字节顺序类型指的是整数在内存中保存的顺序,即主机字节顺序。常见的有两种:英文名中文名描述big-endian大尾数顺序地址的低位存储值的高位little-endian小尾数顺序地址的低位存储值的低位如Intelx86结构下,short型数0x1234表示为34 12, int型数0x12345678表示为78 56 34 12如IBM power PC结构下,short型数0x1234表示为12 34, int型数0x12345678表示为12 34 56 78网络字节顺序与本地字节顺序之间的转换函数: htonl()-Host to Network Long ntohl()-Network to Host Long htons()-Host to Network Short ntohs()-Network to Host Short2.2.7 地址转换方法in_addr_t inet_addr(const char *)将一个点间隔地址转换成一个in_addrchar *inet_ntoa(struct in_addr)将网络地址转换成“.”点隔的字符串格式。int inet_aton(const char *, struct in_addr *)将一个字符串IP地址转换为一个32位的网络序列IP地址。2.2.8 获取地址- 用getsockname获得本地ip和port- 用getpeername获得对端ip和port套接字socket必须是已连接套接字描述符。2.2.9 获取本地IP地址参考stackoverflow链接:2.2.10 UPD套接字实现代码#include - (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

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论