[华为云在线课程][Python网络编程][Python网络编程][二][学习笔记]

举报
John2021 发表于 2022/05/30 05:33:17 2022/05/30
【摘要】 1.Python网络编程 1.1.Socket简介Socket套接字是对TCP/IP协议的封装,自身而非协议而是一套调用的接口规范(API)。Socket一般分为TCP网络编程和UDP网络编程。 1.2.Python中的网络编程Python提供了两个级别访问的网络服务:低级别的网络服务支持基本的Socket,提供了标准的BSD Sockets API,可以访问底层操作系统Socket接口的...

1.Python网络编程

1.1.Socket简介

Socket套接字是对TCP/IP协议的封装,自身而非协议而是一套调用的接口规范(API)。Socket一般分为TCP网络编程和UDP网络编程。

1.2.Python中的网络编程

Python提供了两个级别访问的网络服务:

  • 低级别的网络服务支持基本的Socket,提供了标准的BSD Sockets API,可以访问底层操作系统Socket接口的全部方法。
  • 高级别网络服务模块SocketServer,提供了服务器中心类,可以简化网络服务器的开发。

Python还具有提供对特定应用级网络协议(如FTP,HTTP等)的更高级别访问的库。

1.3.Python Socket模块

Python中的Socket模块,可以简单快捷的实现基础的网络通信,Socket模块中提供了以下属性和方法:

  • 创建Socket
  • 地址绑定
  • TCP、UDP协议实现
  • 接收、发送数据

1.4.创建socket

socket.socket([family[,type[,proto]]]):创建套接字

  • family:套接字家族可以使AF_UNIX或者AF_INET
  • type:套接字类型可以根据是面向连接的还是非连接分为SOCK_STREAM或者SOCK_DGRAM
  • s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

1.5.服务器端常用方法和属性

绑定主机地址和端口号

  • host=socket.gethostname() #获取本地主机名
  • s.bind((host,port)) #绑定地址和端口

开始TCP监听(转化为被动连接)

  • s.listen(n) #n至少为1

接受客户端连接

  • s.accept() #等待连接

主动初始化TCP服务器连接

  • s.connect(address)
  • address:host,port

接收数据

  • s.recv(bufsize[,flags]) #从套接字接收TCP数据,返回字节对象。bufsize指定一次接收的最大数据量
  • s.recvfrom(bufsize[,flags]) #接收UDP数据,与revc()类似,返回值为字节对象和地址(bytes,address)

1.6.通用方法

发送数据

  • s.send(bytes,[,flags]) #发送数据给套接字
  • s.sendall(bytes[,flags]) #持续从bytes发送数据,直到所有数据都已发送或发生错误为止(成功返回None,失败则抛出异常)
  • s.sendto(bytes,address) #发送UDP数组,将数据发送到套接字,address是形式为(ipaddr,port)的元组。返回值是发送的字节数
  • s.sendfile(file,offset=0,count=None) #发送文件

关闭socket

  • s.close()

获取socket地址

  • s.getpeername() #返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)
  • s.getsockname() #返回套接字自己的地址

设置连接超时时间

  • s.settimeout(timeout) #设置套接字操作的超时期,单位为s

1.7.UDP通信流程

服务器端

  • 创建socket
  • 绑定地址
  • 发送/接收数据
  • 关闭

客户端

  • 创建socket
  • 接收/发送
  • 关闭

1.8.UDP通信实现

创建socket

  • udp_socket=socket(AF_INET,SOCK_DGRAM)

绑定地址相关信息

  • udp_socket.bind(local_addr) #可选

等待接收/发送数据

  • recv_data=udp_socket.recvfrom(1024)

关闭套接字

  • udp_socket.close()

1.9.TCP通信流程

服务器端

  • 创建socket
  • 绑定端口
  • 转化为被动连接
  • 接收客户端连接
  • 接收/发送数据
  • 关闭

