TCP的通信过程

3. TCP 通信过程

3.1 编码解码

ipython3 工具安装 pip3 install ipython3

s = "hello dage"
# str类型  不能直接在网络中传输  如果需要传输需要转换为 Bytes 二进制 字节类型
# utf-8编码情况 一个汉字 3 个字节 ; GBK 编码情况下  一个汉字 2 字节

s1 = "hello大哥"
# str-编码-> bytes  二进制数据 = 字符串数据.encode(encoding='utf-8')
In [8]: b2 = s1.encode('utf-8')

In [9]: type(b2)
Out[9]: bytes
In [10]: b2
Out[10]: b'hello\xe5\xa4\xa7\xe5\x93\xa5'
    
In [13]: b3 = s1.encode('gbk')
In [14]: b3
Out[14]: b'hello\xb4\xf3\xb8\xe7'

# bytes-解码->str   字符串数据 = 二进制数据.decode(encoding='utf-8')
# 解码时的方案 一定要和此数据在编码时的方案保持一致   否则就会出错(异常或数据错误)
In [22]: b3.decode('gbk')
Out[22]: 'hello大哥'

3.2 客户端通信

import socket

if __name__ == '__main__':
    # 1 创建TCP套接字  参数1是地址协议版本 IPv4   参数2是套接字类型  基于字节流Stream
    tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 2 建立和服务器的连接 - 面向连接的协议  参数是服务器IP和服务器端口构成的元组
    tcp_socket.connect(('172.16.51.151', 8080))
    # 3 发送数据  参数就是需要发送的字节数据
    tcp_socket.send("黑服你".encode())

    # 4 接收数据  参数是需要接收数据的最大字节数  返回值就是接收到的数据<字节数据>
    # 如果对方断开了连接  接收的数据将b''  长度是0
    ret = tcp_socket.recv(1024)
    if len(ret) == 0:
        print("对方断开连接了")
        # print(ret)
    else:
        print("接收到了来自服务器的数据 %s" % ret.decode())

    # 5 关闭连接 关闭套接字
    tcp_socket.close()

3.3 服务器通信

# TCP 服务器和多个用户循环通信
import socket


# echo回射服务器 将接收到的数据原封不动反弹回客户端
if __name__ == '__main__':
    # 1 创建一个服务器套接字(大堂经理)  IPv4           基于字节流
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 2 固定端口   IP=''表示本机所有IP
    server_socket.bind(('', 8888))

    # 3 监听   设置等待服务区(已经连通的但是尚未被服务的套接字) 经验值128
    server_socket.listen(128)

    # 4 循环接受一个新用户的连接请求 分配到和客户端关联的套接字 业务员
    while True:
        client_socket, client_address = server_socket.accept()
        print("有客官来了 业务来了")
        # (<socket.socket>业务员 , 客户端地址元组('172.16.51.151', 45970))
        # print(ret)

        # 5 由业务员负责给客户端服务 处理请求数据
        while True:
            data = client_socket.recv(4096)
            print("客户端%s发送了%s" % (str(client_address),data.decode()))

            # if len(data) == 0:  # b'' None
            if not data:
                # 6 关闭和客户端关联的套接字 业务员
                client_socket.close()
                break
            client_socket.send(data)


    # 7 关闭服务区套接字   大堂经理
    # server_socket.close()

TCP 相关知识点梳理

调试助手 windows版本 发送出来的数据是 GBK 编码 收 UTF-8编码

data = recv(4096)

send(data.deocde(‘GBK’).encode(‘UTF-8’))

b’’ b’ ’

3.4 Address already in use问题解决

  • 权宜办法

    换端口

  • 原理: TCP 标准规定

​ 为了保证最后一次 ACK 成功送达 连接完全断开

​ 凡是主动断开连接的一方

​ 套接字相关资源(端口) 必须保持 2MSL 时间 30s-2min

  • 解决方案

​ 地址重用 立即忽略 2MSL 时间

​ # 设置套接字选项 套接字选项 地址重用 1 表示设置

​ 套接字对象.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

3.5 多任务版本TCP服务器

import socket
import threading


def client_request(client_socket, client_address):
    """处理客户端请求的函数"""
    # 5 由业务员负责给客户端服务 处理请求数据
    while True:
        data = client_socket.recv(4096)
        print("客户端%s发送了%s" % (str(client_address), data.decode()))

        # if len(data) == 0:  # b'' None
        if not data:
            # 6 关闭和客户端关联的套接字 业务员
            client_socket.close()
            break
        client_socket.send(data)


# echo回射服务器 将接收到的数据原封不动反弹回客户端
if __name__ == '__main__':
    # 1 创建一个服务器套接字(大堂经理)  IPv4           基于字节流
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 设置套接字选项   作用: 立即重用端口  不需要等待30s-2min
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

    # 2 固定端口   IP=''表示本机所有IP
    server_socket.bind(('', 8888))

    # 3 监听   设置等待服务区(已经连通的但是尚未被服务的套接字) 经验值128
    server_socket.listen(128)

    # 4 循环接受一个新用户的连接请求 分配到和客户端关联的套接字 业务员
    while True:
        client_socket, client_address = server_socket.accept()
        print("有客官来了 业务来了")
        # (<socket.socket>业务员 , 客户端地址元组('172.16.51.151', 45970))
        # print(ret)
        # client_request(client_socket)
        # 创建一个子线程 运行 处理客户端请求的函数
        thd = threading.Thread(target=client_request, args=(client_socket,client_address))
        thd.start()

    # 7 关闭服务区套接字   大堂经理
    # server_socket.close()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值