TCP介绍
TCP协议,传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议
TCP通信需要经过创建连接、数据传送、终止连接三个步骤。
TCP通信模型中,在通信开始之前,一定要先建立相关连接,才能发生数据。
TCP特点
面向连接
1.通信双方必须先建立连接才能进行数据的传输
2.可靠传输
TCP采用发送应答机制
1.超时重传
2.错误校验
3.流量控制和阻塞管理
TCP与UDP区别总结
1、TCP面向连接;UDP是无连接的,即发送数据之前不需要建立连接
2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
3、UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。
4、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
5、TCP对系统资源要求较多,UDP对系统资源要求较少。
udp通信:
tcp通信:
TCP客户端
客户端,就是需要被服务的一方
TCP客户端构建流程
1.创建socket
2.链接服务器
3.接收数据(最大接收2014个字节)
4.关闭套接字
import socket
def main():
# 创建套接字
tcp_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_ip = input('请输入服务端的ip')
server_port = input('请输入服务端的端口')
# 连接服务器
tcp_client.connect_ex((server_ip, server_port))
# 发送数据
send_data = input('请输入要发送的内容:')
tcp_client.send(send_data.encode())
# 接收数据
recv_data = tcp_client.recv(1024)
print(recv_data.decode('gbk'))
tcp_client.close()
if __name__ == '__main__':
main()
tcp的使用大体和udp一样,区别之处在于tcp的使用需要先进行连接,因为进行了连接,所以也不需要sendto和recvfrom了,直接send,recv即可。
TCP服务端
服务器端:就是提供服务的一方
TCP服务端
1 socket创建套接字
2 bind绑定IP和port
3 listen使套接字变为可以被动链接
4 accept等待客户端的链接
5 recv/send接收发送数据
import socket
def main():
# 创建套接字
tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定
tcp_server.bind(('ip地址', 端口))
# 转被动为主动
tcp_server.listen(128)
new_client_socket, client_addr = tcp_server.accept()
# 接收数据
recv_data = new_client_socket.recv(1024)
print(recv_data.decode('gbk'))
# 发送数据
new_client_socket.send(b'hello')
new_client_socket.close()
tcp_server.close()
if __name__ == '__main__':
main()
在使用tcp服务端时出现的一点不同为需要转被动为主动,这时会分配到一个新的套接字以及地址,接受和发送数据都是通过这个新的套接字来进行。
我们可以把上述过程想象为:
1 买手机
2 插上手机卡
3 设置手机为正常接听状态
4 等待别人打电话
TCP服务端为多个客户端服务
import socket
def main():
# tcp的套接字
tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定信息
tcp_server.bind(("ip地址", 端口))
# 为多个客户端服务
while True:
# 主动变被动
tcp_server.listen(128)
new_client_socket, client_addr = tcp_server.accept()
# 为客户端多次服务
while True:
# 接收数据 阻塞
recv_data = new_client_socket.recv(1024)
# 客户端发送过来数据
# 客户端断开连接
if recv_data.decode('gbk'):
# 发送数据
new_client_socket.send('haha'.encode('gbk'))
else:
break
# 关闭客户端
new_client_socket.close()
tcp_server.close()
if __name__ == '__main__':
main()
为了使tcp服务端向多个客户端服务,我们在listen前添加一个while循环,即一有一个客户端连接,就进行一次listen,获得一个新的套接字。
再在接发数据处添加一个while循环,判断条件为是否还有接受到数据,如果一直有接收到信息就保持循环,而没有时则break退出。最后关闭套接字。
文件下载器
为了通过socket套接字实现文件下载的功能,我们需在客户端、服务端分别实现如下功能:
TCP客户端
1.创建套接字
2.目的信息 服务器的ip port
3.连接服务器
4.输入要下载的文件名称
5.发送文件下载请求
6.接收对方发送过来的数据
7.接收到数据在创建文件
8.关闭套接字
TCP服务端
1 socket创建套接字
2 bind绑定IP和port
3 listen使套接字变为可以被动链接
4 accept等待客户端的链接
5 recv/send接收发送数据
客户端:
import socket
def main():
# 创建TCP套接字
tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_ip = input("server ip:")
server_port = int(input("server port:"))
# 连接服务器
tcp_client_socket.connect((server_ip, server_port))
file_name = input('请输入文件名称:')
# 发送文件下载请求
tcp_client_socket.send(file_name.encode('gbk'))
# 接收文件
recv_data = tcp_client_socket.recv(1024*1024)
if recv_data:
# 保存文件
with open('接收'+file_name, 'wb') as f:
f.write(recv_data)
# 关闭套接字
tcp_client_socket.close()
if __name__ == '__main__':
main()
服务端:
import socket
def send_file_client(new_client_socket):
# 接收客户端发送过来的数据
file_name = new_client_socket.recv(1024).decode()
content = b""
try:
with open(file_name, 'rb') as f:
content = f.read()
except:
print("no download file:%s" % file_name)
new_client_socket.send(content)
new_client_socket.close()
def main():
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_server_socket.bind(("", 8080))
tcp_server_socket.listen(128)
new_client_socket, client_addr = tcp_server_socket.accept()
# 给客户端返回文件内容
send_file_client(new_client_socket)
tcp_server_socket.close()
if __name__ == '__main__':
main()
与之前的文字信息的发送接受添加的只是文件的读取写入,所以这里便不进行重复解释了。