Socket 网络编程
1.TCP/IP、UDP
TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议。是一个工业标准的协议集,它是为广域网(WANs)设计的。
UDP(User Data Protocol,用户数据报协议)是与TCP相相应的协议。它是属于TCP/IP协议族中的一种。
以下这张图。表明了这些协议的关系。如图TCP/IP协议族包含运输层、网络层、链路层:
2.Socket
在图1中,我们没有看到Socket的影子,那么它究竟在哪里呢?还是用图来说话,一目了然。
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中。Socket事实上就是一个门面模式。它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说。一组简单的接口就是所有,让Socket去组织数据。以符合指定的协议。
3.使用socket
前人已经给我们做了好多的事了,网络间的通信也就简单了很多,但毕竟还是有挺多工作要做的。
曾经听到Socket编程,认为它是比較高深的编程知识,可是仅仅要弄清Socket编程的工作原理,神奇的面纱也就揭开了。
一个生活中的场景。
你要打电话给一个朋友。先拨号,朋友听到电话铃声后提起电话,这时你和你的朋友就建立起了连接,就能够讲话了。等交流结束,挂断电话结束此次交谈。
生活中的场景就解释了这工作原理。或许TCP/IP协议族就是诞生于生活中。这也不一定。
4.代码演示样例
#import "ViewController.h"
#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>
@interface ViewController ()
// client socket
@property (nonatomic, assign) int clientSocket;
@property (nonatomic, weak) IBOutlet UIWebView *myWebView;
@end
@implementation ViewController
/**
======= 请求头 =======
1> 请求行
GET / HTTP/1.1
GET 表示从server"拿"数据
/ 訪问server的根文件夹
HTTP/1.1 HTTP的协议以及版本号
2> 请求头
Host: 要訪问的主机
User-Agent: 用户代理,告诉serverclient的类型
Accept: 告诉serverclient支持的数据格式
Accept-Language: 告诉serverclient支持的语言
Accept-Encoding: 告诉serverclient支持的解压缩类型
HTTP请求本身的格式,是字符串格式的。最末一行,以 \n\n 结束,表示所有请求的内容发送完成,server能够处理!
提示:key 值是 HTTP 协议定义的,不能任意更改!
==========响应 ===========
1> 状态行
HTTP/1.1 200 OK
HTTP/1.1 HTTP的协议以及版本号
200 状态码(404)
2XX 成功
4XX client错误
5XX server错误
2> 响应头,server告诉client的一些信息
提示:响应的信息,通常在开发“下载”功能时,才会使用,平时用不着
Date: 响应日期
Server: server的信息
// 文件长度
Content-Length: 24
3> 数据实体。从server返回的二进制数据!
println("hello world!");
*/
- (void)viewDidLoad
{
[super viewDidLoad];
// http 端口是 80
if ([self connectToHost:@"61.135.169.125" port:80])
{
NSLog(@"连接成功");
}
// 发送消息给 web server
// 建立请求字符串
NSString *request = @"GET / HTTP/1.1\n"
"Host: www.baidu.com\n"
"User-Agent: iPhone AppleWebKit\n\n";
// 对结果的处理
NSString *result = [self sendAndRecv:request];
// 找 \r\n 的出现的位置
NSRange range = [result rangeOfString:@"\r\n\r\n"];
// 推断是否找到
if (range.location == NSNotFound)
{
NSLog(@"html 错误");
return;
}
NSString *html = [result substringFromIndex:range.location];
[self.myWebView loadHTMLString:html baseURL:[NSURL URLWithString:@"http://www.baidu.com"]];
}
- (BOOL)connectToHost:(NSString *)host port:(int)port
{
// 1. socket
/**
參数
domain: 协议域,AF_INET
type: Socket 类型,SOCK_STREAM(流 TCP)/SOCK_DGRAM(报文。提示:
在有些公司的程序猿给server发送数据,会说:发送报文)
protocol: IPPROTO_TCP。提示:假设输入0。会依据第二个參数。自己主动选择协议
返回值
socket 假设>0。就是正确的
*/
self.clientSocket = socket(AF_INET, SOCK_STREAM, 0);
// 2. 连接到另外一台计算机
/**
參数
1> clientsocket
2> 指向数据结构sockaddr的指针。当中包含目的端口和IP地址
C 语言中没有对象,实现都是通过结构体来实现的
3> 结构体数据长度
返回值
0 成功/其它 错误代号,非常多C语言的程序都会如此设计。原因:成功仅仅有一个。失败会有非常多种!
C 语言中,一般是非零即真
*/
struct sockaddr_in serverAddress;
// 1> 地址 inet_addr 能够将 ip 地址转换成整数
// 提示:在网络上的使用的非常多数据,须要做字节翻转
serverAddress.sin_addr.s_addr = inet_addr(host.UTF8String);
// 2> 端口 htons 能够将端口转换成整数
// 端口号相同要做字节翻转
serverAddress.sin_port = htons(port);
// 3> 协议
serverAddress.sin_family = AF_INET;
// 在 C 语言中。通常传递结构体的指针同一时候,会传递结构体的尺寸
int result = connect(self.clientSocket, (const struct sockaddr *)&serverAddress, sizeof(serverAddress));
return (result == 0);
}
/**
* 发送&接收消息
*/
- (NSString *)sendAndRecv:(NSString *)msg {
// 3. 发送数据给server
/**
參数
1> clientsocket
2> 发送内容地址
3> 发送内容长度
4> 发送方式标志,一般为0
返回值
假设成功,则返回发送的字节数,失败则返回SOCKET_ERROR
提示:在非常多C语言框架中,会将基本数据类型进行封装。使用的时候,便于兴许框架的调整
*/
// 在 UTF8 编码中。一个中文相应 3 个字节
ssize_t sendLen = send(self.clientSocket, msg.UTF8String, strlen(msg.UTF8String), 0);
// 4. 从server接收数据
uint8_t buffer[1024];
// 1> 定义一个可变的二进制数据,方便拼劲
NSMutableData *dataM = [NSMutableData data];
// server返回的回车计数
int count = 0;
while (count == 0)
{
// 2> 接收数据
ssize_t recvLen = recv(self.clientSocket, buffer, sizeof(buffer), 0);
[dataM appendBytes:buffer length:recvLen];
// 通过跟踪,\r\n\r\n 须要继续等待,\r\n 表示传输结束
// 取末尾一个字节
uint8_t lastByte = buffer[recvLen - 1];
// 取倒数第三个字节
uint8_t preLastByte = buffer[recvLen - 3];
if (lastByte == '\n' && preLastByte != '\n') {
count++;
}
}
return [[NSString alloc] initWithData:dataM encoding:NSUTF8StringEncoding];
}
/**
* 断开连接
*/
- (void)disconnect {
// 5. 关闭连接
close(self.clientSocket);
}
@end
5. 延伸阅读
1.Linux socket 编程:
http://www.ibm.com/developerworks/cn/education/linux/l-sock/l-sock.html
2. 网络编程学习笔记一:Socket编程:
http://blog.csdn.net/gneveek/article/details/8699198