首页 > 编程语言 >网络编程--python

网络编程--python

时间:2024-09-04 21:24:25浏览次数:7  
标签:__ 服务器端 -- recv 编程 python 客户端 data socket

网络编程

1、介绍

(一)、概述

网络编程也叫套接字编程, Socket编程, 就是用来实现 网络互联的 不同计算机上 运行的程序间 可以进行数据交互

(二)、三要素

  • IP地址: 设备(电脑, 手机, IPad, 耳机…)在网络中的唯一标识.

  • 端口号: 程序在设备上的唯一标识.

  • 协议: 通信(传输)规则

(三)、ip

概述

设备(电脑, 手机, IPad, 耳机…)在网络中的唯一标识

分类

  • 按照 代数 划分:
    IPv4: 4字节, 十进制来表示, 例如: 192.168.13.157
    IPv6: 8字节, 十六进制来表示, 理论上来讲, 可以让地球上的每一粒沙子都有自己的IP.

  • 按照 Ipv4 常用类别划分:
    城域网: 第1段是网络地址 + 后3段是主机地址, 例如: 10.0.0.0
    广域网: 前2段是网络地址 + 后2段是主机地址, 例如: 10.21.0.0
    局域网: 前3段是网络地址 + 后1段是主机地址, 例如: 192.168.13.*

命令

  • 查看本机的IP:
    ipconfig 适用于 windows系统
    ifconfig 适用于 linux系统, Mac系统
  • 测试网络连接是否通畅:
    ping 主机地址 或者 域名

(四)、端口号

端口:   传输数据的通道, 每个程序都有.  类似于: 每个教室都有自己的门.
端口号: 程序在设备上的唯一标识.
范围:   0 ~ 65535, 其中0 ~ 1023已经被系统占用或者用作保留端口, 你自己在使用的时候, 尽量规避这个号段.

(五)、协议

协议有很多种,这里取最常见的TCP(Transmission Control Protocol)和UDP(User Datagram Protocol)来举例介绍。

作用

通信双方都要遵守的通信规则

特点

  • TCP
1. 面向有连接的.
2. 采用 流的方式传输数据, 理论上无大小限制.
3. 安全(可靠)协议.
4. 效率相对较低.
5. 区分客户端 和 服务器端.
  • UDP
1. 面向无连接.
2. 采用 数据包 的方式传输数据, 有大小限制(每个包不超过64KB).
3. 不安全(不可靠)协议.
4. 效率相对较高.
5. 不区分客户端 和 服务器端, 叫: 发送端和接收端.

三次握手

1. 客户端像服务器端发出请求, 申请建立连接.
2. 服务器端校验客户端数据合法后, 给出客户端回执信息, 可以建立连接.
3. 客户端重新向服务器端发出请求, 建立连接.

四次挥手

因为TCP协议是双向的, 需要两个方向都断开, 即: A => B,   B => A

命令行

查看本机端口号和协议:  netstat -ano   如果是Linux或者Mac, netstat -anp     all network Protocol(所有的网络端口)

(六)、socket通信

原理

通信两端都有自己的socket对象,数据在两个socket之间通过字节流(TCP)或者数据包(UDP)的方式传输。

服务器端

1. 创建服务器端Socket对象.
2. 绑定(服务器端的)ip和端口号, 元组形式.
3. 设置监听数量.
4. 等待客户端申请建立连接, 如果有客户端申请建立连接, 校验数据合法后, 会返回1个: (负责和该客户端交互的socket对象, 客户端的信息) 元组
5. 给客户端发送数据.        字节形式.
6. 接收客户端发送的数据.     字节形式.
7. 释放资源.

客户端

1. 创建客户端Socket对象.
2. 连接(服务器端的)ip和端口号, 元组形式.
3. 发送数据给服务器端.
4. 接受服务器端发送的数据.  回执信息.
5. 释放资源.

2、socket

(一)、创建socket对象

# 创建对象.
# object: 对象的意思
# 参1: Address Family: 地址族, 指定IP地址的协议, IPV4, IPV6, UNIX...
# 参2: Socket Type: 指定套接字的类型, TCP, UDP, UNIX...
# 这里的: socket.AF_INET: 指的是IpV4,  socket.SOCK_STREAM: 指的是 字节流的方式.
socket_obj = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

(二)、编解码

