socket,网络编程通信原理,TCP协议通信的实现方式。
TCP/IP协议,即传输控制协议/网间协议,定义了主机连接Internet以及数据如何传输的标准。
这里采用TCP/IP 四层模型是目前被广泛采用的一种模型,是OSI七层模型的精简版。
是由
1.应用层 TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 等等 2.传输层 TCP,UDP 3.网络层 IP,ICMP,OSPF,EIGRP,IGMP 4.网络接口层 SLIP,CSLIP,PPP,MTU
这是一种自底向上的模型,总是有下层向上层提供服务:
socket
在本地计算机中,我们可以利用PID对本机的每一个进程都进行唯一的标志,而在互联网中,每两台计算机的应用PID是有很大几率会产生冲突,因此为了对互联网中的应用有着唯一的标志,我们根据IP可以唯一标识一台主机,而TCP层协议和端口号可以唯一标识一个主机的一个进程,这样我们就可以通过IP地址+协议+端口号标识网络中的一个进程。
在能够唯一标识了网络中的应用后,socket就可以实现它们之间的相互通信通信。
socket就是我们常说的套接字,它是在传输层和应用层之间的一个抽象层,将TCP/IP层负责的操作抽象为了几个简单的借口提供应用层调用,从而实现了网络通信。
socket通信流程
socket是“打开——读/写——关闭”模式的实现,其中TCP协议通讯的socket的交互流程大概就是这样的:
建立socket连接至少需要一对套接字,其中一个运行于服务器,称之为ServerSocket,另一个是运行于客户端上的ClientSocket。
套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。(以下混合采用①来标记)
1 服务器根据地址类型(ipv4,ipv6)、socket类型,协议创建socket
# python
socket.socket(socket.AF_INET,socket.SOCK_STREAM)
2 服务器为socket绑定ip地址和端口号
// go
// 1+2、获取一个tcp的Addr套接字
addr, err := net.ResolveTCPAddr(s.IPVersion, fmt.Sprintf("%s:%d", s.IP, s.Port))
# python
socket.bind((SERVER_IP,SERVER_PORT)) #绑定地址和端口号
3 服务器socket已经准备好了监听客户端发来的连接请求,这时候的服务器socket是没有没打开的
①:服务器监听:服务器端套接字并不具体确定客户端套接字,而是处于一种阻塞、等待状态,实时的监听网络状态,准备在第一时间接收到客户端的连接请求。
// go
//服务器绑定的ip版本
IPVersion string
listenner, err := net.ListenTCP(s.IPVersion, addr)
# python
socket.listen(128) #监听的最大数量
3.1 这个时候,客户端可以开始准备连接服务器了
3.1.1 客户端创建socket
# python
client_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
3.1.2 客户端打开socket,根据服务器的ip地址和端口号,发送connection请求
②:客户端请求:客户端向指定服务器套接字发送连接请求,必须要描述它要连接的服务器套接字,指出服务器的IP和端口,并发送请求。
// go
// 3.1.1+3.1.2
conn, err := net.Dial("tcp", "127.0.0.1:8999")
# python
client_socket.connect(('127.0.0.1',8888))
4 服务器接收到客户端的socket,connect请求,开始接受客户端请求,直到客户端返回连接信息。在这期间,socket一直处于阻塞状态,直到accept()方法接收到了客户端的连接信息后才返回。开始接收下一个客户端的连接请求
4.1 客户端连接成功,向服务器发送连接状态信息
4.2 服务器accept方法返回,连接成功
③:当服务器的套接字监听到了来自客户端的套接字请求,就响应给客户端套接字请求,建立一个新的连接,并把服务器套接字的描述也发给客户端,一旦客户端确认了此描述,双方就正式建立连接。
// go
// 阻塞的等待客户端链接,处理客户端连接业务(读写)
conn, err := listenner.AcceptTCP()
# python
# 等待客户端链接,获取客户端链接
soc,addr=self.server_socket.accept()
④:而服务器的套接字继续处于监听状态,准备接受下一个来自其他客户端的套接字请求。
5 服务器开始通过socket处理客户端业务
// go
dealConn := NewConnection(s, conn, cid, s.MsgHandle)
# python
#处理业务
#读业务
recv_data=soc.recv(512)
print(recv_data.decode('utf-8'))
#写业务
soc.send('成功链接'.encode('utf-8'))
6 服务器、客户端socket关闭
// go
//关闭socket链接
c.Conn.Close()
//告知Writer关闭
c.ExitChan <- true
//将当前链接从ConnMgr中删除掉
c.TcpServer.GetConnMgr().Remove(c)
//回收资源
close(c.ExitChan)
close(c.msgChan)
# python
#客户端关闭
client_socket.close()
#服务器关闭
soc.close()
整个过程就是socket编程的流程。
在这其中也包含了TCP协议的一些重点:
1.三次握手
在TCP/IP协议中,TCP协议通过三次握手建立一个可靠的连接
第一次握手:客户端尝试连接服务器,并向服务器发送SYN包(同步序列编号Synchronize Sequence Numbers),syn=j,客户端进入SYN_SEND状态等待服务器确认。
第二次握手:服务器接收客户端SYN包并确认(ack=j+1),同时向客户端发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态。
第三次握手:客户端接收到服务器的SYN_ACK包,同时向服务器发送确认ACK包(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
这种服务器socket和客户端socket建立连接就是三次握手
2.基于socket的HTTP链接的特点
HTTP协议(超文本传输协议(Hypertext Transfer Protocol )),是Web联网的基础,也是手机联网常用的协议之一,HTTP就是建立在TCP协议之上的一种协议应用。
HTTP连接的显著特点就是客户端发送请求过后就只能等待服务器会送响应,在请求结束后,会主动释放连接。整个过程中,从建立连接到关闭连接的过程,称之为“一次连接”。
三、TCP和UDP的区别:
1、TCP是面向链接的,虽然网络的各种波动影响,没有百分百的可靠连接,但TCP的三次握手,是在最低限度上(也就是最大程度上)保证了连接的可靠性。
UDP是一种无连接的数据传输协议,UDP在传输数据前,并不会与对方建立连接,接收到消息后也不会向对方发送确认信号,发送端也并不知道数据是否全部发送正确,也就不存在重发,所以UDP也是不可靠传输协议。
2、正由于了UDP的特点,使得UDP的开销更小,数据传输效率更高,避免了数据收发时的确认,所以UDP的实时性是更好的。
所以TCP的传输相对来说就要比UDP的传输来的慢一些,但因为程序员可以对UDP的数据进行手动验证,比如对每个数据的发送都进行加密,在接收时进行对应的解密验证,从而实现了部分可靠。
但在天性上,UDP应为在底层协议上的封装并没有采用TCP的“三次握手”的可靠连接,所以各有各的使用场景与优点。
**本文章仅供学习参考使用**