python之网络编程

本文介绍了网络编程的基本概念,包括TCP/IP协议、IP地址、UDP与TCP的特点及应用,并通过实例演示了使用Python进行UDP和TCP编程的方法。

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

一、网络编程

网络通信概述

什么是⽹络?⽹络就是⼀种辅助双⽅或者多⽅能够连接在⼀起的⼯具。
使⽤⽹络的⽬的:联通多⽅然后进⾏通信⽤的,即把数据从⼀⽅传递给另外⼀⽅。

TCP/IP协议

如何实现⽹络通信?协议
有的说英语,有的说中⽂,有的说德语,说同⼀种语⾔的⼈可以交流,不同的语⾔之间就不⾏了 为了解决不同种族⼈之间的语⾔沟通障碍,现规定国际通⽤语⾔是英语,这就是⼀个规定,这就是协议。
TCP/IP协议(族)
互联⽹协议包含了上百种协议标准,但是最重要的两个协议是TCP和IP 协议,所以,⼤家把互联⽹的协议简称TCP/IP协议。
在这里插入图片描述
IP地址
⽤来在⽹络中标记⼀台电脑的⼀串数字,⽐如192.168.1.1;在本地 局域⽹上是惟⼀的。
每⼀个IP地址包括两部分:⽹络地址和主机地址。
在这里插入图片描述
回环地址IP
IP地址127.0.0.1 代表本机IP地址,等价于localhost, ⽤ http://127.0.0.1 就可以测试本机中配置的Web服务器。

UDP

UDP ⽤户数据报协议,是⼀个⽆连接的简单的⾯向数据报的运输层协议。UDP不提供可靠性,它只是把应⽤程序传给IP层的数据报发送出去,但 是并不能保证它们能到达⽬的地。由于UDP在传输数据报前不⽤在客户和服 务器之间建⽴⼀个连接,且没有超时重发等机制,故⽽传输速度很快。
UDP是⼀种⾯向⽆连接的协议,每个数据报都是⼀个独⽴的信息,包括完整 的源地址或⽬的地址,它在⽹络上以任何可能的路径传往⽬的地,因此能否到达⽬的地,到达⽬的地的时间以及内容的正确性都是不能被保证的。
UDP特点
UDP是⾯向⽆连接的通讯协议,UDP数据包括⽬的端⼝号和源端⼝号信息, 由于通讯不需要连接,所以可以实现⼴播发送。 UDP传输数据时有⼤⼩限 制,每个被传输的数据报必须限定在64KB之内。 UDP是⼀个不可靠的协 议,发送⽅所发送的数据报并不⼀定以相同的次序到达接收⽅。

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 协 议

UDP

UDP是⾯向消息的协议,通信时不需要建⽴连接,数据的传输⾃然是不可靠 的,UDP⼀般⽤于多点通信和实时的数据业务,⽐如:
语⾳⼴播 ,视频,QQ,TFTP(简单⽂件传送) ,SNMP(简单⽹络管理协议), DNS(域名解释)
udp连接的过程
在这里插入图片描述
根据上面的模型,我们用udp做一个模拟聊天的工具。
首先先搭建好服务器端:
创建,绑定端口,连接

import socket

udpServer = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)

udpServer.bind(('0.0.0.0', 9000))

print("正在等待客户端udp的连接。。。。")

while True:

    recvdata, address = udpServer.recvfrom(1024)
    print("客户端:", recvdata.decode('utf-8'))

    server = input("服务器端>>:").encode('utf-8')
    udpServer.sendto(b'%s' % server, address)
    if recvdata== b'quit' or server.decode('utf-8') =='quit':
        break
udpServer.close()

接着写一个客户端去测试服务器。
也是先创建,

import socket
udpClient= socket.socket(family=socket.AF_INET,type=socket.SOCK_DGRAM)

while True:
    Client = input("客户端:>>").encode('utf-8')
    udpClient.sendto(b' %s '%Client, ('172.25.254.39', 9000))
    recvData, address = udpClient.recvfrom(1024)
    print("服务器端:", recvData.decode('utf-8'))
    if recvData==b'quit' or Client.decode('utf-8') =='quit':
        break
udpClient.close()

运行之后看我们测试的结果。
客户端:
在这里插入图片描述
服务器端结果:
在这里插入图片描述
这样就说明我们的模拟聊天就成功了。
当然,可以用UDP做一个拓展,就是我客户端发送linux命令,服务器反馈命令的结果。
客户端实现:

import socket
udpClient= socket.socket(family=socket.AF_INET,type=socket.SOCK_DGRAM)
while True:
    desktop = input("客户端:>>").encode('utf-8')
    udpClient.sendto(b' %s '%desktop, ('172.25.254.39', 9000))

    if desktop==b'quit':
        break
udpClient.close()

服务器实现:

import socket
import os

udpServer = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
udpServer.bind(('0.0.0.0', 9000))
while True:

    recvdata, address = udpServer.recvfrom(1024)
    s=recvdata.decode('utf-8')
    if recvdata ==b'quit':
        break
    obj=os.popen(s)
    content=obj.read()
    print('cmd >>#: %s'%content)
udpServer.close()

测试结果:
输入的客户端命令
在这里插入图片描述
服务器返回的结果。
在这里插入图片描述

TCP

