TCP协议 -> 传输控制协议
用途:主要用于网间传输的协议,分割处理报文并把结果包传到IP层,并接收处理IP曾传到的数据包。
TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
TCP通信模型中,在通信开始之前,一定要先建立相关的链接,才能发送数据,类似于生活中,"打电话""。
TCP通信流程
TCP服务器流程如下:
1.socket 创建一个套接字
2.bind 绑定ip和port
3.listen 启动监听,使套接字变为可以被动连接,当关闭监听时,任何客户端都不能连接服务端
4.accept 等待客户端的连接
5.recv/send 接收/发送数据
6.close 关闭socket对象
TCP连接三次握手
TCP断开连接四次挥手
TCP断开链接的过程和建立连接的过程比较类似,只不过中间的两步并不总是会合成一步走,所以它分成了4个动作。
上面有一个非常特殊的状态time_wait,它是主动关闭的一方在回复完对方的挥手后进入的一个长期状态,这个状态标准的
持续时间是4分钟,4分钟后才会进入到closed状态,释放套接字资源。不过在具体实现上这个时间是可以调整的。
单进程
TCP服务端流程:
- socket 创建一个套接字
from socket import *
server = socket(AF_INET,SOCK_STREAM)
2.bind 绑定ip和port
SERVERADDR = ('192.168.12.156',8888)
server.bind(SERVERADDR)
3.listen 启动监听,使套接字变为可以被动连接,当关闭监听时,任何客户端都不能连接服务端
server.listen(n) # n 代表可监听的客户端的数量,不写则默认为最大
4.accept 等待客户端的连接
server.accept()
5.recv/send 接收/发送数据
info = client.recv(1024)
print(info.decode('utf8'),client.getpeername())
inputstr = input('请输入发送信息:').encode('utf8')
client.send(inputstr)
6.close 关闭socket对象
client.close()
server.close()
TCP客户端流程:
from socket import *
client = socket(AF_INET,SOCK_STREAM)
client.connect(('192.168.12.156',8888)) # 连接到服务端
# 发送消息
inputstr = input('输入发送信息:').encode('utf8')
client.send(inputstr)
print('发送成功')
# 接收消息
while True:
result = client.recv(1024)
if len(result)>0:
print(result)
else:
break
# 关闭客户端
client.close()
多线程
TCP服务端流程:
from socket import *
import threading
def tread(cs):
while True:
result = cs.recv(1024)
if len(result)>0:
info = result.decode('gbk')
# print(cs.getpeername(),info)
to = info.split(':')[0]
message = info.split(':')[1].encode('gbk')
# print(to,message)
if to in userdict.keys():
userdict[to].send(message)
else:
cs.send("对方已离线,您不能发送消息".encode('gbk'))
else:
userdict.pop(str(cs.getpeername()[1]))
print('剩余客户端',len(userdict))
# print('断开',cs.getpeername())
break
def tlisten(s):
# 接收连接
while True:
client, clientaddr = s.accept()
# 将连接的用户存到用户字典
userdict[str(clientaddr[1])] = client
print(clientaddr,"连接上了","用户列表",len(userdict))
# print(clientaddr, '连接上了')
# 第二个线程,用来接收client 发来的消息
tr = threading.Thread(target=tread,args=(client,))
tr.start()
if __name__=='__main__':
try:
userdict = {}
# 构造服务端对象
server = socket(AF_INET, SOCK_STREAM)
# 绑定地址
server.bind(('192.168.12.156', 8888))
# 开启监听
server.listen(10)
print('开启监听')
# 开启线程用于接受客户端连接
tl = threading.Thread(target=tlisten,args=(server,))
tl.start()
except Exception as e:
print(e)
TCP客户端流程:
from socket import *
import threading
def twrite(ct):
"""发送"""
try:
while True:
if not ct._closed:
# 当进入while循环,还没有断开连接
# input阻塞之后断开连接
inputstr = input('请输入要发送的信息:').encode('utf8')
if ct._closed:
break
else:
ct.send(inputstr)
else:
break
except Exception as e:
print(e)
def tread(ct):
"""接收"""
try:
while True:
result = ct.recv(1024)
if len(result) > 0:
print(result)
else:
ct.close()
break
except Exception as e:
print(e)
if __name__=='__main__':
try:
client = socket(AF_INET, SOCK_STREAM)
ADDRESS = ('192.168.12.156', 8888)
ADDR = client.connect(ADDRESS)
tw = threading.Thread(target=twrite, args=(client, ))
tw.start()
tr = threading.Thread(target=tread, args=(client,))
tr.start()
tw.join()
tr.join()
client.close()
except Exception as e:
print(e)
print('已断开连接')