网络编程基础(Python语言实现)

本文介绍了网络通信的基本概念,TCP/IP协议族的工作原理,并详细解析了Socket编程在TCP和UDP协议下的实现方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

网络通信概述

什么是网络?
网络就是一种辅助双法或者多方能连接在一起的工具。
如果没有网络,可想单机的世界是多么孤单。

使用网络的目的:
联通多方然后进行通信用的,即把数据从一方传递给另外一方。网络编程就是,让在不同的电脑上的软件能够数据传递,即进程之间的通信

TCP/IP协议

如何实现网络通信?------协议
有的说英语,有的说中文,有的说德语,说同一种语言的人可以交流,不同语言的人就不行了,为了解决不同种族人之间的语言沟通障碍,现规定国际通用语言是英语,这就是一个规定,这是协议。

网络通信协议是什么?
问题:不同种类之间的计算机到底是怎么进行数据传递的呢?
答:就像说不同语言的人沟通一样,只要有一种大家都认可都遵守的协议即可,那么这个计算机都遵守的网络通信协议叫做TCP/IP协议。

TCP/IP协议(族)
互联网协议包含了上百种协议标准,但是最重要的两个协议是TCP/IP协议,所以大家把互联网的协议简称为TCP/IP协议。
在这里插入图片描述
什么是IP地址
ip地址:用来在网络中标记一台电脑的一串数字,比如192.168.1.1;在本地局域网上是唯一的。
在这里插入图片描述
私有IP
网络IP中,国际规定有一部分IP地址是用于局域网使用,也就是属于私网IP,不再公网中使用的,他们的范围是:
10.0.0.0~10.255.255.255
172.16.0.0~172.31.255.255
192.168.0.0~192.168.255.255

回环地址IP
IP地址127.0.0.1代表本地IP地址,等价于localhost,用http://127.0.0.1就可以测试本集中配置的WEB服务器。

子网掩码
子网掩码不能呢个单独存在,它必须结合IP地址一起使用。

子网掩码的作用: 将某个IP地址分成网络地址和主机地址两部分,子网掩码的设定必须遵循一定的规则,用来判断两个IP是否在同一个网络。
A: 172.25.254.18/24
B: 172.25.0.10/24

端口
1.端口就好像一个房子的门,是出入这间房子的必经之路。
2.端口号只有整数,范围是从0到65535
熟悉的服务及其对应的端口号:
http : 80
mysql ; 3306
https :443
ssh :22
ldqp : 289

socket编程

本地进程间通信(IPC)
1.队列
2.同步
3.管道

网络进程间通信
问题: 本地通过进程PID来唯一标示一个进程,在网络中如何唯一标示一个进程?
答:网络层“IP地址”可以唯一标示网络中的主机,而传输层的"协议+端口“可以唯一标示主机中的应用程序(进程)。因此利用IP地址,协议,端口就可以标示网络的进程。

什么是socket?
答:socket(简称套接字)是进程间的一种通信方式,能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于Socket来完成通信的。

创建socket
在 Python 中 使⽤socket 模块的函数 socket 就可以完成: socket.socket(AddressFamily, Type)
1). Address Family:
AF_INET: IPV4⽤于 Internet 进程间通信
AF_INET6: IPV6⽤于 Internet 进程间通信
2). Type:套接字类型
SOCK_STREAM: 流式套接字,主要⽤于 TCP 协议
SOCK_DGRAM: 数据报套接字,主要⽤于 UDP 协 议

socket编程(UDP)

UDP介绍
1.UDP用户数据报协议,是一个无连接的简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证他们能到达目的地,由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重法等机制,故而传输速度很快。
2.UDP是一种面向无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。

UDP特点
UDP是面向无连接的通讯协议,UDP数据包括目的端口号和源端口号信息,由于通讯不需要连接,所以可以实现广播发送。UDP传输数据时有大小限制,每个传输的数据报必须限定在64KB以内。UDP是一个不可靠的协议,发送方所发送的数据报并不一定以相同的次序到达接收方。
在这里插入图片描述
服务端代码框架:

import socket
#1.实例化socket对象
udpServer = socket.socket(family=socket.AF_INET,type=socket.SOCK_DGRAM)
#2.绑定IP和端口
#172.25.254.250
#0.0.0.0代表开放所有的IP地址
udpServer.bind(('0.0.0.0',9001))
print('等待客户端UDP的连接......')

#3.接收客户端的连接
recvdata,address = udpServer.recvfrom(1024)
print('接收到客户端的数据:',recvdata.decode('utf-8'))

#4.给客户端回复信息
udpServer.sendto(b"hello client",address)
#5.关闭socket对象
udpServer.close()

客户端代码框架:

import socket

udpClient = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
udpClient.sendto(b'hello server', ('172.25.254.49', 9001))
recvData, address = udpClient.recvfrom(1024)
print('接收服务端的数据:', recvData.decode('utf-8'))
udpClient.close()

UDP网络程序框图
在这里插入图片描述

socket编程(TCP)