客户端

  • 创建socket
  • 连接服务器
  • 发送/接收数据
  • 关闭

1.10.TCP通信实现

TCP服务器

  • 创建socket:tcp_server=socket(AF_INET,SOCK_STREAM)
  • 绑定地址:tcp_server.bind(address)
  • 被动连接:tcp_server.listen(128)
  • 等待客户端连接:client_socket,clientAddr=tcp_server_.accept()
  • 接收/发送数据:recv_data=client_socket.recv(1024)
  • 关闭socket:client_socket.close()

2.socket UDP实验

2.1.新建工程

在PyCharm中新建工程后新建文件夹UDP,在里面新建.py文件

2.2.实现简单的UDP客户端通信程序

编写udp_client.py

from socket import *

udp_socket = socket(AF_INET, SOCK_DGRAM)

dest_addr = ('127.0.0.1', 2233)  # 测试脚本或者网络调试助手所在主机的地址

udp_socket.sendto('你好'.encode('utf8'), dest_addr)
udp_socket.sendto('你好'.encode('utf8'), dest_addr)
udp_socket.close()

编写测试udp_server.py

from socket import *

udp_socket = socket(AF_INET, SOCK_DGRAM)

udp_socket.bind('127.0.0.1', 2233)  # 绑定要测试的IP地址

recv_data, addr = udp_socket.recvfrom(1024)  # 1024表示本次接收的最大字节数
print('收到%s:%s发来的信息 -- %s' % (addr[0], addr[1], recv_data))

recv_data, addr = udp_socket.recvfrom(1024)  # 1024表示本次接收的最大字节数
print('收到%s:%s发来的信息 -- %s' % (addr[0], addr[1], recv_data))

udp_socket.close()

运行测试脚本

python udp_server.py

运行udp_client.py

python udp_client.py

测试脚本输出:

收到127.0.0.1:64546发来的信息 -- b'\xe4\xbd\xa0\xe5\xa5\xbd'
收到127.0.0.1:64546发来的信息 -- 你好

收到127.0.0.1:54945发来的信息 -- b'\xe4\xbd\xa0\xe5\xa5\xbd'
收到127.0.0.1:54945发来的信息 -- 你好

2.3.绑定端口号

发现端口号每次都不固定,如果想绑定端口号,要在客户端更改代码

from socket import *

udp_socket = socket(AF_INET, SOCK_DGRAM)
dest_addr = ('127.0.0.1', 2233)  # 创建套接字
bind_dest_addr = ('', 2233)  # 要绑定的端口号
udp_socket.bind(bind_dest_addr)  # 进行绑定
udp_socket.sendto('你好'.encode('utf8'), dest_addr)
udp_socket.sendto('你好'.encode('utf8'), dest_addr)
udp_socket.close()

输出结果:

收到127.0.0.1:2233发来的信息 -- b'\xe4\xbd\xa0\xe5\xa5\xbd'
收到127.0.0.1:2233发来的信息 -- 你好

收到127.0.0.1:2233发来的信息 -- b'\xe4\xbd\xa0\xe5\xa5\xbd'
收到127.0.0.1:2233发来的信息 -- 你好

3.socket TCP实验

3.1.新建文件

在PyCharm中新建工程后新建文件夹TCP,在里面新建.py文件

3.2.实现TCP服务器端程序

新建文件tcp_server.py

from socket import *

# 创建socket
tcp_server_socket = socket(AF_INET, SOCK_STREAM)
# 本地信息
address = ('', 7788)
# 绑定
tcp_server_socket.bind(address)
# 使用socket创建的套接字默认的属性是主动的,使用listen将其变为被动的,这样就可以接收别人的链接了
tcp_server_socket.listen(128)
# 如果有新的客户端来链接服务器,那么就产生一个新的套接字专门为这个客户端服务
# client_socket 用来为这个客户端服务
# tcp_server_socket 就可以省下来专门等待其他新客户端的链接
client_socket, clientAddr = tcp_server_socket.accept()
# 接收对方发送过来的数据
recv_data = client_socket.recv(1024)  # 接收1024个字节
print('接收到的数据为:', recv_data.decode('gbk'))
# 发送一些数据到客户端
client_socket.send('thank you!'.encode('gbk'))
# 关闭为这个客户端服务的套接字,只要关闭了,就意味着不能再为这个客户端服务了,如果还需要服务,只能再次重新连接
client_socket.close()

