网络编程

网络编程

1 osi七层,tcp/ip五层

  1. cs架构和bs架构

  2. 互联网

  3. osi七层、tcp五层

    • 物理层

      • 网线,光纤
    • 数据链路层

      • 网卡
    • 网络层

      • 路由器
    • 传输层(运输层)

      • 四层路由器
    • 应用层(会话层,表示层,应用层)

      • HTTP协议、ftp协议、websocket协议。。。

2 每一层功能

  1. 物理层
    • 网线 -》高低电频,传输的是电信号
    • 8个比特位是一个字节
  2. 数据链路层
    • 数据帧:一组电信号是一个数据帧,有头和数据部分
    • 网卡---》mac地址---》全球唯一,在出厂时就印在了网卡上
    • 48位二进制,看到的都是16进制
    • 广播:局域网内通信,所有人都会接受到,通过mac地址确定给谁的数据,如果不是自己的就不处理
    • 广播风暴
  3. 网络层
    • 跨局域网通信,需要进过网络层
    • IP地址:0.0.0.0-255.255.255.255
    • 子网掩码:与IP地址进行与运算可以得到网络地址
    • ARP协议:IP和mac的对照表
  4. 传输层
    • 端口:0-65535,一个程序可以监听多个端口,但是一个端口只能属于一个应用程序
    • TCP协议:可靠传输(三次握手和四次挥手)
    • UDP协议:不可靠传输
  5. 应用层
    • HTTP协议,FTP协议,websocket...

3 常用端口号

应用程序 FTP TFTP TELNET SMTP DNS HTTP SSH MYSQL
熟知端口 21,20 69 23 25 53 80 22 3306
传输层协议 TCP UDP TCP TCP UDP TCP TCP TCP

DNS:把网络地址转换成ip地址

从浏览器发送出去的数据,都是HTTP协议,默认端口是80

4 TCP三次握手和四次挥手(面试题)

  1. tcp可靠传输:三次握手,四次挥手保证数据可靠
  2. 三次握手(建立链接)
    • 客户端向服务器端发送链接请求 1
    • 服务器端回复可以建立,并且带着跟客户端建立链接的数据报 2
    • 客户端收到后。链接建立完成 3
  3. 这个过程后就可以进行可靠传输数据
  4. 四次挥手(断开连接)
    • 客户端告诉服务端要断开链接 1
    • 服务端收到,回复ok 2
    • 服务端可能还有数据在传递,暂时还没断开,等待数据传输完毕
    • 服务端告诉客户端要断开链接 3
    • 客户端收到,回复ok 4

5 Socket层

  1. socket抽象层,从osi七层中抽象出来的,抽象了网络层和传输层,跟语言无关,任何语言都会有socket的封装
  2. 专门给开发人员用的

image-20210420120955375

6 基于Tcp的socket套接字(重点)

  • 服务端


# 导入socket模块
import socket
import time
# 第一个socket是模块名,第二个socket是类名
#类实例化得到对象,得到一个socket对象
# server=socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)
#不写默认就是他
server=socket.socket()

# 绑定地址跟端口  ,传一个元组,监听的地址,监听的端口
server.bind(('192.168.11.28',8008))
#监听
# 半连接池是5,可以缓冲5个
server.listen(5)

#等待用户连接(看源码,有两个返回结果)
# sock是连接对象,以后这个服务端和客户端交互,使用这个对象交互
# addr是客户端地址(ip和端口)
sock,addr=server.accept()

# 接收客户端发给我的消息
data=sock.recv(1024)
# 打印
print(data)

#服务端给客户端发送消息(必须是byte格式)
sock.send(b'helloworld')
time.sleep(1)
# 关闭连接对象
sock.close()

#关闭服务
server.close()
  • 客户端
import socket

# 创建socket对象
client=socket.socket()
# 连接服务端
client.connect(('127.0.0.1',8008))
#给服务端发了一个sb
client.send(b'sb')
# 收到了服务端给我的
data=client.recv(1024)

print(data)
# 关闭
client.close()

7 加入链接循环的socket套接字TCP

  • 服务端
'''
2.1 基于文件类型的套接字家族
套接字家族的名字:AF_UNIX
unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信


2.2 基于网络类型的套接字家族
套接字家族的名字:AF_INET

(还有AF_INET6被用于ipv6,还有一些其他的地址家族,不过,他们要么是只用于某个平台,要么就是已经被废弃,或者是很少被使用,或者是根本没有实现,所有地址家族中,AF_INET是使用最广泛的一个,python支持很多种地址家族,但是由于我们只关心网络编程,所以大部分时候我么只使用AF_INET)



'''

import socket
#实例化得到一个对象
#type=socket.SOCK_STREAM   TCP服务端
#type=socket.SOCK_DGRAM   UDP服务端
server=socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)

# 绑定地址和端口
server.bind(('127.0.0.1',80))

# listen:监听

server.listen(1)

# 等待用户连接
print('开始等待客户端连接了')
while True:
    sock,addr=server.accept()

    print(sock)
    print('客户端的地址是:',addr)

    data=sock.recv(1024)
    print(data)

    # 这不是字符串的upper
    sock.send(data.upper())

    sock.close()
server.close()

  • 客户端
import socket

client=socket.socket()
client.connect(('127.0.0.1',80))

client.send('sb'.encode('utf-8'))

data=client.recv(1024)
print(data)

client.close()

8 加入通信循环的socket套接字TCP

  • 服务端

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

server.bind(('127.0.0.1',81))


server.listen(1)

print('开始等待客户端连接了')
while True:

    sock,addr=server.accept()
    print(sock)
    print('客户端的地址是:',addr)


    # 等待客户端发送过来的数据,如果客户端没有发送数据,会一直等着
    while True:
        try:
            data=sock.recv(1024)
            if len(data)==0: # 这个表示客户端正常断开了,结束通信循环
                break
            print(data.decode('utf-8'))
            sock.send(data.upper())
        except Exception as e:
            print(e) #客户端非正常断开,需要异常捕获
            break


    sock.close()
server.close()

  • 客户端

  
import socket

client=socket.socket()
client.connect(('127.0.0.1',81))


while True:

    input_data=input('请输入发送给客户端的内容(输入q退出):')

    if input_data=='q':
        break
    client.send(input_data.encode('utf-8'))

    data=client.recv(1024)
    print(data.decode('utf-8'))

client.close()

9 基于UDP的socket套接字

  • 服务端
import socket

# udp的服务端
server = socket.socket(type=socket.SOCK_DGRAM)

# 监听地址和端口
server.bind(('127.0.0.1', 82))

# 不需要listen,直接建立链接
print('等待客户端发送数据:')
while True:
#recvfrom回返回数据和客户端的地址
    data,addr = server.recvfrom(1024)
    print(data)
    print(addr)
    server.sendto(data.upper(), addr)

server.close()

  • 客户端
import socket


client=socket.socket(type=socket.SOCK_DGRAM)
client.sendto(b'sb',('127.0.0.1',82))
# data,addr=client.recvfrom(1024)
# data,_=client.recvfrom(1024)
data=client.recv(1024)
print(data)
# print(addr)

client.close()
posted @ 2021-07-02 20:29  zheng-sn  阅读(51)  评论(0)    收藏  举报