TCP详解:
TCP传输控制协议(英语:Transmission Control Protocol,缩写为TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议。

三次握手与四次挥手:
在这里插入图片描述
如上图:存在两个包,同步序列号SYN 确认包ACK
四种状态: SYN_SENT, LISTEN, SYN_RECV, ESTABLISHED
在三次握手中,客户端和服务器端都发送两个包SYN和ACK,只不过服务器端的两个包是一次性发过来的,客户端的两个包是分两次发送的。

TCP数据传输:
在这里插入图片描述
TCP四次挥手:
在这里插入图片描述四次挥手
当A端和B端要断开连接时,需要四次握手,这里称为四次挥手。

断开连接请求可以由客户端发出,也可以由服务器端发出,在这里我们称A端向B端请求断开连接。

第一次挥手

A端向B端请求断开连接时会向B端发送一个带有FIN标记的报文段,这里的FIN是Finish的意思。

第二次挥手

B端收到A发送的FIN后,B段现在可能现在还有数据没有传完,所以B端并不会马上向A端发送FIN,而是先发送一个确认序号ACK,意思是说“你发的断开连接请求我收到了,但是我现在还有数据没有发完,请稍等一下呗”。

第三次挥手

当B端的事情忙完了,那么此时B端就可以断开连接了,此时B端向A端发送FIN序号,意思是这次可以断开连接了。

第四次挥手

A端收到B端发送的FIN后,会向B端发送确认ACK,然后经过两个MSL时长后断开连接。

MSL是Maximum Segment Lifetime,最大报文段生存时间,2个MSL是报文段发送和接收的最长时间

在这里插入图片描述
代码实现服务端框架:

import socket

# 1.创建一个socket对象;
# family指定使用IP协议的版本:IPV4:AF_INET; ipv6:AF_INET6
# type指定传输层使用的协议类型:TCP(SOCKET.SOCK_STREAM),UDP(SOCK_DGRAM)
server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
# 2.绑定一个IP和端口,供客户端来连接;
server.bind(('172.25.254.250', 4002))
# 3.监听是否有客户端连接
server.listen(5)
print('服务端正在启动......')
# 4.接收客户端的连接,accept() -> (socket object,address info)
clientSocket, address = server.accept()
print('客户端的地址:', address)
# 5.接收客户端发送的信息
recvData = clientSocket.recv(1024)
print("服务端接收的信息:", recvData.decode('utf-8'))
# 6.给客户端回复消息,send(self,data:**bytes***,flags:int = .....)
clientSocket.send('你好,客户端'.encode('utf-8'))
# 7.关闭服务器端socket对象
server.close()

代码实现客户端框架:

import socket

# 1.创建一个socket对象;
# family指定使用IP协议的版本:IPV4:AF_INET; ipv6:AF_INET6
# type指定传输层使用的协议类型:TCP(SOCKET.SOCK_STREAM),UDP(SOCK_DGRAM)
client = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
# 2.连接服务器(ip,port)
client.connect(('172.25.254.250',4002))
# 3.给服务端回复消息,send(self,data:***bytes***,flages:int=...)-> int:...
client.send('你好,服务器'.encode('utf-8'))

# 4.接收服务端回复的消息
recvData = client.recv(1024)
print('客户端接收的信息:', recvData.decode('utf-8'))

# 5.关闭客户端socket对象
client.close()

应用:模拟QQ聊天
代码实现(服务端):

import socket
# 1.创建对象
server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
# 2.创建地址和端口
server.bind(('172.25.254.49', 4002))
# 3.监听
server.listen(5)
print('服务端正在启动.....')
# 4.接收客户端的连接
ServerSocket, address = server.accept()
while True:
    # 5.接收客户端发送的消息
    recvData = ServerSocket.recv(1024)
    recv = recvData.decode('utf-8')
    print('服务端接收的信息:',recv )
    if recv == 'bye':
        break
    # 6.给客户端发送消息
    send_data = input("server:>>").encode('utf-8')
    ServerSocket.send(send_data)

# 7.关闭socket对象
server.close()
ServerSocket.close()

客户端:

import socket

# 1.创建一个socket对像;
client = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
# 2.连接服务端
client.connect(('172.25.254.49', 4022))
# 3.给服务端发送信息
while True:
    send_data = input('client:>>').encode('utf-8')
    client.send(send_data)

    if send_data.decode('utf-8') == 'bye':
        break
# 5.关闭客户端socket对象
client.close()

并发服务器

并发服务器是socket应用编程中最常见的应用模型。根据连接方式分为长连接和短连接.
长连接:建立SOCKET连接后不管是否使用都保持连接。
短连接:双方都有数据交互时,建立TCP连接,数据发送完成后断开连接。

并发服务器模型根据处理方式可分为同步方式和异步方式:
在这里插入图片描述

单进程服务器:
同⼀时刻只能为⼀个客户进⾏服务,不能同时为多个客户服务
类似于找⼀个“明星”签字⼀样,客户需要耐⼼等待才可以获取到服务

多进程服务器:
优点: 通过为每个客户端创建⼀个进程的⽅式,能够同时为多个客户端进⾏服务
缺点: 当客户端不是特别多的时候,这种⽅式还⾏,如果有⼏百上千个,就不 可取了,因为每次创建进程等过程需要好较⼤的资源
在这里插入图片描述

在这里插入图片描述
代码实现框架(服务端):

import socket
from multiprocessing import Process


def dealWithClient(ServerSocket, clientAddress):
    while True:
        # 5.接收客户端发送的消息
        recvData = ServerSocket.recv(1024)
        recv = recvData.decode('utf-8')
        print(clientAddress[0] + str(clientAddress[1]) + ':>' + recv)
        if recv == 'quit':
            break
    ServerSocket.close()


# 1.创建对象
server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
# 2.创建地址和端口
server.bind(('172.25.254.49', 4022))
# 3.监听
server.listen(5)
print('服务端正在启动.....')
# 4.接收客户端的连接

while True:
    ServerSocket, address = server.accept()
    p = Process(target=dealWithClient, args=(ServerSocket, address))
    p.start()

多线程服务器
在这里插入图片描述

gevent版-TCP服务器
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值