欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python socket编程(2)

程序员文章站 2022-07-11 11:41:15
...

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通信:
Python socket编程(2)
tcp通信:
Python socket编程(2)

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

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

相关标签: socket python