Socket基础

ISO-OSI的七层协议经典架构


OSI(Open System interconnection)开放系统互连参考模型

 ISO(International Standards Organization)国际标准化组织

第一层:物理层

机械性能:接口的型状,尺寸的大小,引脚的数目和排列方式等。

电气性能:接口规定信号的电压、电流、阻抗、波形、速率及平衡特性等。

 工程规范:接口引脚的意义、特性、标准。

 工作方式:确定数据位流的传输方式,如:单工、半双工或全双工。

 物理层协议有:

 美国电子工业协会(EIA)的RS232,RS422,RS423,RS485等;

 国际电报电话咨询委员会(CCITT)的X.25、X.21等;

 物理层的数据单位是位(BIT),典型设备是集线器HUB。

这层主要和硬件有关,与软件关系不大。

第二层:链路层

 链路层屏蔽传输介质的物理特征,使数据可靠传送。

 内容包括介质访问控制、连接控制、顺序控制、流量控制、差错控制和仲裁协议等。

 链路层协议有:

 协议有面向字符的通讯协议(PPP)和面向位的通讯协议(HDLC)。

 仲裁协议:802.3、802.4、802.5,即:

 CSMA/CD(Carrier Sense Multiple Access with Collision Detection)、Token Bus、Token Ring

 链路层数据单位是帧,实现对MAC地址的访问,典型设备是交换机Switch。

第三层:网络层

网络层管理连接方式和路由选择。

连接方式:虚电路(Virtual Circuits)和数据报(Datagram)服务。

虚电路是面向连接的(Connection-Oriented),数据通讯一次路由,通过会话建立的一条通路。

数据报是非连接的(Connectionless-Oriented),每个数据报都有路由能力。

网络层的数据单位是包,使用的是IP地址,典型设备是路由器Router。

这一层可以进行流量控制,但流量控制更多的是使用第二层或第四层。

第四层:传输层

 提供端到端的服务。可以实现流量控制、负载均衡。

 传输层信息包含端口、控制字和校验和。

 传输层协议主要是TCP和UDP。

 传输层位于OSI的第四层,这层使用的设备是主机本身。 

第五层:会话层

 会话层主要内容是通过会话进行身份验证、会话管理和确定通讯方式。

 一旦建立连接,会话层的任务就是管理会话。

第六层:表示层

 表示层主要是解释通讯数据的意义,如代码转换、格式变换等,使不同的终端可以表示。

 还包括加密与解密、压缩与解压缩等。

第七层:应用层

 应用层应该是直接面向用户的程序或服务,包括系统程序和用户程序,

 例如www、FTP、DNS、POP3和SMTP等都是应用层服务。

 数据在发送时是数据从应用层至物理层的一个打包的过程,

 接收时是数据从物理层至应用层的一个解包的过程,

 从功能角度可分为三组,1、2层解决网络信道问题,3、4层解决传输问题,5、6、7层处理对应用进程的访问。

 从控制角度可分为二组,第1、2、3层是通信子网层,第4、5、6、7层是主机控制层。



TCP/IP


要想理解socket首先得熟悉一下TCP/IP协议族, TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,定义了主机如何连入因特网及数据如何再它们之间传输的标准,从字面意思来看TCP/IP是TCP和IP协议的合称,但实际上TCP/IP协议是指因特网整个TCP/IP协议族。不同于ISO模型的七个分层,TCP/IP协议参考模型把所有的TCP/IP系列协议归类到四个抽象层中

应用层:TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 等等

传输层:TCP,UDP

网络层:IP,ICMP,OSPF,EIGRP,IGMP

数据链路层:SLIP,CSLIP,PPP,MTU

每一抽象层建立在低一层提供的服务上,并且为高一层提供服务,看起来大概是这样子的

 http协议   对应于应用层 

 tcp协议    对应于传输层  

 ip协议     对应于网络层 

 三者本质上没有可比性。  何况HTTP协议是基于TCP连接的。 

 TCP/IP是传输层协议,主要解决数据如何在网络中传输;而HTTP是应用层协议,主要解决如何包装数据。

 我 们在传输数据时,可以只使用传输层(TCP/IP),但是那样的话,由于没有应用层,便无法识别数据内容,如果想要使传输的数据有意义,则必须使用应用层 协议,应用层协议很多,有HTTP、FTP、TELNET等等,也可以自己定义应用层协议。WEB使用HTTP作传输层协议,以封装HTTP文本信息,然 后使用TCP/IP做传输层协议将它发送到网络上。Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。


                          


在TCP/IP协议中两个因特网主机通过两个路由器和对应的层连接。各主机上的应用通过一些数据通道相互执行读取操作

   

