四、python学习之网络-TCP

一、网络传输方式-TCP
1.TCP概念:
    TCP简称传输控制协议,是一种面向连接,可靠的,基于字节流的传输通信协议。
    TCP通信需要经过建立连接,数据传送,终止连接三个步骤。

2.TCP特点:
    2.1 面向连接:
        通信双方必须先建立连接才能进行数据传输,双方都必须为该连接分配必要的系统内核资源,以管理连接的状态和连接上的传输。  

    2.2 可靠传输:
           <1>TCP采用应答机制:

            TCP发送的每个报文段都必须得到接收方的应答才认为这个TCP报文段传输成功

            <2>超时重传:

发送端发出一个报文段之后就启动定时器,如果在定时时间内没有收到应答就重新发送这个报文段。

TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。

            <3>错误校验:

由发送端计算,然后由接收端验证,其目的是为了检测数据在发送端到接收端之间是否有改动,如果接收方检测到校验和有差错,则直接丢弃这个数据包。

            <4>流量控制和阻塞管理:

流量控制用来避免主机发送得过快而使接收方来不及完全收下。

3.TCP的优缺点:
    优点:
        可靠,稳定
        适合传输大量的数据
    缺点:
        数据传输速度慢
        占用系统资源

4.TCP和UDP的区别:

<1>TCP面向连接; UDP是不面向连接;

<2>TCP提供可靠的数据传输,也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP不保证可靠的数据传输,容易出现丢包情况;

<3>TCP需要连接传输速度慢,UDP不需要连接传输速度快

<4>TCP不支持发广播;UDP支持发广播

<5>TCP对系统资源要求较多,UDP对系统资源要求较少。

<6>TCP适合发送大量数据,UDP适合发送少量数据

<7>TCP有流量控制,UDP没有流量控制

5.TCP使用场景:
    对网络质量有要求的时候。比如:HTTP,HTTPS,FTP等文件传输协议;POP,SMTP等邮件传输协议。

6. UDP网络程序流程:
    udp网络程序发送数据不需要建立连接

7.TCP网络程序流程:
    tcp网络程序需要先通过3次握手建立连接

二、TCP客户端:

#!/usr/bin/python3
#-*-coding:utf-8-*-

import socket

# 设置服务器的ip和端口
ip_host = ("192.168.14.49", 7788)

if __name__ == '__main__':
    # 创建套接字
    tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 连接服务器
    tcp_client_socket.connect(ip_host)
    # 打印连接状态
    print("连接成功...")
    # 发送数据
    conent = input(">")
    tcp_client_socket.send(conent.encode())

    # 接收数据
    recv_data = tcp_client_socket.recv(1024)
    print("接收到的数据:", recv_data.decode())

    # 关闭连接
    tcp_client_socket.close()

三、TCP服务端:

#!/usr/bin/python3
#-*-coding:utf-8-*-

# 导包
import socket

if __name__ == '__main__':
    # 创建tcpServer的套接字
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 绑定端口
    tcp_server_socket.bind(('',7788))
    # 设置端口复用
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
    # 设置监听
    tcp_server_socket.listen(128)

    # 获取客户端的连接
    service_tcp_client, client_host = tcp_server_socket.accept()
    # 打印客户端ip和地址
    print("客户端:", client_host)

    # 接手客户端的数据
    recv = service_tcp_client.recv(1024)
    print("客户端发送的数据:",recv.decode())

    # 服务端回复客户端
    service_tcp_client.send("服务端已收到你的数据...".encode())

    # 关闭客户端的套接字
    service_tcp_client.close()

    # 关闭服务短的套接字
    tcp_server_socket.close()

注意:

TCP连接断开后.端口不会立即释放,需要等待1~2分钟
# 设置程序退出后端口后立即释放,即端口复用

tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)

四、TCP注意点:

1.tcp服务器一般情况下都需要绑定端口号,否则客户端找不到这个服务器

2.tcp客户端一般不绑定端口号,使用随机生成的端口号即可

※3.tcp服务器中通过listen可以将socket创建出来的主动套接字变为被动的,这是做tcp服务器时必须要做的

4.当tcp客户端和服务端建立好连接才可以收发数据,udp是不需要建立连接,直接就可以发送数据

5.当一个tcp客户端和服务端连接成功后,服务器端会有1个新的套接字,这个套接字用来标记这个客户端,单独为这个客户端服务

6.listen后的套接字是被动套接字,用来接收新的客户端的链接请求的,而accept返回的新套接字是标记这个新客户端的

7.关闭listen后的套接字意味着被动套接字关闭了,会导致新的客户端不能够链接服务器,但是之前已经链接成功的客户端正常通信。

8.关闭accept返回的套接字意味着这个客户端已经服务完毕

※9.当客户端的套接字调用close后,服务器端会recv解堵塞,并且返回的长度为0,因此服务器可以通过返回数据的长度来区别客户端是否已经下线


五、TCP实现FTP文件下载器
    1.服务端:

# -*-coding:utf-8-*-

from socket import *
import os

if __name__ == '__main__':
    # 创建套接字
    tcp_server = socket(AF_INET, SOCK_STREAM)
    # 设置端口
    tcp_server.bind(('', 7788))
    # 设置端口复用
    tcp_server.setsockopt(SOL_SOCKET, SO_REUSEADDR, True)
    # 设置监听
    tcp_server.listen(128)

    while True:
        # 获取客户端连接
        tcp_client, client_host = tcp_server.accept()
        print("当前来连接的客户端是:")
        print(client_host)
        # 获取文件名
        file_name = tcp_client.recv(1024).decode('utf-8')
        print(file_name)
        # 传输文件
        # print(os.path.exists(file_name))
        if os.path.exists(file_name):
            with open(file_name, 'rb') as f:
                print(f)
                while True:
                    f_data = f.read(1024)
                    print(f_data)
                    if f_data:
                        tcp_client.send(f_data)
                    else:
                        print("文件传输完成...")
                        break
        else:
            tcp_client.send("文件不存在...".encode("utf-8"))

        # 关闭客户端流
        tcp_client.close()

    # 关闭服务端流
    # tcp_server.close()


    2.客户端:

#!/usr/bin/python3
#-*-coding:utf-8-*-

from socket import *

server_host = ("192.168.14.74", 7788)

if __name__ == '__main__':
    # 创建套接字
    tcp_client = socket(AF_INET, SOCK_STREAM)
    # 连接服务器
    tcp_client.connect(server_host)
    file_name = input("输入要下载的文件名:")
    tcp_client.send(file_name.encode("utf-8"))
    with open(file_name, "wb") as f:
        while True:
            # 接收文件
            recv_data = tcp_client.recv(1024)
            print(len(recv_data))
            if recv_data:
                f.write(recv_data)
                f.flush()
            else:
                print("下载完成...")
                break
    # 关流
    tcp_client.close()

标志位:

SYN: 表示连接请求 ACK: 表示确认 FIN: 表示关闭连接 seq:表示报文序号 ack: 表示确认序号

小结:

1.第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。

2.第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack (number )=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。

3.第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。

六、TCP的三次握手:
建立连接时产生三次握手

 

 

七、TCP的四次挥手:
在断开连接时发生四次挥手

小结:

1.第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送。

2.第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1。

3.第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送。

4.第四次挥手:Client收到FIN后,接着发送一个ACK给Server,确认序号为收到序号+1。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浅弋、璃鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值