网络编程

网络编程

1.ip地址的介绍

1.ip地址的概念

ip地址就是标识网络中设备的一个地址,好比现实生活中的家庭地址

2.ip地址的表现形式

1651159234177

说明:

  • ip地址分为两类:IPv4和IPv6
  • IPv4是目前使用的ip地址
  • IPv6是未来使用的ip地址
  • IPv4是由点分十进制组成
  • IPv6是由冒号十六进制组成

3.ip地址的作用

标识网络中唯一的一台设备,也就是说通过IP地址能够找到网络中某台设备

4.查看IP地址

  • Linux和macOS使用ifconfig这个命令
  • windows中使用ipconfig

1651159561363

  • 192.168.100.2是设备在网络中的IP地址
  • 127.0.0.1表示本机地址
  • 127.0.0.1该地址对应的域名是localhost,域名是IP地址的别名,通过域名能解析出一个对应的ip地址

5.检查网络是否正常

ping www.baidu.com

2.端口和端口号的介绍

1.什么是端口

端口是传输数据的通道,好比教师的们,是数据传输必经之路

每一个端口都会有一个对应的端口号,想要找到端口通过端口号即可

通过ip地址找到对应的设备,通过端口号找到对应的端口,然后通过端口把数据传输给应用程序

2.端口和端口号的关系

端口号可以标识唯一的一个端口

3.端口号的分类

  • 知名端口号

0-1023

  • 动态端口号

1024-65535

3.TCP的介绍

1.网络应用程序之间的通信地址

数据不能随便发送,在发送之前还需要选择一个对应的传输协议,保证程序之间按照指定的传输规则进行数据的通信

2.TCP的概念

简称传输控制协议,它是一种面向连接的、可靠的、基于字节流的传输层通信协议

TCP通信步骤:

  • 创建连接
  • 传输数据
  • 关闭连接

3.TCP的特点

  • 面向连接
    • 通信双方必须先建立连接才能进行数据的传输,数据传输完成后,双方必须断开连接,以释放系统子源
  • 可靠传输
    • TCP采用发送应答机制
    • 超时重传
    • 错误校验
    • 流量控制和阻塞管理

4.总结

TCP是一个稳定、可靠的传输协议,常用于对数据进行准确无误的传输,比如文件下载浏览器上网

网络程序通信的流程:

  • 通过ip地址找到网络中的设备
  • 通过端口号找到对应进程的端口
  • 传输数据时还需要使用传输协议(TCP),保证可靠性
  • socket完成进程之间网络数据的传输

4.socket的介绍

简称套接字,是进程之间通信的一个工具,进程之间想要进行网络通信需要基于socket

1651163160623

1.socket的作用

负责进程之间的网络数据传输,好比数据的搬运工

5.TCP网络应用程序开发流程

1.TCP网络应用程序开发流程的介绍

  • TCP客户端程序开发
  • TCP服务端程序开发

客户端程序是指运行在用户设备上的程序,服务端程序是指运行在服务器设备上的程序,专门为客户端提供数据服务

2.TCP客户端程序开发流程的介绍

1651163491741

步骤说明:

  • 创建客户端套接字对象
  • 和服务端套接字建立连接
  • 发送数据
  • 接收数据
  • 关闭客户端套接字

3.TCP服务端程序开发流程的介绍

1651163661878

步骤说明:

  • 创建服务端套接字对象
  • 绑定端口号
  • 设置监听
  • 等待接受客户端的连接请求
  • 接收数据
  • 发送数据
  • 关闭套接字

4.小结

  • TCP网络应用程序开发分为客户端程序开发和服务端程序开发
  • 主动发起连接请求是客户端程序
  • 等待接收连接请求的是服务端程序

6.TCP客户端程序开发

1.开发TCP客户端程序开发步骤

  • 创建客户端套接字对象
  • 和服务端套接字建立连接
  • 发送数据
  • 接收数据
  • 关闭客户端套接字

2.socket类的介绍

导入socket模块

import socket

创建客户端socket对象

socket.socket(AddressFamily,Type)

参数说明:

  • AddressFamily表示IP地址类型,分为IPV4和IPV6
  • Type表示传输协议类型

