网络通信的要素
- socket
- 通过socket来建立连接,然后通信
- IP -- Internet Protocol
- 网络上主机设备的唯一标识
- 端口号
- 不同进程的标识
- 传输协议
- 通讯规则
Socket
- 套接字
- 网络上的两个程序通过一个
双向的通信连接
实现数据的交换,这个连接的一端称为一个socket。 - 应用程序通常通过"套接字"向网络发出请求或者应答网络请求
传输协议
常用的传输协议有TCP和UDP
-
TCP-Transmission Control Protocol:(传输控制协议)
- 建立连接,形成数据传输的通道
- 可以进行大数据的传输,传输数据大小不受限制
- 通过
三次握手
完成连接,是可靠
协议,安全的,但同时也是效率低
的
-
UDP-User Datagram Protocol:(用户数据协议)
- 将数据以及源和目的封装成数据包,不需要建立连接
- 数据包大小限制在64K之内
- 因为无需连接,所以是
不可靠
的数据传输协议,但是,速度快
TCP/IP协议
- TCP/IP是个协议组,可分为三个层次:网络层、传输层和应用层。
- 在网络层有IP协议、ICMP协议、ARP协议、RARP协议和BOOTP协议。
- 在传输层中有TCP协议与UDP协议。
- 在应用层有:
- TCP包括FTP、HTTP、TELNET、SMTP等协议
- UDP包括DNS、TFTP等协议
短连接
- 连接->传输数据->关闭连接
- HTTP是无状态的,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接。
- 短连接是指SOCKET连接后发送后
接收完
数据后马上断开连接。
长连接
- 连接->传输数据->保持连接 -> 传输数据-> 。。。 ->关闭连接。
- 长连接指建立SOCKET连接后不管是否使用都
保持连接
,但安全性较差。
HTTP协议
-
数据内容
格式
协议 - 通常,由HTTP客户端
发起
一个请求,建立
一个到服务器指定端口(默认是[80端口])的TCP
连接。HTTP服务器则在那个端口监听
客户端发送过来的请求。一旦收到请求,服务器(向客户端)发回一个状态行,比如"HTTP/1.1 200 OK",和(响应的)消息,消息的消息体可能是请求的文件、错误消息、或者其它一些信息。 - 为什么HTTP使用TCP协议
- 1.保证数据的可靠
- 2.服务器的连接是有限的,所以需要断开连接
- 3.一个网页必须传送很多数据,而TCP协议提供传输控制,按顺序组织数据,和错误纠正
- �HTTP格式:请求头+请求体
- 请求头:
- Content-Type
- Content-Length
- Accept-Language
- 请求体:请求参数
- 请求头:
Socket 流程
代码模拟实现,这里使用第三方框架CocoaAsyncSocket
- 创建socket对象,并监听
// 创建服务监听对象
ServerListener *listener = [[ServerListener alloc] init];
// 开启监听
[listener start];
// 开启主运行循环来保证服务不被停止
[[NSRunLoop currentRunLoop] run];
#import "ServerListener.h"
#import "GCDAsyncSocket.h"
@interface ServerListener ()<GCDAsyncSocketDelegate>
/** socket*/
@property (nonatomic, strong) GCDAsyncSocket *socket;
@end
@implementation ServerListener
-(void)start {
// 1.创建socket对象
GCDAsyncSocket *socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)];
self.socket = socket;
NSLog(@"%@",socket);
// 2.绑定端口,端口号最好是1024以上
NSError *error = nil;
[socket acceptOnPort:5288 error:&error];
if (error) {
NSLog(@"服务开启失败,有错误:\n%@",error);
} else {
NSLog(@"服务开启成功");
}
}
@end
- 实现代理方法
#pragma mark - GCDAsyncSocket Delegate
// 有新客户端连接时调用
-(void)socket:(GCDAsyncSocket *)serverSocket didAcceptNewSocket:(GCDAsyncSocket *)clientSocket
{
// 保存客户端socket,不然会断开连接
[self.clientSockets addObject:clientSocket];
#warning 客户端连接成功后,监听数据,接收和读取数据都是使用clientSocket
// 读取数据
[clientSocket readDataWithTimeout:-1 tag:0];
}
// read()--读取客户端的数据
-(void)socket:(GCDAsyncSocket *)clientSocket didReadData:(NSData *)data withTag:(long)tag
{
NSLog(@"clientSocket: HOST:%@ PORT:%@",clientSocket.connectedHost,@(clientSocket.connectedPort));
NSString *dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"----\n%@",dataStr);
// 服务器响应
NSString *sendStr = @"我(服务器)收到了!!!\n";
NSData *sendData = [sendStr dataUsingEncoding:NSUTF8StringEncoding];
[clientSocket writeData:sendData withTimeout:-1 tag:0];
// 每次读取完数据后,还得监听数据
[clientSocket readDataWithTimeout:-1 tag:0];
}
// write()--数据发送成功
-(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag {
NSLog(@"%s",__func__);
}