tcp和udp的区别

在这里就必须讲一下udp和tcp的区别了

TCP:面向连接、传输可靠(保证数据正确性,保证数据顺序)、用于传输大量数据(流模式)、速度慢,建立连接需要开销较多(时间,系统资源)。

UDP:面向非连接、传输不可靠、用于传输少量数据(数据包模式)、速度快。

关于TCP是一种流模式的协议,UDP是一种数据报模式的协议,这里要说明一下,TCP是面向连接的,也就是说,在连接持续的过程中,socket中收到的数据都是由同一台主机发出的(劫持什么的不考虑),因此,知道保证数据是有序的到达就行了,至于每次读取多少数据自己看着办。

而UDP是无连接的协议,也就是说,只要知道接收端的IP和端口,且网络是可达的,任何主机都可以向接收端发送数据。这时候,如果一次能读取超过一个报文的数据,则会乱套。比如,主机A向发送了报文P1,主机B发送了报文P2,如果能够读取超过一个报文的数据,那么就会将P1和P2的数据合并在了一起,这样的数据是没有意义的。



TCP三次握手和四次挥手


相对于SOCKET开发者,TCP创建过程和连接拆除过程是由TCP/IP协议栈自动创建的。因此开发者并不需要控制这个过程。但是对于理解TCP底层运作机制,相当有帮助。

因此在这里详细解释一下这两个过程。

TCP三次握手

所谓三次握手(Three-way Handshake),是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。

 三次握手的目的是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号并交换 TCP 窗口大小信息.在socket编程中,客户端执行connect()时。将触发三次握手。 

首先了解一下几个标志,SYN(synchronous),同步标志,ACK (Acknowledgement),即确认标志,seq应该是Sequence Number,序列号的意思,另外还有四次握手的fin,应该是final,表示结束标志。

第一次握手:客户端发送一个TCP的SYN标志位置1的包指明客户打算连接的服务器的端口,以及初始序号X,保存在包头的序列号(Sequence Number)字段里。

第二次握手:服务器发回确认包(ACK)应答。即SYN标志位和ACK标志位均为1同时,将确认序号(Acknowledgement Number)设置为客户的序列号加1以,即X+1。

第三次握手:客户端再次发送确认包(ACK) SYN标志位为0,ACK标志位为1。并且把服务器发来ACK的序号字段+1,放在确定字段中发送给对方.并且在数据段放写序列号的+1。

tcp四次挥手

TCP的连接的拆除需要发送四个包,因此称为四次挥手(four-way handshake)。客户端或服务器均可主动发起挥手动作,在socket

编程中,任何一方执行close()操作即可产生挥手操作。 

其实有个问题,为什么连接的时候是三次握手,关闭的时候却是四次挥手?

因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,”你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。


HTTP连接

HTTP协议即超文本传送协议(HypertextTransfer Protocol ),是Web联网的基础,也是手机联网常用的协议之一,HTTP协议是建立在TCP协议之上的一种应用。

HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。

1)在HTTP 1.0中,客户端的每次请求都要求建立一次单独的连接,在处理完本次请求后,就自动释放连接。

2)在HTTP 1.1中则可以在一次连接中处理多个请求,并且多个请求可以重叠进行,不需要等待一个请求结束后再发送下一个请求。

由 于HTTP在每次请求结束后都会主动释放连接,因此HTTP连接是一种“短连接”,要保持客户端程序的在线状态,需要不断地向服务器发起连接请求。通常的 做法是即时不需要获得任何数据,客户端也保持每隔一段固定的时间向服务器发送一次“保持连接”的请求,服务器在收到该请求后对客户端进行回复,表明知道客 户端“在线”。若服务器长时间无法收到客户端的请求,则认为客户端“下线”,若客户端长时间无法收到服务器的回复,则认为网络已经断开。

  socket

我们知道两个进程如果需要进行通讯最基本的一个前提能能够唯一的标示一个进程,在本地进程通讯中我们可以使用PID来唯一标示一个进程,但PID只在本地唯一,网络中的两个进程PID冲突几率很大,这时候我们需要另辟它径了,我们知道IP层的ip地址可以唯一标示主机,而TCP层协议和端口号可以唯一标示主机的一个进程,这样我们可以利用ip地址+协议+端口号唯一标示网络中的一个进程。

能够唯一标示网络中的进程后,它们就可以利用socket进行通信了,什么是socket呢?我们经常把socket翻译为套接字,socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信


socket简介


首先让我们通过一张图知道socket在哪里?

 


