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

在此,感谢大神博客   吴白 

          吴秦(Tyler)

          百度运维博文精选Https对性能的影响

          腾讯课堂某公开课