编解码指的是  字符串 和 二进制数据之间相互转换.
编码: 字符串(我们能看懂的) ==> 二进制(计算机能看懂)
解码: 二进制(计算机能看懂) ==> 字符串(我们能看懂的)

(三)、收发一句话

客户端

import socket

# 在main中测试.
if __name__ == '__main__':
    # 1. 创建客户端Socket对象, 指定: 地址族, 传输类型.
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 2. 连接(服务器端)地址和端口.
    client_socket.connect(("127.0.0.1", 2121))
    # 3. 接受服务器端发送的数据并打印.
    # 分解版
    # recv_data_bys = client_socket.recv(1024)
    # recv_data = recv_data_bys.decode("utf-8")
    # 合并版
    recv_data = client_socket.recv(1024).decode("utf-8")
    print(f'客户端收到: {recv_data}')
    # 4. 给服务器端发送数据(回执信息).
    client_socket.send('有内鬼, 终止交易! Over'.encode("utf-8"))
    # 5. 关闭Socket对象.
    client_socket.close()

服务器端

import socket

# 在main中编写.
if __name__ == '__main__':
    # 1. 创建服务器端Socket对象, 指定: 地址族, 传输类型.
    # 参1: IPV4,  参2: 字节流
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 2. 绑定地址和端口.
    server_socket.bind(("127.0.0.1", 2121))
    # 3. 设置监听数量.    范围: 1 ~ 128
    server_socket.listen(5)
    # 4. 等待客户端连接, 如有连接, 则返回: (和客户端交互的Socket对象, 客户端地址)
    print('等待客户端连接中.....')
    accept_socket, client_info = server_socket.accept()
    # 5. 给客户端发送数据.
    # accept_socket.send('Welcome to study socket!'.encode('utf-8'))
    accept_socket.send(b'Welcome to study socket!')

    # 6. 接受客户端发送的数据并打印.
    recv_data_bys = accept_socket.recv(1024)        # receive: 接收,  一次读取1024个字节
    # 把字节转成字符串, 并打印.
    recv_data = recv_data_bys.decode('utf-8')
    print(f'服务器端收到 {client_info} 发送的信息: {recv_data}')

    # 7. 关闭Socket对象.
    accept_socket.close()       # 一般只关闭 和客户端交互的socket对象.
    # server_socket.close()     # 服务器端socket对象一般不关闭.

上面的服务器收到一句话后,就会自动断开,不是很合理,优化为可以一次接收多个人的消息(同一时刻只能连接一个人),不主动结束。

服务器端接收多客户端消息

import socket

# 在main中编写.
if __name__ == '__main__':
    # 1. 创建服务器端Socket对象, 指定: 地址族, 传输类型.
    # 参1: IPV4,  参2: 字节流
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 2. 绑定地址和端口.
    server_socket.bind(("127.0.0.1", 2121))
    # 3. 设置监听数量.    范围: 1 ~ 128
    server_socket.listen(5)

    while True:
        try:
            # 4. 等待客户端连接, 如有连接, 则返回: (和客户端交互的Socket对象, 客户端地址)
            accept_socket, client_info = server_socket.accept()
            # 5. 给客户端发送数据.
            # accept_socket.send('Welcome to study socket!'.encode('utf-8'))
            accept_socket.send(b'Welcome to study socket!')

            # 6. 接受客户端发送的数据并打印.
            recv_data_bys = accept_socket.recv(1024)        # receive: 接收,  一次读取1024个字节
            # 把字节转成字符串, 并打印.
            recv_data = recv_data_bys.decode('utf-8')
            print(f'服务器端收到 {client_info} 发送的信息: {recv_data}')

            # 7. 关闭Socket对象.
            accept_socket.close()       # 一般只关闭 和客户端交互的socket对象.
            # server_socket.close()     # 服务器端socket对象一般不关闭.
        except:
            pass

此时客户端发送一句就会自动结束,而服务器端会一直运行,直到手动停止。平时我们发送消息时,一般主动结束才会结束,因此可以对代码做以下调整。

(四)、长连接

客户端和服务器端成功连接后, 可以一直收发数据, 而不用频繁的创建和销毁Socket对象.可以选择合适的时机, 销毁Socket对象

需求

客户端不断地给服务器端发送数据, 服务器端收到后并打印. 直至客户端发送 “886”, 结束程序

客户端

import socket

