python基础教学day21--网络编程

本文详细介绍了网络通信的基础概念,包括TCP/IP协议的工作原理、IP地址及子网掩码的作用,对比了TCP与UDP的不同之处,并提供了实际的Python代码示例来演示如何使用socket进行网络编程。

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

一、网络通信概述

1、网络通信就是一种能够使双方或者多方连接在一起的工具。
2、网络通信的目的

  • 能够把多方连接在一起,然后进行数据的传递
  • 网络编程就是,使不同电脑上的软件能够进行数据传递,即进程之间的通信

二、TCP/IP协议

1、网络协议为计算机中进行数据交换而建立的规则、标准或约定的集合。
2、互联网有上百种协议标准,最重要的两个协议时TCP/IP协议。
3、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

4、回环地址ip:ip地址127.0.0.1代表本机ip地址,等价与localhost,用http://127.0.0.1即可测试本机中的配置的Web服务器。
5、⼦⽹掩码不能单独存在,它必须结合IP地址⼀起使⽤。
⼦⽹掩码的作⽤: 将某个IP地址划分成⽹络地址和主机地址两部分. ⼦⽹掩码的设定 必须遵循⼀定的规则, 用来判断两个IP是否在同一个网络。
A: 172.25.254.18/24
B: 172.25.0.10/24
6、端口是连接的必要条件,端口号只有整数范围ie是从0到65535。下面是一些主要服务的端口号:

  • http端口号:80
  • ssh端口号:22
  • https端口号:443
  • mysql端口号:3306
  • redis端口号:6379

三、socket编程

1、本地间的通信有:队列、同步、管道
2、网络层的“ip地址”可以唯一标识网络中的主机,而传输层的“协议和端口”可以唯一标识主机中的应用程序(进程)。因此利用IP地址,协议,端口就可以标识网络的进程。
3、socket是进程通信间的一种方式,能实现不同主机间的通信,我们网络上的多数服务器都是基于Socket完成通信。
4、在 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 协 议

5、UDP用户数据报协议,是⼀个⽆连接的简单的⾯向数据报的运输层协议。UDP不提供可靠性,它只是把应⽤程序传给IP层的数据报发送出去,但 是并不能保证它们能到达⽬的地。由于UDP在传输数据报前不⽤在客户和服 务器之间建⽴⼀个连接,且没有超时重发等机制,故⽽传输速度很快。
6、UDP是⾯向消息的协议,通信时不需要建⽴连接,数据的传输⾃然是不可靠 的,UDP⼀般⽤于多点通信和实时的数据业务,⽐如:

  • 语音广播
  • 视频
  • QQ
  • TFTP(简单文件传输)
  • SNMP(简单网络管理协议)
  • DNS(域名解释)
    在这里插入图片描述

服务端代码:


import socket

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

udpsocket.bind(('0.0.0.0',9996))

print('模拟qq聊天开始....')
while True:
    #返回的是一个元组,第一个元素的是客户端发送的消息,第二个元素是客户端与服务端交互的地址(IP,port)
    recvdata,address = udpsocket.recvfrom(1024)
    r = recvdata.decode('utf-8')
    print('B:>>',r)
    if r == 'quit':
        print('聊天结束...')
        break
    send_data = input('A:>>').encode('utf-8')
    udpsocket.sendto(send_data,address)
udpsocket.close()


客户端代码:

import socket

udpclient = socket.socket(family=socket.AF_INET,type=socket.SOCK_DGRAM)
print('用户B上线.....')
while True:
    send_data = input('B:>>').encode('utf-8')
    udpclient.sendto(send_data,('172.25.254.47',9996))
    if send_data == 'quit':
        print(';聊天结束....')
        break
    recv_Data, address = udpclient.recvfrom(1024)
    print('A:>>',recv_Data.decode('utf-8'))
udpclient.close()

四、TCP详解

