网络编程

网络编程

一、网络模型

1.osi 七层网络模型

OSI模型,即开放式通信系统互联参考模型,是国际标准化组织(ISO)提出的一个试图使各种计算机在世界范围内互连为网络的标准框架,简称OSI。这是一种事实上被TCP/IP 4层模型淘汰的协议,在当今世界上没有大规模使用

具体七层数据格式功能连接方式典型设备
应用层用户的应用程序和网络之间的接口计算机
表示层协商数据交换格式
会话层允许用户使用简单易记的名称建立连接
传输层提供终端到终端的可靠连接pc机、手机
网络层使用权数据路由经过大型网络路由器
数据联络层决定访问网络介质的方式交换机
物理层将数据转换为可通过物理介质传送的电子信号光纤、同轴电缆

2.TCP/IP网络模型

TCP/IP 是基于 TCP 和 IP 这两个最初的协议之上的不同的通信协议的大的集合

OSI功能TCP/IP
应用层应用层HTTP、FTP、DNS、SMTP
传输层传输层TCP、UDP
网络互联层网络层IP
网络接入层(主机网络层)物理层、数据联络层

3.TCP协议(重要、面试、研发的)非常复杂

TCP是一种面向连接的,可靠的,给予字节流的传输层通讯协议

TCP需要先建立连接,然后传输,在传输的时候,还会做校验,如果有错误,重新传

TCP是因特网中的传输层协议,使用三次握手协议建立连接。当主动方发出SYN连接请求后,等待对方回答SYN+ACK,并最终对对方的 SYN 执行 ACK 确认,三次握手完成,TCP客户端和服务器端成功地建立连接,可以开始传输数据了

总结:三次握手,四次挥手

互联网传输数据主要用到两个协议,TCP、UDP

UDP是一种无连接的,不可靠的,基于字节流的传输层通讯协议

类比:TCP是打电话,接通才能说话;UDP是发电报,直接发,不管收

4.IP(网络之间互连的协议)

在因特网中,它是能使连接到网上的所有计算机网络实现相互通信的一套规则,规定了计算机在因特网上进行通信时应当遵守的规则。任何厂家生产的计算机系统,只要遵守IP协议就可以与因特网互连互通。

IP地址(IP Address)
基本概念

IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。

Internet上的每台主机(Host)都有一个唯一的IP地址。IP协议就是使用这个地址在主机之间传递信息,这是Internet 能够运行的基础。IP地址是一个32位的二进制数,被分割为4个“8位二进制数”,IP地址通常用“点分十进制”表示成(a.b.c.d)的形式,其中,a,b,c,d都是0~255之间的十进制整数。

IP地址是一种在Internet上的给主机编址的方式,也称为网际协议地址。常见的IP地址,分为IPv4与IPv6两大类。IPV4就是有4段数字,每一段最大不超过255,2011年2月3日IPv4位地址分配完毕,为了扩大地址空间,拟通过IPv6重新定义地址空间。IPv6采用128位地址长度。

互联网上的IP地址统一由一个叫“ICANN”(Internet Corporation for Assigned Names and Numbers,互联网赋名和编号公司)的组织来管理。

区别方法

公有地址(Public address)由Inter NIC(Internet Network Information Center因特网信息中心)负责。这些IP地址分配给注册并向Inter NIC提出申请的组织机构。通过它直接访问因特网。

私有地址(Private address)属于非注册地址,专门为组织机构内部使用。

分类介绍

每个IP地址包括两个标识码(ID),即网络ID和主机ID,同一个物理网络上的所有主机都使用同一个网络ID,网络上的一个主机有一个主机ID与其对应。Internet委员会定义了5种IP地址类型以适合不同容量的网络,即A类~E类。

其中A、B、C3类(如下表格)由InternetNIC在全球范围内统一分配,D、E类为特殊地址。

网络类别最大网络数IP地址范围最大主机数私有IP地址范围
A126(2^7-2)1.0.0.0–127.255.255.2551677721410.0.0.0–10.255.255.255
B16384(2^14)128.0.0.0–191.255.255.25565534172.16.0.0–172.31.255.255
C2097152(2^21)192.0.0.0–223.255.255.255254192.168.0.0–192.168.255.255

5.端口(port)

基本概念

如果把IP地址比作一间房子 ,端口就是出入这间房子的门。真正的房子只有几个门,但是一个IP地址的端口 可以有65536(即:2^16)个,端口是通过端口号来标记的,端口号只有整数,范围是从0 到65535(2^16-1)。本地操作系统会给那些有需求的进程分配协议端口。

分类

1.周知端口:从0到1023,操作系统给系统服务固定分配的端口。通常这些端口的通讯明确表明了某种服务的协议。例如:80端口实际上总是HTTP通讯。

2.注册端口:从1024到49151,分配给用户进程的端口。也就是说有许多服务绑定于这些端口,这些端口同样用于许多其它目的。例如:许多系统处理动态端口从1024左右开始。

3.动态和/或私有端口:从49152到65535,一般不固定分配,由操作系统,动态分配

总结

IP用来表示终端,端口就是用来区别程序,注意一个端口只能同时被一个程序监听

端口号及功能

端口号功能
22ssh远程登录协议规定的默认监听端口
8000Django运行命令监听端口
3306MySQL
6379Redis

二、套接字(socket)

1.基本概念

TCP用主机的IP地址加上主机上的端口号作为TCP连接的端点,这种端点就叫做套接字(socket)或插口,套接字是对TCP、UDP的封装,为了简化技术难度

