1 TCP原理图

image.png
在TCP协议中, 两台主机的地位不再平等, 有一台是服务端, 为客户端提供服务

2 客户端为py程序,服务端为网络调试助手

  1. from socket import *
  2. tcp_socket = socket(AF_INET, SOCK_STREAM)
  3. server_ip = input("请输入服务器IP:")
  4. server_port = int(input("请输入服务器port:"))
  5. print("正在连接服务器...")
  6. tcp_socket.connect((server_ip, server_port))
  7. print("连接服务器成功!")
  8. send_data = input("请输入要发送的数据:")
  9. tcp_socket.send(send_data.encode("utf-8"))
  10. print("正在等待接收数据...")
  11. recvData = tcp_socket.recv(1024)
  12. print("接收到的数据为:", recvData.decode("gbk"))
  13. tcp_socket.close()
  14. print("套接字已关闭")

image.png
image.png

3 服务端为py程序,客户端为网络调试助手

  1. from socket import *
  2. tcp_socket = socket(AF_INET, SOCK_STREAM)
  3. print("服务器绑定端口号:7890")
  4. tcp_socket.bind(("", 7890))
  5. print("令tcp_socket变为监听套接字")
  6. tcp_socket.listen(128) # 允许同时有XX个客户端连接此服务器,但是和操作系统有关, 一般写128或者不写
  7. print("正在等待接收客户端的连接请求...")
  8. # client_socket是用来为一个客户端服务的套接字
  9. client_socket, client_addr = tcp_socket.accept()
  10. print("客户端信息:", client_addr)
  11. print("客服套接字等待接收客户端的消息中...")
  12. recv_data = client_socket.recv(1024)
  13. print("客户端刚刚说:", recv_data.decode("gbk"))
  14. reply = "您好,先生,是要更换199元套餐吗?"
  15. print("客服套接字回复客户端:", reply)
  16. client_socket.send(reply.encode("utf-8"))
  17. print("客服下班了")
  18. client_socket.close()
  19. print("10010倒闭了")
  20. tcp_socket.close()

image.png
image.png

4 服务端py程序为一个客户端多次服务

  1. from socket import *
  2. tcp_socket = socket(AF_INET, SOCK_STREAM)
  3. print("服务器绑定端口号:7890")
  4. tcp_socket.bind(("", 7890))
  5. print("令tcp_socket变为监听套接字")
  6. tcp_socket.listen(128)
  7. while True:
  8. print("正在等待接收客户端的连接请求...")
  9. # client_socket是用来为一个客户端服务的套接字
  10. client_socket, client_addr = tcp_socket.accept()
  11. print("客户端信息:", client_addr)
  12. while True:
  13. print("客服套接字等待接收客户端的消息中...")
  14. recv_data = client_socket.recv(1024)
  15. print("客户端刚刚说:", recv_data.decode("gbk"))
  16. if not recv_data: # 若客户端退出,会收到一个空str
  17. break
  18. reply = "马冬梅"
  19. print("客服套接字回复客户端:", reply)
  20. client_socket.send(reply.encode("utf-8"))
  21. print("客服下班了")
  22. client_socket.close()
  23. print("10010倒闭了")
  24. tcp_socket.close()

image.png

5 长连接 与 短连接

(1) TCP短连接

模拟一种TCP短连接的情况:

  1. client 向 server 发起连接请求
  2. server 接到请求,双方建立连接
  3. client 向 server 发送消息
  4. server 回应 client
  5. 一次读写完成,此时双方任何一个都可以发起 close 操作

在步骤5中,一般都是 client 先发起 close 操作。当然也不排除有特殊的情况。
从上面的描述看,短连接一般只会在 client/server 间传递一次读写操作!

短连接的操作步骤
建立连接——数据传输——关闭连接…建立连接——数据传输——关闭连接

TCP短连接的优点和缺点
• 短连接对于服务器来说管理较为简单,存在的连接都是有用的连接,不需要额外的控制手段。
• 但如果客户请求频繁,将在TCP的建立和关闭操作上浪费时间和带宽。

TCP短连接的应用场景
而像WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,
而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,
如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,
那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好。

(2) TCP长连接

再模拟一种长连接的情况:

  1. client 向 server 发起连接
  2. server 接到请求,双方建立连接
  3. client 向 server 发送消息
  4. server 回应 client
  5. 一次读写完成,连接不关闭
  6. 后续读写操作…
  7. 长时间操作之后client发起关闭请求

长连接的操作步骤
建立连接——数据传输…(保持连接)…数据传输——关闭连接

TCP长连接的优点和缺点
• 长连接可以省去较多的TCP建立和关闭的操作,减少浪费,节约时间。
对于频繁请求资源的客户来说,较适用长连接。
• client与server之间的连接如果一直不关闭的话,会存在一个问题,
随着客户端连接越来越多,server早晚有扛不住的时候,这时候server端需要采取一些策略,
如关闭一些长时间没有读写事件发生的连接,这样可以避免一些恶意连接导致server端服务受损;
如果条件再允许就可以以客户端机器为颗粒度,限制每个客户端的最大长连接数,
这样可以完全避免某个蛋疼的客户端连累后端服务。

TCP长连接的应用场景
• 长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况。
每个TCP连接都需要三次握手,这需要时间,如果每个操作都是先连接,
再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,
再次处理时直接发送数据包就OK了,不用建立TCP连接。
例如:数据库的连接用长连接,如果用短连接频繁的通信会造成socket错误,
而且频繁的socket 创建也是对资源的浪费。