Python socket编程(2)

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()

与之前的文字信息的发送接受添加的只是文件的读取写入,所以这里便不进行重复解释了。

发布了24 篇原创文章 · 获赞 2 · 访问量 416

猜你喜欢

转载自blog.csdn.net/weixin_45735361/article/details/104011784