if __name__ == '__main__':
    # 1. 创建客户端Socket对象.
    cli_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 2. 连接服务器端. ip 和 端口号
    cli_socket.connect(("127.0.0.1", 6666))

    # 3. 发送数据到服务器端.
    while True:
        # 3.1 提示用户录入要发送的数据, 并接收.
        data = input('请录入要发送的数据: ')
        # 3.2 将其转成二进制形式, 发送给服务器端.
        cli_socket.send(data.encode("utf-8"))
        # 3.3 判断用户是否要退出.
        if data == "886":
            break

    # 4. 释放资源.
    cli_socket.close()

服务器端

import socket

if __name__ == '__main__':
    # 1. 创建服务器端Socket对象.
    ser_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 2. 绑定服务器端ip 和 端口号.
    ser_socket.bind(("127.0.0.1", 6666))
    # 3. 设置监听连接数.
    ser_socket.listen(5)
    # 4. 启动监听, 等待客户端建立连接.
    accept_socket, client_info = ser_socket.accept()

    # 5. 接收客户端发送的信息.
    while True:
        # 5.1 接收客户端发送的信息(二进制形式 => 字符串)
        recv_data = accept_socket.recv(1024).decode("utf-8")
        # 5.2 打印接收到的客户端的消息.
        print(f'服务器端收到: {recv_data}')
        # 5.3 判断客户端是否发送了"886", 如果是, 结束程序.
        if recv_data == "886":
            break

    # 6. 释放资源.
    accept_socket.close()

(五)、文件上传

客户端

import socket

if __name__ == '__main__':
    # 1. 创建客户端Socket对象.
    cli_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 2. 连接服务器端. ip 和 端口号
    cli_socket.connect(("127.0.0.1", 8888))
    # 3. 读取数据源文件的信息, 并发送数据到服务器端.
    # with open('d:/绕口令.txt', 'rb') as src_f:
    with open('d:/图片/a.jpg', 'rb') as src_f:
        # 扩展: 你也可以考虑先把文件名发给服务器端, 然后再上传文件.
        # cli_socket.send('绕口令.txt'.encode('utf-8'))
        # 3.1 分批次读取, 一次读取 1024个字节.
        while True:
            # 3.2 具体的从文件中读取数据的动作.
            data = src_f.read(1024)
            # 3.3 将读取到的数据写给 => 服务器端.
            cli_socket.send(data)
            # 3.4 判断是否读取完毕.
            if len(data) <= 0:
                break
    # 5. 释放资源.
    cli_socket.close()

服务器端

import socket

if __name__ == '__main__':
    # 1. 创建服务器端Socket对象.
    ser_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 2. 绑定服务器端ip 和 端口号.
    ser_socket.bind(("127.0.0.1", 8888))
    # 3. 设置监听连接数.
    ser_socket.listen(10)
    # 4. 启动监听, 等待客户端建立连接.
    accept_socket, client_info = ser_socket.accept()

    # 5. 接收客户端的回执信息.
    # 5.1 关联目的地文件, 用于把客户端的数据写到该文件中.
    with open('./data/文件.txt', 'wb') as dest_f:
        # 5.2 循环接收客户端写过来的文件数据.
        while True:
            # 5.3 具体的接收客户端数据的动作.
            recv_data = accept_socket.recv(1024)
            # 5.4 判断读取到的数据是否为空, 为空, 说明文件传输完毕.
            if len(recv_data) <= 0:
                break
            # 5.5 把读取到的数据写入到目的地文件中.
            dest_f.write(recv_data)

    # 7. 释放资源.
    accept_socket.close()

在现实使用过程中,多个客户端会往服务器端发送文件,因此我们需要改造一下服务器端代码。

服务器端持续监听

import socket