TCP: 传输控制协议(英语:Transmission Control Protocol,缩写为TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
TCP/UDP对比
在这里插入图片描述
TCP建立连接的过程。

在这里插入图片描述
tcp连接的时候有三次握手,断开的时候有四次分手。

TCP三次握⼿

在这里插入图片描述

两个包: 同步序列标号 SYN 确认包 ACK
四种状态: SYN_SENT, LISTEN, SYN_RECV, ESTABLISHED
在三次握手中,客户端和服务器端都发送两个包SYN和ACK,只不过服务器端的两个包是一次性发过来的,客户端的两个包是分两次发送的。

三次握手
TCP连接是通过三次握手来连接的。
第一次握手
当客户端向服务器发起连接请求时,客户端会发送同步序列标号SYN到服务器,在这里我们设SYN为x,等待服务器确认,这时客户端的状态为SYN_SENT。
第二次握手
当服务器收到客户端发送的SYN后,服务器要做的是确认客户端发送过来的SYN,在这里服务器发送确认包ACK,这里的ACK为x+1,意思是说“我收到了你发送的SYN了”,同时,服务器也会向客户端发送一个SYN包,这里我们设SYN为y。这时服务器的状态为SYN_RECV。
一句话,服务器端发送SYN和ACK两个包。
第三次握手

客户端收到服务器发送的SYN和ACK包后,需向服务器发送确认包ACK,“我也收到你发送的SYN了,我这就给你发个确认过去,然后我们即能合体了”,这里的ACK为y+1,发送完毕后,客户端和服务器的状态为ESTABLISH,即TCP连接成功。

在三次握手中,客户端和服务器端都发送两个包SYN和ACK,只不过服务器端的两个包是一次性发过来的,客户端的两个包是分两次发送的。

TCP四次分手

当A端和B端要断开连接时,需要四次握手,这里称为四次挥手。
在这里插入图片描述
两个包: FIN:Finish, ACK确认序号。
四次挥手
当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是报文段发送和接收的最长时间

理解例连接过程,我们用TCP来实现上面的模拟聊天。
首先也是服务器的搭建。

import socket

#1、创建服务端Socket对象
server=socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)

#2、绑定端口(Ip:Port)
server.bind(('0.0.0.0',8999))
#3、监听是否有客户端连接?
server.listen(5)
print("server  start.....")

#4、接受客户端的accept
clientSocketobj,clientAddress=server.accept()
while True:

    #5、接受客户端消息
    recv_data=clientSocketobj.recv(1024).decode('utf-8')
    if recv_data == 'quit':
        break
    print("客户端:",recv_data)

    #6、给客户端发送消息
    res=input("服务器:>>").encode('utf-8')
    if not res:
        continue
    clientSocketobj.send(res)
    if res ==b'quit':
        break
#7、关闭socket对象
print("power off.....")
clientSocketobj.close()
server.close()

接着就是客户端的测试了。

import socket

# 1、创建客户端socket对象
client = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)

# 2、连接服务器
client.connect(('172.25.254.39',8999))
# 3、给服务器发消息
while True:
    res=input("客户端:>>").encode('utf-8')
    if not res:
        continue
    client.send(res)
    # 4、接受服务器端的消息
    recv_data=client.recv(1024).decode('utf-8')
    if recv_data=='quit' or res==b'quit':
        break
    print("服务器:", recv_data)
# 5、关闭socket对象
print("power off.....")
client.close()

客户端结果:
在这里插入图片描述
服务器结果:
在这里插入图片描述

并发服务器

并发服务器是socket应用编程中最常见的应用模型。根据连接方式分为长连接和短连接。并发服务器模型根据处理方式可分为同步方式和异步方式。
在这里插入图片描述
多进程服务器
优点: 通过为每个客户端创建⼀个进程的⽅式,能够同时为多个客户端进⾏服务
缺点: 当客户端不是特别多的时候,这种⽅式还⾏,如果有⼏百上千个,就不 可取了,因为每次创建进程等过程需要好较⼤的资源。
实现如下:
首先也是服务器搭建。

def dealwithClient(clientSocketobj,clientAddress):
    while True:

        # 5、接受客户端消息
        recv_data = clientSocketobj.recv(1024).decode('utf-8')
        print(clientAddress[0]+' '+str(clientAddress[1])+':>>'+recv_data)
        if recv_data == 'quit':
            break
    clientSocketobj.close()

import socket
from  multiprocessing import Process
#1、创建服务端Socket对象
server=socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)


#2、绑定端口(Ip:Port)
server.bind(('0.0.0.0',8999))
#3、监听是否有客户端连接?
server.listen(5)
print("server  start.....")
while True:
#4、接受客户端的accept
    clientSocketobj,clientAddress=server.accept()
    p=Process(target=dealwithClient,args=(clientSocketobj,clientAddress))
    p.start()

然后也是客户端去测试。

import socket

# 1、创建客户端socket对象
client = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)

# 2、连接服务器
client.connect(('172.25.254.39',8999))
# 3、给服务器发消息
while True:
    res=input("客户端:>>").encode('utf-8')
    if not res:
        continue
    client.send(res)
    if res==b'quit':
        break
# # 5、关闭socket对象
print("power off.....")
client.close()

然后多复制几个客户端去测试我们的多进程服务器。
服务器的结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值