方法说明:

  • connect((host,port))表示和服务端套接字建立连接,host是服务器ip地址,port是应用程序的端口号
  • send(data)表示发送数据,data是二进制数据
  • recv(buffersize)表示接收数据,buffersize是每次接收数据的长度

3.TCP客户端程序开发示例代码

import socket

if __name__ == '__main__':

    # 1.创建TCP客户端套接字
    # AF_INET:ipv4地址类型
    # SOCK_STREAM:tcp传输协议类型
    tcp_client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    # 2.和服务端建立套接字连接
    tcp_client_socket.connect(("192.168.116.1",8080))
    # 3.发送数据到服务端
    # windows里面的网络调试助手使用的是gbk编码
    # linux里面的网络调试助手使用的是utf-8编码
    tcp_client_socket.send("hello你好".encode("gbk"))
    # 4.接收服务端的数据
    # 1024:表示每次接收的最大字节数
    recv_data = tcp_client_socket.recv(1024)
    # 对二进制数据进行解码
    print(recv_data.decode("gbk"))
    # 5.关闭套接字
    tcp_client_socket.close()

4.TCP服务端程序开发步骤

  • 创建服务端套接字对象
  • 绑定端口号
  • 设置监听
  • 等待接收客户端的连接请求
  • 接收数据
  • 发送数据
  • 关闭套接字

socket方法说明 :

  • bind((host,port))表示绑定端口号,host是ip地址,port是端口号,IP地址一般不指定,表示本机的任何一个ip地址都可以
  • listen(backlog)表示设置监听,backlog参数表示最大等待建立连接的个数
  • accept()表示等待接收客户端的连接请求
  • send(data)表示发送数据,data是二进制数据
  • recv(buffersize)表示接收数据,buffersize是每次接收数据的长度

5.TCP服务端程序开发实例代码

1651167311638

import socket
if __name__ == '__main__':
    # 1.创建tcp套接字对象
    # AF_INET:IPV4  AF_INET6:IPV6
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    # 设置端口号复用,表示意思:服务端程序退出端口号立即释放
    tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
    # 2.绑定端口号
    # 第一个参数表示ip地址,一般不用指定,表示本机的任何一个ip即可
    # 第二个参数表示借口好
    tcp_server_socket.bind(("",9090))
    # 3.设置监听
    # 128表示最大等待建立连接的个数
    tcp_server_socket.listen(128)
    # 4.等待接收客户端的连接请求
    # 注意:每次当客户端和服务端建立连接成功,都会返回一个新的套接字
    # tcp_server_socket只负责等待接收客户端的连接请求,收发消息不使用该套接字对象
    new_client,ip_port = tcp_server_socket.accept()
    # 代码执行到此,说明客户端和服务端建立连接成功
    print("客户端的ip和端口号:",ip_port)
    # 5.接收客户端的数据
    # 收发消息都是用返回的这个新的套接字
    recv_data = new_client.recv(1024)
    print("接收客户端的数据为",recv_data.decode("gbk"))
    # 6.发送数据到客户端
    new_client.send("嘿嘿嘿".encode("gbk"))
    # 关闭服务于客户端套接字,表示和客户端终止通信
    new_client.close()
    # 7.关闭套接字
    tcp_server_socket.close()

说明:

当客户端和服务端建立连接后,服务端程序退出后端口号不会立即释放,需要等待大概1-2分钟

解决办法有两种:

1.更换服务端端口号

2.设置端口号复用(推荐),也就是说让服务端程序退出后端口号立即释放。

设置端口号复用的代码如下:

# 参数1:表示当前套接字
# 参数2:设置端口号复用选项
# 参数3:设置端口号复用选项对应的值
tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)

7.TCP网络应用程序的注意点

