Socket:专业术语:套接字;通俗的解释:两孔插座(一个孔:IP地址,一个孔:端口号).使用场景:通信,如QQ好友交谈,如浏览器的进程怎么与web服务器通信等.
Socket来历:
socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。
其中,这些socket函数的介绍请看这里:吴秦(Tyler)Socket编程
在组网领域的首次使用是在1970年2月12日发布的文献IETF RFC33中发现的,撰写者为Stephen Carr、Steve Crocker和Vint Cerf。根据美国计算机历史博物馆的记载,Croker写道:"命名空间的元素都可称为套接字接口。一个套接字接口构成一个连接的一端,而一个连接可完全由一对套接字接口规定。”计算机历史博物馆补充道:"这比BSD的套接字接口定义早了大约12年。
通过上面,我们知道了socket(套接字)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元,多个TCP连接或多个应用程序进程可能需要通过同一个TCP协议端口传输数据。为了区别不同的应用程序进程和连接,计算机操作系统为应用程序与TCP/IP协议交互提供了套接字(Socket)接口。应用层可以和传输层通过Socket接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket,另一个运行于服务器端,称为ServerSocket。套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。Socket可以支持不同的传输层协议(TCP或UDP),当使用TCP协议进行连接时,该Socket连接就是一个TCP连接,UDP连接同理。
网络七层协议:
网络七层协议由下往上分别为物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。其中物理层、数据链路层和网络层通常被称作媒体层,是网络工程师所研究的对象;传输层、会话层、表示层和应用层则被称作主机层,是用户所面向和关心的内容。
HTTP协议对应于应用层,TCP协议对应于传输层,IP协议对应于网络层,HTTP协议是基于TCP连接的,三者本质上没有可比性。 TCP/IP是传输层协议,主要解决数据如何在网络中传输;而HTTP是应用层协议,主要解决如何包装数据。Socket是应用层与TCP/IP协议族通信的中间软件抽象层,是它的一组接口。
其图示如下:
而其中TCP,UDP协议的区别如下:
而,建立TCP连接需要经过"三次握手",断开连接需要"四次握手".这就是当初大学天天背诵而不知干嘛的"三次握手,四次分手"原则(至今也才懵懵懂懂).
Socket通信就是依靠这完成的,其中通讯示意图如:
以上就是一些基本的知识点,下面写一个小demo演示下:
// // ViewController.m // Socket入门 // // Created by Shaoting Zhou on 2017/4/17. // Copyright © 2017年 Shaoting Zhou. All rights reserved. // nc -lk 12345 监听12345端口 #import "ViewController.h" #import <sys/socket.h> #import <netinet/in.h> #import <arpa/inet.h> @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [self socketDemo]; } //MARK : Socket演练 - (void)socketDemo { //1.创建Socket /** 参数 domain: 协议域,AF_INET --> IPV4 type: Socket 类型,SOCK_STREAM(TCP)/SOCK_DGRAM(UDP) protocol: IPPROTO_TCP, 如果传入0,会自动更具第二个参数,选择合适的协议 返回值 socket */ int clientSocket = socket(AF_INET, SOCK_STREAM, 0); //2.连接到服务器 /** 参数 1> 客户端socket 2> 指向数据结构体sockaddr的指针,其中包括目的端口和IP地址 3> 结构体数据长度 返回值 0 成功/其他 错误代号 */ //结构体 sockaddr struct sockaddr_in serverAddr; //协议域 serverAddr.sin_family = AF_INET; //端口号 serverAddr.sin_port = htons(12345); //定义一个端口号演示 //IP地址 serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); int connResult = connect(clientSocket, (const struct sockaddr *)&serverAddr , sizeof(serverAddr)); //3.发送数据给服务器 /** C语言里面 Void * 代表指向任意类型 参数 1> 客户端socket 2> 发送内容地址(指针) 3> 发送内容长度 4> 发送方式标志,一般为0 返回值 如果成功,则返回发送的字节数,失败则返回SOCKET_ERROR */ NSString * sendMsg = @"shaoting"; //随意定义一个字符串演示 ssize_t sendLen = send(clientSocket, sendMsg.UTF8String, strlen(sendMsg.UTF8String), 0); NSLog(@"发送了 %ld 个字节",sendLen); //4.从服务器接收数据 /** 参数 1> 客户端socket 2> 接收内容缓冲区地址(指针) 3> 接收内容缓存区长度 4> 接收方式,0表示阻塞,必须等待服务器返回数据 返回值 如果成功,则返回读入的字节数,失败则返回SOCKET_ERROR */ uint8_t buffer[1024];//空间准备出来 ssize_t recvLen = recv(clientSocket, buffer, sizeof(buffer), 0); NSLog(@"接收到了 %ld 个字节",recvLen); //获取服务器返回的数据,从缓冲区读取recvLen个字节!!! NSData * data = [NSData dataWithBytes:buffer length:recvLen]; //二进制转字符串 NSString * str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@",str); //5.关闭 close(clientSocket); } @end
首先在终端运行 nc -lk 12345,监听着端口12345,启动Xcode项目,这时会连上本地服务器127.0.0.1,然后就会发送刚才准备的字符串(shaoting),然后还可以从服务器发个消息到客户端.演示效果如:
本文demo地址:https://github.com/pheromone/iOS-Scoket-
当然,大家应该还听说过XMPP协议,这个就是在Scoket基础上得来的.这个是当初学习XMPP的demo地址:https://github.com/pheromone/iOS-XMPPDemo
在此,感谢大神博客 吴白
腾讯课堂某公开课