1、TCP三次握手

  1. 两个包: 同步序列标号 SYN 确认包 ACK
  2. 四种状态: SYN_SENT, LISTEN, SYN_RECV, ESTABLISHED
    在三次握手中,客户端和服务器端都发送两个包SYN和ACK,只不过服务器端的两个包是一次性发过来的,客户端的两个包是分两次发送的。
  3. 第一次握手:当客户端向服务器发起连接请求时,客户端会发送同步序列标号SYN到服务器,在这里我们设SYN为x,等待服务器确认,这时客户端的状态为SYN_SENT。
  4. 第二次握手:当服务器收到客户端发送的SYN后,服务器要做的是确认客户端发送过来的SYN,在这里服务器发送确认包ACK,这里的ACK为x+1,意思是说“我收到了你发送的SYN了”,同时,服务器也会向客户端发送一个SYN包,这里我们设SYN为y。这时服务器的状态为SYN_RECV
  5. 第三次握手:客户端收到服务器发送的SYN和ACK包后,需向服务器发送确认包ACK,“我也收到你发送的SYN了,我这就给你发个确认过去,然后我们即能合体了”,这里的ACK为y+1,发送完毕后,客户端和服务器的状态为ESTABLISH,即TCP连接成功。

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

2、TCP四次挥手
断开连接请求可以由客户端发出,也可以由服务端发出,在这里我们称A端向B端请求断开连接。

  1. 第一次挥手:A端向B端请求断开连接时会向B端发送一个带有FIN标记的报文段,这里的FIN是Finish的意思。
  2. 第二次挥手:B端收到A发送的FIN后,B段现在可能现在还有数据没有传完,所以B端并不会马上向A端发送FIN,而是先发送一个确认序号ACK,意思是说“你发的断开连接请求我收到了,但是我现在还有数据没有发完,请稍等一下
  3. 第三次挥手:当B端的事情忙完了,那么此时B端就可以断开连接了,此时B端向A端发送FIN序号,意思是这次可以断开连接了。
  4. 第四次挥手: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.绑定地址和端口
server.bind(('0.0.0.0',9998))

#3.监听是否有客户端连接
server.listen(5)
print('服务端开始.....')

#4.接受客户端的连接
clientSockObj,clientAddress = server.accept()

#5.接受客户端发送的信息
recv_data = clientSockObj.recv(1024).decode('utf-8')
print('接收到客户端发送的消息:',recv_data)

#6.给客户端发送消息
send_data = b'hello'
clientSockObj.send(send_data)

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

客户端代码:

import socket
client = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)

client.connect(('172.25.254.47',9998))

while True:
    send_data = input('客户端:>>').encode('utf-8')
    if not send_data:
         continue
    client.send(send_data)
    if send_data == 'quit':
        break

client.close()

五.并发服务器

1.并发服务器是socket应用编程中最常见的应用模型。根据连接方式分为长连接和短连接.
2.

通信方式具体通信过程
长连接建立SOCKET连接后不管是否使用都保持连接
短连接双方有数据交互时,建立TCP连接,数据发送完成后断开连接

3.并发服务器模型根据处理方式可分为ie同步方式和异步方式.
4.单进程服务器

  • 同一时刻只能为⼀个客户进⾏服务,不能同时为多个客户服务
  • 客户需要耐⼼等待才可以获取到服务

5.多进程服务器

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

服务端代码:

def dealWithClient(clientSockObj,clientAddress):
    while True:
        #5.接受客户端发送的信息
        recv_data = clientSockObj.recv(1024).decode('utf-8')
        print(clientAddress[0] + str(clientAddress[1]) + ':>' + recv_data)
        if recv_data == 'quit':
            break
        # send_data = input('server:>>').encode('utf-8')
        # if not send_data:
        #     continue
        # clientSockObj.send(send_data)
    clientSockObj.close()


import socket
from multiprocessing import Process

server = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

server.bind(('0.0.0.0',9996))

server.listen(5)
print('server start..........')

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

客户端1代码:

import socket
client = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)

client.connect(('172.25.254.47',9996))

while True:
    send_data = input('客户端:>>').encode('utf-8')
    if not send_data:
         continue
    client.send(send_data)
    if send_data == 'quit':
        break

client.close()

客户端2代码:

import socket
client = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)

client.connect(('172.25.254.47',9996))

while True:
    send_data = input('客户端:>>').encode('utf-8')
    if not send_data:
         continue
    client.send(send_data)
    if send_data == 'quit':
        break

client.close()

服务端显示结果:

server start..........
172.25.254.4757732:>1
172.25.254.4757734:>2
172.25.254.4757732:>1.1
172.25.254.4757734:>2.1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值