if __name__ == '__main__':
    # 1. 创建服务器端Socket对象.
    ser_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 2. 绑定服务器端ip 和 端口号.
    ser_socket.bind(("120.0.0.1", 8888))
    # 3. 设置监听连接数.
    ser_socket.listen(10)

    try:
        count = 0  # 计数变量.
        while True:
            count += 1  # 走到这里, 说明是1个新文件.
            # 拼接文件名
            file_name = './data/文件_' + str(count) + '.jpg'
            # 4. 启动监听, 等待客户端建立连接.
            accept_socket, client_info = ser_socket.accept()
            # 5. 接收客户端的回执信息.
            # 5.1 关联目的地文件, 用于把客户端的数据写到该文件中.
            with open(file_name, 'wb') as dest_f:
                # 5.2 循环接收客户端写过来的文件数据.
                while True:
                    # 5.3 具体的接收客户端数据的动作.
                    recv_data = accept_socket.recv(8192)
                    # 5.4 判断读取到的数据是否为空, 为空, 说明文件传输完毕.
                    if len(recv_data) <= 0:
                        break
                    # 5.5 把读取到的数据写入到目的地文件中.
                    dest_f.write(recv_data)
            # 走到这里, 说明文件传输完毕.
            print(f'服务器端收到 {client_info} 上传文件成功!')
            # 7. 释放资源.
            accept_socket.close()
    except:
        pass

标签:__,服务器端,--,recv,编程,python,客户端,data,socket
From: https://blog.csdn.net/egglikeFe/article/details/141904505

相关文章

  • 【深度学习】代码复现基础--conda环境配置(pytorch)
    0.需求做实验阶段经常需要复现代码,要从github上把代码克隆下来,然后按照里头的readme文件配置环境【主要是pytorch】。电脑本身已经装好了Anaconda和开发工具,这个过程其实很简单,只是一些语句,但具体细节经常会忘,每次又要反复查,网上查着又都是从0开始的,且很多为比较旧的教程,因此......
  • 【Java】ApiPost请求返回 `406` 状态码(jackson)
    Java系列文章目录补充内容Windows通过SSH连接Linux第一章Linux基本命令的学习与Linux历史文章目录Java系列文章目录一、前言二、学习内容:三、问题描述3.1问题截图3.2错误简介3.2.1HTTP状态码`406NotAcceptable`3.2.2序列化和反序列化3.3后端问题位置四......
  • 基于迭代扩展卡尔曼滤波算法的倒立摆控制系统matlab仿真
    1.课题概述基于迭代扩展卡尔曼滤波算法的倒立摆控制系统,对比UKF,EKF迭代UKF,迭代EKF四种卡尔曼滤波的控制效果。2.系统仿真结果3.核心程序与模型版本:MATLAB2022aX_iukf=zeros(2,Times1);X_iukf(:,1)=state0;P_iukf=zeros(2,2,Times1);P_iukf(:,:,1......
  • 基于GA遗传优化的离散交通网络双层规划模型设计matlab仿真
    1.程序功能描述基于GA遗传优化的离散交通网络双层规划模型设计.优化输出路段1和路段2的收费情况收敛过程。2.测试软件版本以及运行结果展示MATLAB2022a版本运行3.核心程序rng(gen)genP1=0.9;P2=1-P1;FitnV=ranking(Objv);......
  • PointNet++改进策略 :模块改进 | PAConv,位置自适应卷积提升精度
    题目:PAConv:PositionAdaptiveConvolutionwithDynamicKernelAssemblingonPointClouds来源:CVPR2021机构:香港大学论文:https://arxiv.org/abs/2103.14635代码:https://github.com/CVMI-Lab/PAConv前言PAConv,全称为位置自适应卷积(PositionAdaptiveConvolution),是一种......
  • 【python因果推断库6】使用 pymc 模型的工具变量建模 (IV)1
    目录使用pymc模型的工具变量建模(IV)使用pymc模型的工具变量建模(IV)这份笔记展示了一个使用工具变量模型(InstrumentalVariable,IV)的例子。我们将会遵循Acemoglu,Johnson和Robinson(2001)的一个案例研究,该研究尝试解开强大的政治机构对于以国内生产总值(GDP)......
  • 计算机毕业设计:Java旅游景区订票售票系统开题报告+源代码效果图
     博主介绍:黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。所有项目都配有从入门到精通的基础知识视频课程,学习后应对毕业设计答辩。项目配有对应开发文档、开题报告、任务书、P......
  • Python | 爬虫实战——亚马逊搜索页监控(附详细源码)
    背景做亚马逊店铺,如果你的品卖爆了,免不得遇到被人跟品、广告关键词竞争甚至是恶意投诉等事情。如果靠人去检查产品是否正常,存在不及时的问题。所以,基本都会想要有一个自动检测的工具。一般是自动根据关键词,设置邮编,查看对应市场下的搜索结果页是否,然后进一步判断搜索结构页......
  • MathType免费安装公众号
    ......
  • mathtype7破解版下载安装!附带免费激活码许可证
    ......