套接字用(IP地址:端口号)表示,它是网络通信过程中端点的抽象表示,包含进行网络通信必需的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口

2.Python中使用socket

创建套接字

# 创建套接字
from socket import *   # 导入socket模块
tcp_sock = socket(family=AF_INET, type=SOCK_STREAM)
udp_sock = socket(family=AF_INET, type=SOCK_DGRAM)

# family是地址簇,默认AF_INET type 指定是tcp还是udp

创建一个TCP服务器

# 创建一个tcp server
from socket import socket   # 导入模块
# 1.创建套接字
tcp_server = socket()   # 默认就是tcp
# 2.绑定监听端口和ip
tcp_server.bind(('',8888))		#('', 端口号)
# 3.开始监听
tcp_server.listen(5)	#5表示排队(最多排五个)
# 4.等待连接
print('开始等待')
client,addr = tcp_server.accept()       # 阻塞的,直到有连接进来
print('有连接进来 它的地址是:', addr)
while True:
    # 5.接受数据
    res = client.recv(1024)
    if res == b'':
        client.close()
        break
    print('接收到数据:', res.decode(encoding='utf-8'))
    # 6. 发送数据
    client.send(res)

创建一个TCP客户端

# 创建一个TCP客户端
from socket import socket
# 1.创建socket
client = socket()
# 2.连接服务端
client.connect(('127.0.0.1',8888))	#('IP',端口号)
while True:
    # 发送信息
    client.send(input('请输入信息:').encode())
    # 接收信息
    data = client.recv(1024)	# 单位:1024个字节
    print(data.decode(encoding='utf-8'))

socket爬取百度图片

import socket
import re

# 创建一个客户端
client = socket.socket()
# 连接地址
client.connect(('image.baidu.com', 80))
# 构造报文
request = 'GET /search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=index&fr=&hs=0&xthttps=111111&sf=1&fmq=&pv=&ic=0&nc=1&z=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&word=动漫&oq=动漫&rsp=-1 HTTP/1.0\r\nHost: image.baidu.com\r\n\r\n'
# 发送请求消息
client.send(request.encode())
# 循环接收网站返回的数据
res = b''
data = client.recv(1024)
while data:
    res += data
    data = client.recv(1024)
# 关闭socket
client.close()
# 图片首页地址
url_root = 'image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=index&fr=&hs=0&xthttps=111111&sf=1&fmq=&pv=&ic=0&nc=1&z=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&word=动漫&oq=动漫&rsp=-1'
# "hoverURL":"https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2535548369,3399272173&fm=26&gp=0.jpg"
image_url_all = re.findall(r'"hoverURL":"(.*?jpg|jpeg|gif|png)"', res.decode(), re.S)
n = 0
for image_url in image_url_all:
    n += 1
    #  切割出host和path
    host = image_url.split('//')[-1].split('/', maxsplit=1)[0]
    path = image_url.split('//')[-1].split('/', maxsplit=1)[1]
    # 再创建一个客户端
    client_image = socket.socket()
    # 连接到图片地址
    client_image.connect((host, 80))
    # 构造图片地址的报文
    request_image = 'GET /{} HTTP/1.0\r\nHost: {}\r\nReferer: {}\r\n\r\n'.format(path, host, url_root)
    client_image.send(request_image.encode())
    res = b''
    data_image = client_image.recv(1024)
    while data_image:
        res += data_image
        data_image = client_image.recv(1024)
    print(res)
    # 提取出图片信息
    content_image = re.findall(b'\r\n\r\n(.*)', res, re.S)
    # 写入文件
    with open(r'../socket-text/image/{}.jpg'.format(n), 'wb') as f:
        f.write(content_image[0])

上面代码的简单封装

import socket
import re


def socket_get_content(hosts, paths, url_root):
    client = socket.socket()
    client.connect((hosts, 80))
    request = 'GET /{} HTTP/1.0\r\nHost: {}\r\nReferer:{}\r\n\r\n'.format(paths, hosts, url_root)
    client.send(request.encode())
    res = b''
    data = client.recv(1024)
    while data:
        res += data
        data = client.recv(1024)
	client.close()
    return res

image_url_all = socket_get_content('image.baidu.com',
                                   'search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=index&fr=&hs=0'
                                   '&xthttps=111111&sf=1&fmq=&pv=&ic=0&nc=1&z=&se=1&showtab=0&fb=0&width=&height='
                                   '&face=0&istype=2&ie=utf-8&word=动漫&oq=动漫&rsp=-1',
                                   '')
# "hoverURL":"https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2535548369,3399272173&fm=26&gp=0.jpg"
image_urls = re.findall(r'"hoverURL":"(.*?jpg|jpeg|gif|png)"', image_url_all.decode(), re.S)
image_name = 0
for image_url in image_urls:
    image_name += 1
    host = image_url.split('//')[-1].split('/', maxsplit=1)[0]
    path = image_url.split('//')[-1].split('/', maxsplit=1)[1]
    image_contents = socket_get_content(host,
                                        path,
                                        'image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1'
                                        '&fm=index&fr=&hs=0&xthttps=111111&sf=1&fmq=&pv=&ic=0&nc=1&z=&se=1&showtab=0'
                                        '&fb=0&width=&height=&face=0&istype=2&ie=utf-8&word=动漫&oq=动漫&rsp=-1')
    content_image = re.findall(b'\r\n\r\n(.*)', image_contents, re.S)
    with open(r'image/{}.jpg'.format(image_name), 'wb') as f:
        f.write(content_image[0])
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值