我们知道两个进程如果需要进行通讯最基本的一个前提能能够唯一的标示一个进程,在本地进程通讯中我们可以使用PID来唯一标示一个进程,但PID只在本地唯一,网络中的两个进程PID冲突几率很大,这时候我们需要另辟它径了,我们知道IP层的ip地址可以唯一标示主机,而TCP层协议和端口号可以唯一标示主机的一个进程,这样我们可以利用ip地址+协议+端口号唯一标示网络中的一个进程。

能够唯一标示网络中的进程后,它们就可以利用socket进行通信了,什么是socket呢?我们经常把socket翻译为套接字,socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信


Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。

tcpsocket和udpsocket的具体实现

讲了这么久,终于要开始讲socket的具体实现了,iOS提供了Socket网络编程的接口CFSocket,不过这里使用BSD Socket。

tcp和udp的socket是有区别的,这里给出这两种的设计框架

基本TCP客户—服务器程序设计基本框架

 

基本UDP客户—服务器程序设计基本框架流程图

 




ios原生的socket用起来不是很直观,所以我用的是AsyncSocket这个第三方库,对socket的封装比较好,只是好像没有带外传输(out—of-band) 如果你的服务器需要发送带外数据,可能得想下别的办法


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当涉及到C++的Socket编程,一个常见的基础项目是创建一个简单的客户端和服务器之间的通信。下面是一个简单的示例,展示了如何使用C++的Socket库来实现这样一个项目: **服务器端代码:** ```cpp #include <iostream> #include <cstdlib> #include <cstring> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int main() { int serverSocket, clientSocket; struct sockaddr_in serverAddress, clientAddress; char buffer[1024]; // 创建服务器端socket serverSocket = socket(AF_INET, SOCK_STREAM, 0); if (serverSocket < 0) { std::cerr << "无法创建socket!" << std::endl; return 1; } // 绑定服务器地址和端口 serverAddress.sin_family = AF_INET; serverAddress.sin_port = htons(12345); // 设置端口号为12345 serverAddress.sin_addr.s_addr = INADDR_ANY; if (bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) < 0) { std::cerr << "绑定失败!" << std::endl; return 1; } // 监听连接请求 listen(serverSocket, 5); std::cout << "等待客户端连接..." << std::endl; // 接受客户端连接 socklen_t clientAddressLength = sizeof(clientAddress); clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddress, &clientAddressLength); // 接收和发送数据 while (true) { memset(buffer, 0, sizeof(buffer)); int bytesRead = read(clientSocket, buffer, sizeof(buffer)); if (bytesRead <= 0) { // 连接断开或出错 break; } std::cout << "收到消息:" << buffer << std::endl; // 回复客户端 std::string message = "已收到消息!"; write(clientSocket, message.c_str(), message.size()); } // 关闭socket close(clientSocket); close(serverSocket); return 0; } ``` **客户端代码:** ```cpp #include <iostream> #include <cstdlib> #include <cstring> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int main() { int clientSocket; struct sockaddr_in serverAddress; char buffer[1024]; // 创建客户端socket clientSocket = socket(AF_INET, SOCK_STREAM, 0); if (clientSocket < 0) { std::cerr << "无法创建socket!" << std::endl; return 1; } // 设置服务器地址和端口 serverAddress.sin_family = AF_INET; serverAddress.sin_port = htons(12345); // 设置服务器端口号为12345 serverAddress.sin_addr.s_addr = inet_addr("127.0.0.1"); // 设置服务器IP地址 // 连接服务器 if (connect(clientSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) < 0) { std::cerr << "连接失败!" << std::endl; return 1; } // 发送和接收数据 while (true) { std::string message; std::cout << "请输入消息:"; std::getline(std::cin, message); if (message == "exit") { // 输入"exit"表示结束通信 break; } // 发送消息 write(clientSocket, message.c_str(), message.size()); // 接收服务器回复 memset(buffer, 0, sizeof(buffer)); int bytesRead = read(clientSocket, buffer, sizeof(buffer)); if (bytesRead <= 0) { // 连接断开或出错 break; } std::cout << "收到回复:" << buffer << std::endl; } // 关闭socket close(clientSocket); return 0; } ``` 这个示例展示了基本的客户端和服务器之间的通信过程。服务器监听指定的端口,等待客户端连接。一旦有客户端连接成功,服务器会接收来自客户端的消息,并回复一个固定的消息。客户端首先创建一个socket并连接到服务器,然后可以发送消息给服务器并接收服务器的回复。 请注意,这只是一个简单的示例,没有包含错误处理和异常情况的处理。在实际开发中,您可能需要更全面和健壮的代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值