【转】Python学习---Socket通信原理以及三次握手和四次挥手详解
【原文】https://www.toutiao.com/i6566024355082404365/
什么是Socket?
Socket的中文翻译过来就是“套接字”。套接字是什么,我们先来看看它的英文含义:插座。
Socket就像一个电话插座,负责连通两端的电话,进行点对点通信,让电话可以进行通信,端口就像插座上的孔,端口不能同时被其他进程占用。而我们建立连接就像把插头插在这个插座上,创建一个Socket实例开始监听后,这个电话插座就时刻监听着消息的传入,谁拨通我这个“IP地址和端口”,我就接通谁。
实际上,Socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口,供应用层调用实现进程在网络中的通信。Socket起源于UNIX,在Unix一切皆文件的思想下,进程间通信就被冠名为文件描述符(file desciptor),Socket是一种“打开—读/写—关闭”模式的实现,服务器和客户端各自维护一个“文件”,在建立连接打开后,可以向文件写入内容供对方读取或者读取对方内容,通讯结束时关闭文件。
另外我们经常说到的Socket所在位置如下图:
Socket通信过程
Socket保证了不同计算机之间的通信,也就是网络通信。对于网站,通信模型是服务器与客户端之间的通信。两端都建立了一个Socket对象,然后通过Socket对象对数据进行传输。通常服务器处于一个无限循环,等待客户端的连接。
一图胜千言,下面是面向连接的TCP时序图:
客户端过程:
客户端的过程比较简单,创建Socket,连接服务器,将Socket与远程主机连接(注意:只有TCP才有“连接”的概念,一些Socket比如UDP、ICMP和ARP没有“连接”的概念),发送数据,读取响应数据,直到数据交换完毕,关闭连接,结束TCP对话。
import socket
import sys
if __name__ == '__main__':
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 创建Socket连接
sock.connect(('127.0.0.1', 8001)) # 连接服务器
while True:
data = input('Please input data:')
if not data:
break
try:
sock.sendall(data)
except socket.error as e:
print('Send Failed...', e)
sys.exit(0)
print('Send Successfully')
res = sock.recv(4096) # 获取服务器返回的数据,还可以用recvfrom()、recv_into()等
print(res)
sock.close()
sock.sendall(data)
这里也可用send()方法:不同在于sendall()在返回前会尝试发送所有数据,并且成功时返回None,而send()则返回发送的字节数量,失败时都抛出异常。
服务端过程:
咱再来聊聊服务端的过程,服务端先初始化Socket,建立流式套接字,与本机地址及端口进行绑定,然后通知TCP,准备好接收连接,调用accept()阻塞,等待来自客户端的连接。如果这时客户端与服务器建立了连接,客户端发送数据请求,服务器接收请求并处理请求,然后把响应数据发送给客户端,客户端读取数据,直到数据交换完毕。最后关闭连接,交互结束。
import socket
import sys
if __name__ == '__main__':
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 创建Socket连接(TCP)
print('Socket Created')
try:
sock.bind(('127.0.0.1', 8001)) # 配置Socket,绑定IP地址和端口号
except socket.error as e:
print('Bind Failed...', e)
sys.exit(0)
sock.listen(5) # 设置最大允许连接数,各连接和Server的通信遵循FIFO原则
while True: # 循环轮询Socket状态,等待访问
conn, addr = sock.accept()
try:
conn.settimeout(10) # 获得一个连接,然后开始循环处理这个连接发送的信息
# 如果要同时处理多个连接,则下面的语句块应该用多线程来处理
while True:
data = conn.recv(1024)
print('Get value ' + data, end='')
if not data:
print('Exit Server', end='')
break
conn.sendall('OK') # 返回数据
except socket.timeout: # 建立连接后,该连接在设定的时间内没有数据发来,就会引发超时
print('Time out')
conn.close() # 当一个连接监听循环退出后,连接可以关掉
sock.close()
conn, addr = sock.accept()
调用accept()时,Socket会进入“waiting”状态。客户请求连接时,方法建立连接并返回服务器。accept()返回一个含有两个元素的元组(conn, addr)。第一个元素conn是新的Socket对象,服务器必须通过它与客户通信;第二个元素addr是客户的IP地址及端口。
data = conn.recv(1024)
接下来是处理阶段,服务器和客户端通过send()和recv()通信(传输数据)。
服务器调用send(),并采用字符串形式向客户发送信息,send()返回已发送的字符个数。
服务器调用recv()从客户接收信息。调用recv()时,服务器必须指定一个整数,它对应于可通过本次方法调用来接收的最大数据量。recv()在接收数据时会进入“blocked”状态,最后返回一个字符串,用它表示收到的数据。如果发送的数据量超过了recv()所允许的,数据会被截短。多余的数据将缓冲于接收端,以后调用recv()时,多余的数据会从缓冲区删除(以及自上次调用recv()以来,客户可能发送的其它任何数据)。传输结束,服务器调用Socket的close()关闭连接。
TCP三次握手的Socket过程:
- 服务器调用socket()、bind()、listen()完成初始化后,调用accept()阻塞等待;
- 客户端Socket对象调用connect()向服务器发送了一个SYN并阻塞;
- 服务器完成了第一次握手,即发送SYN和ACK应答;
- 客户端收到服务端发送的应答之后,从connect()返回,再发送一个ACK给服务器;
- 服务器Socket对象接收客户端第三次握手ACK确认,此时服务端从accept()返回,建立连接。
接下来就是两个端的连接对象互相收发数据。
TCP四次挥手的Socket过程:
- 某个应用进程调用close()主动关闭,发送一个FIN;
- 另一端接收到FIN后被动执行关闭,并发送ACK确认;
- 之后被动执行关闭的应用进程调用close()关闭Socket,并也发送一个FIN;
- 接收到这个FIN的一端向另一端ACK确认。
上面的代码是简单的演示Socket的基本函数使用,其实不管有多复杂的网络程序,这些基本函数都会用到。上面的服务端代码只有处理完一个客户端请求才会去处理下一个客户端的请求,这样的服务器处理能力很弱,而实际中服务器都需要有并发处理能力,为了达到并发处理,服务器就需要fork一个新的进程或者线程去处理请求。
【转】Python学习---Socket通信原理以及三次握手和四次挥手详解的更多相关文章
- TCP三次握手与四次挥手详解
目录 TCP三次握手与四次挥手详解 1.TCP报文格式 2.TCP三次握手 3.TCP四次挥手 4.为什么建立连接需要三次握手? 5.为什么断开连接需要四次挥手? 6.为什么TIME_WAIT状态还需 ...
- TCP三次握手与四次挥手详解(最全面)
目录 TCP的三次握手与四次挥手 TCP报文段的首部格式 TCP的工作原理 TCP 的流量控制 TCP的拥塞控制 拥塞控制与流量控制的关系 拥塞控制所起的作用 慢开始和拥塞避免 慢开始算法的原理 三次 ...
- [ 转载 ] Tcp三次握手和四次挥手详解
#TCP的报头: 源端口号:表示发送端端口号,字段长为16位.目标端口号:表示接收端口号,字段长为16位.序列号:表示发送数据的位置,字段长为32位.每发送一次数据,就累加一次该数据字节数的大小.注意 ...
- TCP的三次握手与四次挥手详解
TCP的三次握手与四次挥手是TCP创建连接和关闭连接的核心流程,我们就从一个TCP结构图开始探究中的奥秘 序列号seq:占4个字节,用来标记数据段的顺序,TCP把连接中发送的所有数据字节都编上一个序 ...
- TCP协议三次握手与四次挥手详解
在计算机网络的学习中TCPi协议与Http协议是我们必须掌握的内容,其中Tcp协议属于传输层,而Http协议属于应用层,本博客主要讲解Tcp协议中的三次握手与四次挥手,关于Http协议感兴趣的可以参看 ...
- 转 TCP/IP的三次握手与四次挥手详解
TCP((Transmission Control Protocol)传输控制协议,是一个面向连接的协议.在运用此协议进行数据传输前都会进行连接的建立工作(三次握手):当数据传输完毕,连接的双方都会通 ...
- TCP/IP的三次握手与四次挥手详解
TCP((Transmission Control Protocol)传输控制协议,是一个面向连接的协议.在运用此协议进行数据传输前都会进行连接的建立工作(三次握手):当数据传输完毕,连接的双方都会通 ...
- TCP三次握手、四次挥手详解
1.TCP报文格式 TCP(Transmission Control Protocol) 传输控制协议.TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接. 我们需要 ...
- TCP三次握手和四次挥手详解
背景描述通过上一篇中网络模型中的IP层的介绍,我们知道网络层,可以实现两个主机之间的通信.但是这并不具体,因为,真正进行通信的实体是在主机中的进程,是一个主机中的一个进程与另外一个主机中的一个进程在交 ...
随机推荐
- HashMap:JDK7 与 JDK8 的实现
JDK7中的HashMap HashMap底层维护一个数组,数组中的每一项都是一个Entry: transient Entry<K,V>[] table; 我们向在HashMap 中存放的 ...
- GCC 多文件编辑
#include <stdio.h> int plus(int a, int b); int minus(int a, int b); int multiply(int a, int b) ...
- 【IT笔试面试题整理】判断一个二叉树是否是平衡的?
[试题描述]定义一个函数,输入一个链表,判断链表是否存在环路 平衡二叉树,又称AVL树.它或者是一棵空树,或者是具有下列性质的二叉树:它的左子树和右子树都是平衡二叉树,且左子树和右子树的高度之差之差的 ...
- CRM项目再分析建表
今天老师带着我们分析了一点项目的业务,我们就觉得有些地方呢 有一些不妥额地方,然后呢 我们就在原来表的基础上做了一些修改! 我们也把我们组的项目业务的工作分配了一下! 但是我们遇到了一个组员不和我们 ...
- Spring-web初始化流程简图
- Netty 核心组件 Pipeline 源码分析(一)之剖析 pipeline 三巨头
目录大纲: 前言 ChannelPipeline | ChannelHandler | ChannelHandlerContext 三巨头介绍 三巨头编织过程(创建过程) ChannelPipelin ...
- 并发编程之 Exchanger 源码分析
前言 JUC 包中除了 CountDownLatch, CyclicBarrier, Semaphore, 还有一个重要的工具,只不过相对而言使用的不多,什么呢? Exchange -- 交换器.用于 ...
- C++为啥要使用new
1.为什么要有new? 为什么要有new?为什么要动态创建对象?为什么有时候不用new,有时候又用new,比如: // Cocos2d-x3.x的Value类,大家都很熟悉了 Value v = Va ...
- uni-app初体验及打包成apk
首先用HBuilderX新建建一个uni-app项目 新建一个目录ucenter,该目录下新建两个vue文件ucenter.vue和setting.vue ucenter.vue <templa ...
- 关于__int64的使用!
关于__int64的使用! 类型 long long __int64 intmax_t 格式 %lld %I64d %I64d 在Dev C++中,三种类型均需用%I64d格式输出 ,c语言中int ...