3.3.实现TCP客户端程序

新建文件tcp_client.py

from socket import *
# 创建socket
tcp_client_socket=socket(AF_INET,SOCK_STREAM)
# 目的信息
server_ip=input('请输入服务器ip:')
server_port=int(input('请输入服务器port:'))
# 链接服务器
tcp_client_socket.connect((server_ip,server_port))
# 提示用户输入数据
send_data=input('请输入要发送的数据:')
tcp_client_socket.send(send_data.encode('gbk'))
# 接收对方发送出来的数据,最大接收1024个字节
recvData=tcp_client_socket.recv(1024)
print('接收到的数据为:',recvData.decode('gbk'))
# 关闭套接字
tcp_client_socket.close()

客户端结果

请输入服务器ip:127.0.0.1
请输入服务器port:7788
请输入要发送的数据:HELLO
接收到的数据为: thank you!

服务端结果

接收到的数据为: HELLO

3.4.TCP文件服务器实践

基于socket模块和TCP协议实现文件下载程序的服务器端和客户端。
新建脚本文件tcp_server_file.py

from socket import *
import sys

from TCP.tcp_server import tcp_server_socket


def get_file_content(file_name):
    """获取文件内容"""
    try:
        with open(file_name, "rb") as f:
            content = f.read()
        return content
    except:
        print("下载异常:%s" % file_name)


def main():
    if len(sys.argv) != 2:
        port = 2333
    else:
        port = int(sys.argv[1])
    # 创建socket
    tcp_server_socket = socket(AF_INET, SOCK_STREAM)
    # 本地信息
    address = ('', port)
    # 绑定本地信息
    tcp_server_socket.bind(address)
    # 将主动套接字变成被动套接字
    tcp_server_socket.listen(128)

    while True:
        # 等待客户端的链接,即为这个客户端发送文件
        client_socket, clientAddr = tcp_server_socket.accept()
        # 接收对方发送过来的数据
        recv_data = client_socket.recv(1024)  # 接收1024个字节
        file_name = recv_data.decode('utf-8')
        print('对方请求下载的文件名为:%s' % file_name)
        file_content = get_file_content(file_name)
        # 发送文件的数据给客户端
        # 因为获取打开文件时是以rb方式打开,所以file_content中的数据已经是二进制的格式,因此不需要encode编码
        if file_content:
            client_socket.send(file_content)
        # 关闭这个套接字
        client_socket.close()

    # 关闭监听套接字
    tcp_server_socket.close()


if __name__ == "__main__":
    main()

客户端程序tcp_client_file.py

from socket import *


def main():
    # 创建socket
    tcp_client_socket = socket(AF_INET, SOCK_STREAM)
    # 目的信息
    server_ip = input("请输入服务器ip:")
    server_port = int(input("请输入服务器port:"))
    # 链接服务器
    tcp_client_socket.connect((server_ip, server_port))
    # 输入需要下载的文件名
    file_name = input("请输入要下载的文件名:")
    # 发送文件下载请求
    tcp_client_socket.send(file_name.encode('utf-8'))
    # 接收对方发送过来的数据,最大接收1024个字节(1K)
    recv_data = tcp_client_socket.recv(1024)
    # 如果接收到数据再创建文件,否则不创建
    if recv_data:
        with open('[接收]' + file_name, 'wb') as f:
            f.write(recv_data)
    # 关闭套接字
    tcp_client_socket.close()


if __name__ == "__main__":
    main()
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。