1.TCP网络应用程序的注意点介绍

  • 当TCP客户端想要和TCP服务端程序进行通信的时候必须要先建立连接
  • TCP客户端程序一般不需要绑定端口号,因为客户端是主动发起建立连接的
  • TCP服务端程序必须绑定端口号,否则客户端找不到这个TCP服务端程序
  • listen后的套接字是被动套接字,只负责接收新的客户端的连接请求,不能收发消息
  • 当TCP客户端程序和TCP服务端程序连接成功后,TCP服务端程序会产生一个新的套接字,收发客户端消息使用该套接字
  • 关闭accept返回的套接字意味着和这个客户端已经通信完毕
  • 关闭listen后的套接字意味着服务端的套接字关闭了,会导致新的客户端不能连接服务端,但是之前已经接成功的客户端还能正常通信
  • 当客户端的套接字调用close后,服务端的recv会解阻塞,返回的数据长度为0,服务端可以通过返回数据长度来判断客户端是否已经下线,反之服务端关闭套接字,客户端的recv也会解阻塞,返回的数据长度为0

8.案例-多任务版本TCP服务端程序开发

1.需求

完成多任务,可以使用线程,比进程更加节省内存资源

2.具体实现步骤

  • 编写一个TCP服务端程序,循环等待接收客户端的连接请求
  • 当客户端和服务端建立成功,创建子线程,使用子线程专门处理客户端的请求,防止主线程阻塞
  • 把创建的子线程设置为守护主线程,防止主线程无法退出

3.代码实现

import socket
import threading

# 处理客户端请求的任务
def handle_client_request(ip_port,new_client):
    print("客户端的ip和端口号:", ip_port)
    while True:
        # 5.接收客户端的数据
        # 收发消息都是用返回的这个新的套接字
        recv_data = new_client.recv(1024)
        if recv_data:
            print("接收客户端的数据为", recv_data.decode("gbk"))
            # 6.发送数据到客户端
            new_client.send("嘿嘿嘿".encode("gbk"))
        else:
            break
    # 关闭服务于客户端套接字,表示和客户端终止通信
    new_client.close()


if __name__ == '__main__':
    # 1.创建tcp套接字对象
    # AF_INET:IPV4  AF_INET6:IPV6
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置端口号复用,表示意思:服务端程序退出端口号立即释放
    # 1.SOL_SOCKET:表示当前套接字
    # 2.SO_REUSEADDR:表示复用端口号的选项
    # 3.True:确定复用
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
    # 2.绑定端口号
    # 第一个参数表示ip地址,一般不用指定,表示本机的任何一个ip即可
    # 第二个参数表示借口好
    tcp_server_socket.bind(("", 9090))
    # 3.设置监听
    # 128表示最大等待建立连接的个数
    tcp_server_socket.listen(128)
    # 4.等待接收客户端的连接请求
    # 注意:每次当客户端和服务端建立连接成功,都会返回一个新的套接字
    # tcp_server_socket只负责等待接收客户端的连接请求,收发消息不使用该套接字对象
    # 循环等待接收客户端的连接请求
    while True:
        new_client, ip_port = tcp_server_socket.accept()
        # 代码执行到此,说明客户端和服务端建立连接成功
        # 当客户端和服务端建立连接成功,创建子线程,让子线程专门负责接收客户端的消息
        sub_thread = threading.Thread(target=handle_client_request,args=(ip_port,new_client))
        # 设置守护主线程,主线程退出子线程直接销毁
        sub_thread.setDaemon(daemonic=True)
        sub_thread.start()
        # 启动子线程执行对应的任务

    # 7.关闭套接字
    # tcp_server_socket.close()

9.socket之send和recv原理剖析

1.认识TCP socket的发送和接收缓冲区

当创建一个TCP socket对象的时候会有一个发送缓冲区和一个接收缓冲区,这个发送和接收缓冲区指的就是内存中的一片空间

2.send原理剖析

send是不是直接把数据发给服务端?

不是,要想发数据,必须得通过网卡发送数据,应用程序是无法直接通过网卡发送数据的,它需要调用操作系统接口,也就是说,应用程序把发送的数据先写入到发送缓冲区中,再由操作系统控制网卡把发送缓冲区中的数据发送给服务端网卡

3.recv原理剖析

recv是不是直接从客户端接收数据?

不是,应用软件是无法直接通过网卡接收数据的,它需要调用操作系统接口,由操作系统通过网卡接收数据,把接收的数据写入到接收缓冲区,应用程序再从接收缓存区获取客户端发送的数据

总结:

  • 发送数据是发送到发送缓冲区
  • 接收数据是从接收缓冲区 获取
posted @   子龙3000E  阅读(91)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示