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

python实现 socket套接字---UDP&TCP

程序员文章站 2022-07-08 08:57:57
...

Socket

socket简称套接字,是支持TCP/IP的网络通信的基本操作单元,可以看作是不同主机之间的进程进行双向通信的端点,简单的说就是通信两方的一种约定,用套接字的相关函数来完成通信过程。
python实现 socket套接字---UDP&TCP

UDP

UDP是面向无连接、基于数据报的不可靠传输。

  1. python中UDP发送端传输的步骤为:
    导入模块
    创捷套接字
    数据传输
    关闭套接字

代码如下:

# 1. 导入模块
import socket
# 2.创建套接字
# socket.socket(协议类型,传输方式)
# 参数一:
# socket.AP_INET 使用IPV4
# socket.AF_INET6 使用IPV6
# 参数二:
# socket.SOCK_DGRAM 使用UDP传输方式(无连接)
# socket。SOCK_STREAM 使用TCP传输方式(有连接)
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 3.数据传输
# udp_socket.sendto(要发送的数据的二进制格式,对方的IP和端口号)
# 参数一:要发送的二进制格式
# 字符串转换成二进制格式 字符串.encode()
# 参数二:对方的IP地址和端口号 address类型
# 要求IP和端口号是一个元组:1)第一个元素的字符串类型的ip地址,2)完整类型的端口号
udp_socket.sendto('hello'.encode('gbk'), ('121.248.154.5', 8080))
# 3.关闭套接字
udp_socket.close()
  1. UDP接收端步骤为
  • 导入模块
  • 创建套接字
  • 发送数据
  • 接收数据
  • 解码数据
  • 输出显示接收到的二进制字符串
  • 关闭套接字
# 导入模块
import socket
# 创建套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 绑定端口
addr = ('', 6666)
udp_socket.bind(addr)

# 发送数据
udp_socket.sendto('gram'.encode(), ('121.248.54.5', 8080))

# 接收数据
# recvfrom(1024)方法的作用:
# 1)从套接字中接受1024个字节的数据
# 2)此方法会造成程序的阻塞,等待另一台计算机发来数据
#    如果对方发数据了,recvfrom会自动解除阻塞
#    如果对方没有发送方数据,会一直等待
# rece_data= (b'hello',('192.168.171.30', 8080))
# rece_data[0 接受到的数据的二进制格式
# rece_data[1] 对方的ip和端口
# win默认gbk编码,linux默认utf-8编码
rece_data = udp_socket.recvfrom(1024)
rece_txt = rece_data[0].decode('gbk')
# 输出
print('来自:', rece_data[1], '的消息:', rece_txt)
# 关闭套接字
udp_socket.close()
  1. UDP广播
# 1.导入模块
import socket
# 2.创建套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 3.设置广播权限
# udp_socket.setsockopt(套接字,属性,属性值)
# SOL_SOCKET:当前的套接字
# SO_BROADCAST:广播属性
udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, True)

# 4.发送数据
# 默认不允许发送广播
udp_socket.sendto('helloworld'.encode(), ('255.255.255.255', 8080))
# 5.关闭套接字
udp_socket.close()

TCP

一.TCP是面向有连接、基于字节流、可靠的传输方式。

  1. TCP面向连接:
    通信双方都必须先建立连接才能进行数据传输,双方都必须为该连接分配必要的系统内核资源,以管理连接的状态和连接上的传输。
    双方间的数据传输都可以通过这一个连接进行,完成数据交换后,双方必须断开连接,以释放系统资源,这种连接是一对一的,因此TCP不适用与广播的应用程序,基于广播的应用程序使用UDP.
  2. TCP可靠传输
  • TCP采用应答机制
  • 超时重传
  • 错误校验
  • 流量控制和阻塞管理
  1. TCP和UDP不同点:
  • 面向连接
  • 有序数据传输
  • 重发丢失的数据包
  • 舍弃丢失的数据包
  • 无差错的数据传输
  • 阻塞/流量控制

二.TCP编程
TCP编程区分客户端和服务器:

  1. TCP客户端
"""
1. 导入模块
2. 创建套接字
3. 建立连接
4. 发送数据
5. 关闭连接
"""
# 1. 导入模块
import socket

# 2. 创建套接字
tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 3. 建立连接
# connet是一个元组类型,ip地址和端口号
tcp_client_socket.connect(('121.248.154.5', 8080))
# 4. 发送数据 以及接受
tcp_client_socket.send('hello'.encode('gbk'))
# rece_data是服务器发送给客户端的信息的二进制,而udp中输入的还有发送方的ip和端口号
recv_data = tcp_client_socket.recv(1024)
recv_text = recv_data.decode('gbk')
print(recv_text)
# 5. 关闭连接
tcp_client_socket.close()

  1. TCP服务器
"""
1 创建套接字
2 bind绑定ip和port
3 开启监听,开启套接字为被动模式
4 等待客户端连接
5 收发数据
6 关闭连接
"""
import socket

# 1 创建套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2 bind绑定ip和port
tcp_server_socket.bind(('', 8081))
# 3 开启监听,开启套接字为被动模式
# listen() 作用设置tcp_server_socket 套接字为被动监听模式,不能再主动发送数据,128是允许最大连接数
# window 下128有效,linux此数字无效
tcp_server_socket.listen(128)
# 4 等待客户端连接
# accept 开始接受客户端连接,程序会默认进入阻塞状态(等待客户端连接),如果由客户端连接后,程序自动解除阻塞
# recv_data返回有两个部分是一个元组
# 1)返回了一个新的套接字socket
# 2)返回了客户端的ip地址和端口号port
new_client_socket, client_ip_port = tcp_server_socket.accept()
print(new_client_socket, client_ip_port)
# 5 收发数据
# recv()会让程序再次阻塞
recv_data = new_client_socket.recv(1024)
recv_text = recv_data.decode('gbk')
print(recv_text)
# 不能呢在和当前的客户端通信了
new_client_socket.close()
# 6 关闭连接
tcp_server_socket.close()
  1. TCP服务器改进
"""
1 创建套接字
2 bind绑定ip和port
3 开启监听,开启套接字为被动模式
4 等待客户端连接
5 收发数据
6 关闭连接
"""
import socket

# 1 创建套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2 bind绑定ip和port
tcp_server_socket.bind(('', 8888))
# 3 开启监听,开启套接字为被动模式
# listen() 作用设置tcp_server_socket 套接字为被动监听模式,不能再主动发送数据,128是允许最大连接数
# window 下128有效,linux此数字无效
tcp_server_socket.listen(128)
# 4 等待客户端连接
# accept 开始接受客户端连接,程序会默认进入阻塞状态(等待客户端连接),如果由客户端连接后,程序自动解除阻塞
# recv_data返回有两个部分是一个元组
# 1)返回了一个新的套接字socket
# 2)返回了客户端的ip地址和端口号port

while True:
    new_client_socket, client_ip_port = tcp_server_socket.accept()
    print(new_client_socket, client_ip_port)

    # 5 收发数据
    # recv()会让程序再次阻塞
    while True:
        # 当接收到的数据为空的时候,表示客户端已经断开了,服务器也要断开
        recv_data = new_client_socket.recv(1024)
        if len(recv_data) != 0:
            recv_text = recv_data.decode('gbk')
            print(recv_text)
        else:
            print('客户端已经断开连接')
            break

# 不能再和当前的客户端通信了
new_client_socket.close()
# 6 关闭连接
tcp_server_socket.close()

"""
上面的程序只有当第一个客户端断开连接时第二个客户端才能和tcp服务器建立连接;
改进的话需要使用多线程
"""