一、Socket简介
1、不同电脑上的进程如何通信?
进程间通信的首要问题是如何找到目标进程,也就是操作系统是如何唯一标识一个进程的!
在一台电脑上是只通过进程号PID,但在网络中是行不通的,因为每台电脑的IP可能都是不一样的,因此TCP/IP协议族通过使用IP地址+端口号的方式来标识任意一台主机的应用进程。
因此,利用IP地址 + 协议 + 端口号就可以用来标识网络进程了,网络中可以利用这个标识来与其他进程通信。
2.什么是socket
Socket简称为套接字,是进程间通信的一种方式,它与其他进程间通信的一个不同之处在于:它能实现不同主机间的进程间通信,网络上各种各样的服务大多是基于Socket来完成的。
二、TCP简介
1.介绍:TCP协议,传输控制协议(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
2.通信流程:建立连接、数据传输、终止连接,就类似我们生活中的“打电话”。
三、TCP特点:
1.面向连接:通信前必须先建立连接才能进行数据传输,双方都必须为该连接分配必要的系统内核资源。
2.可靠传输:主要体现在:
1). TCP采用发送应答机制:TCP发送的每个报文都必须得到接收方的应答才能成功传输该报文。
2). 超时重传:如果发出的报文在一段时间内没有收到应答那么就重新发送这个报文段。此外,TCP是为每个包都分配一个序号,用来保证不会发送方丢包和用于在接收端重组。
3). 错误检验:TCP用一个校验和函数来校验数据是否有误,
4). 流量控制和阻塞管理:用来避免主机发送得过快而使接收方来不及全部收下。
四、UDP协议
UDP是一中无需建立连接就能通信的协议,只需要发送数据即可。因此一般适用于广播的应用程序。
五、TCP与UDP的不同点
- 面向连接(确认有创建三方交握,连接已创建才作传输。)
- 有序数据传输
- 重发丢失的数据包
- 舍弃重复的数据包
- 无差错的数据传输
- 阻塞/流量控制
六、TCP/IP协议族
互联网协议包含了上百种协议标准,但是最重要的两个协议是TCP和IP协议,因此一般把互联网的协议简称为TCP/IP协议族。
七、TCP/IP协议传输示意图
以QQ间发送消息为例!
八、TCP通信模型
主要是使用TCP协议来进行通信!
注意点:
- tcp服务器一般情况下都需要绑定端口,否则客户端找不到这个服务器
- tcp客户端一般不绑定,因为是主动链接服务器,所以只要确定好服务器的ip、port等信息就好,本地客户端可以随机
- tcp服务器中通过listen可以将socket创建出来的主动套接字变为被动的,这是做tcp服务器时必须要做的
- 当客户端需要链接服务器时,就需要使用connect进行链接,udp是不需要链接的而是直接发送,但是tcp必须先链接,只有链接成功才能通信
- 当一个tcp客户端连接服务器时,服务器端会有1个新的套接字,这个套接字用来标记这个客户端,单独为这个客户端服务
- listen后的套接字是被动套接字,用来接收新的客户端的链接请求的,而accept返回的新套接字是标记这个新客户端的
- 关闭listen后的套接字意味着被动套接字关闭了,会导致新的客户端不能够链接服务器,但是之前已经链接成功的客户端正常通信。
- 关闭accept返回的套接字意味着这个客户端已经服务完毕
- 当客户端的套接字调用close后,服务器端会recv解堵塞,并且返回的长度为0,因此服务器可以通过返回数据的长度来区别客户端是否已经下线
代码实现如:
import socket def main():
pass
# 1.创建TCP套接字
tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置地址可重用
tcp_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 2.把套接字绑定到主机上
tcp_sock.bind(('', 6060))
# 3.被动套接字
tcp_sock.listen(128)
print('{}正在监听中'.format(tcp_sock.getsockname()))
# 4.与客户端进行连接
while True:
client, addr = tcp_sock.accept() # Ctrl+Shift +i
print('已经连接到了客户端:{}'.format(addr))
# 接收来自客户端的消息
data = client.recv(1024)
print(data.decode('utf-8'))
# 消息一经发送完毕就断开了连接
client.close() # 短连接 tcp_sock.close() if __name__ == '__main__':
main()