一、网络结构体系
1. OSI协议是由ISO(国际标准化组织)制定的,用于提供给开发者一个必须的、通用的概念以便开发完善、可以用来解释连接不同系统的框架。OSI协议将网络体系结构划分为7层:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层。
2. TCP/IP(Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议)体系结构是指能够在多个不同网络间实现的协议簇。TCP/IP传输协议包含4层体系结构,应用层、传输层、网络层和网络接口层。
1、应用层
应用层协议定义了运行在不同端系统上的应用程序进程如何相互传递报文。
- DNS:域名系统(Domain Name System),用来实现域名与IP地址的转换,运行在UDP之上,默认使用53端口;
- FTP:文件传输协议(File Transfer Protocol),可以通过网络在不同平台之间实现文件的传输,是一种基于TCP的明文传输协议,默认工作在21端口;
- HTTP:超文本传输协议(HyperText Transfer Protocol),运行于TCP之上,默认端口为80;
- SMTP:简单邮件传输协议(Simple Mail Transfer Protocol),建立在TCP的基础上,使用明文传递邮件和发送命令,默认使用25端口。
- TELNET:远程登陆协议,运行于TCP之上,默认使用23端口。
2、传输层
传输层主要负责向两个主机中进程之间的通信提供服务。包括:传输控制协议(Transmission Control Protocol,TCP)和用户数据报协议(User Datagram Protocol,UDP)。
- TCP:为两台计算机之间提供面向连接、可靠的字节流服务。一台计算机发出的字节流无差错地发往网络上的其他计算机,由于其可靠的传输方式,故传输速度较慢。
- UDP:是一个简单的面向数据报的传输层协议。提供的是非面向连接的、不可靠的数据流传输。UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故传输速度很快。
(1)TCP三次握手协议:
- 客户端送一个SYN包作为建立连接的请求等待确认应答。?
- 服务器接收到请求数据包后,发送ACK确认应答,发送SYN包请求连接。
- 客户端针对SYN包发送ACK包确认应答。
?3、网络层
IP运行于网络层,是网络互联的重要基础。通过IP地址(IPV4:64位,IPV6:128位)用来标识网络上的主机,在公开网络上或者局域网内部,每台主机都必须使用不同的IP地址。由于网络地址转换(NAT)和代理服务器等技术的广泛应用,不同内网之间的主机可以使用相同的公网IP地址。IP地址与端口共同来标识网络上特定主机上的特定应用程序,俗称Socket。
局域网地址范围分三类,以下IP段为内网IP段:?
C类:192.168.0.0 - 192.168.255.255
B类:172.16.0.0 - 172.31.255.255?
A类:10.0.0.0 - 10.255.255.255
4、拓展——pygeolist
作用:关联ip地址与地理位置
先使用pyp安装pygeoip
GeoLiteCity.dat: https://github.com/mbcc2006/GeoLiteCity-data
使用的是一个随便找的代理ip
import pygeoip
geo = pygeoip.GeoIP('F:\TOOLS\GeoLiteCity-data-master\GeoLiteCity.dat')
geo.record_by_name('183.141.110.74')
?详细使用以及字段含义:
https://www.cnblogs.com/ssooking/p/6097436.html
4、网络接口层
MAC地址也称为网卡物理地址,具有唯一性,是一个48位的二进制数,用来标识不同的网卡物理地址。
使用ipconfig/all或ifconfig可以查询
(1)更改mac地址
可以用来隐藏自己,或者解决ip封禁问题
更改随机mac
- ifconfig wlan0 down?? //关掉网卡
- macchanger -r wlan0?? //随机生成mac地址
- ifconfig wlan0 up???????? //开启网卡
- ifconfig???????????????????????? //查询mac
更改指定mac
-m 指定自定义的mac地址
- ifconfig wlan0 down?? //关掉网卡
- macchanger -m? 01:23:45:67:89:10 wlan0
- ifconfig wlan0 up???????? //开启网卡
- ifconfig???????????????????????? //查询mac、
二、socket编程
1、简介
套接字(Socket)是计算机之间进行通信的一种约定。通过 Socket,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。套接字(Socket)是计算机之间进行通信的一种约定。通过 Socket,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。
通信过程如下:
- 服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),等待客户端连接。
- 客户端初始化一个Socket,客户端的套接字必须首先指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求(connect)。
- 当服务器端套接字接收到客户端套接字的连接请求,响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,由此连接建立成功。
?2、UDP编程
UDP属于无连接协议,在编程时不需要建立连接,而是直接向接收方发送信息。UDP不提供应答重传机制,无法保证数据一定能够到达目的地。
- socket(family[,type[,proto]]):创建一个Socket对象,family为socket.AF_INET表示使用IPV4,socket.AF_INET6表示使用IPV6;type为SOCK_STREAM表示使用TCP,SOCK_DGRAM表示使用UDP。
- sendto(string,address):把string指定的内容发送给address指定的地址,其中address是一个包含接收方主机IP地址和应用进程端口号的元组,格式为(IP地址,端口号)。
- recvfrom(bufsize[,flags]):接收数据。
?UDP协议优点:效率高、首部中只包含双方地址与校验和等很少的字段,额外开销小。
1、udp_socket_server.py
import socket
ip= input('请输入要连接的ip:')
port = input('请输入要连接的端口:')
ip_addr = (ip,int(port))
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)#连接
s.bind(ip_addr)#绑定 ip为str,port为int
print('绑定ip:'+ ip)
print('绑定端口:'+ port)
while True:
data,addr = s.recvfrom(1024)#接收数据
print('接收数据来自:'+str(addr))
print('接收数据:'+data.decode())#解密数据
send_info = input('请输入:')#传输数据
s.sendto(send_info.encode(),addr)
if data.decode().lower() == 'q':
break
s.close()
2、udp_socket_client.py
import socket
ip = input('请输入连接的ip:')
port = input('请输入要连接的端口:')
ip_addr = (ip,int(port))
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while True:
info = input('请输入:')#发送数据
s.sendto(info.encode(),ip_addr)
data,addr = s.recvfrom(1024)#接收数据
print('接收数据来自:'+str(addr))
print('接收数据:'+ data.decode())
if data.decode().lower() == 'q':
break
s.close()
?3、TCP编程
TCP一般用于可靠数据传输的场合, UDP编程经常用到socket模块方法如下所示:
①
socket(family[,type[,proto]])
:创建一个
Socket
对象,
family
为
socket.AF_INET
表示使用
IPV4
,
socket.AF_INET6
表示使用
IPV6
;
type为SOCK_STREAM表示使用TCP,SOCK_DGRAM表示使用UDP。
②connect(address):连接远程主机;
③
send(bytes[,flags])
:发送数据;
④
recv
(
bufsize
[,flags])
:接收数据;
⑤
bind(address)
:绑定地址;
⑥
listen(backlog)
:开始监听,等待客户端连接,
blacklog
排队数,
backlog+1
表示允许的最大连接数;
⑦
accept()
:响应客户端的请求,接收一个连接;
1、tcp_socket_server.py
import socket
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip_addr = ('127.0.0.1',8888)
s.bind(ip_addr) #传入一个元组,(str,int)
s.listen(1)
print('监听中...')
print('监听端口号:8888')
conn,addr = s.accept()
print('已连接到:',addr)
while True:
data = conn.recv(1024)
data = data.decode()
print('接收:'+data)
info = input('请输入:')
conn.sendall(info.encode())
if data.lower() == 'q':
break
conn.close()
s.close()
2、tcp_socket_client.py
import socket
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip_addr = ('127.0.0.1',8888)
try:
s.connect(ip_addr)
except:
print('服务器未开启...')
while True:
info = input('请输入:')
s.sendall(info.encode())
data = s.recv(1024).decode()
print('接收:'+ data)
if data.lower() == 'q':
break
s.close()
?3、tcp编程拓展
①
Gethostname
()
:获取本地主机名;
②
Gethostbyname
()
:根据主机名获取
ip
地址;
③
Gethostbyaddr
()
:根据
ip
地址获取主机名;
④
Getservbyport
()
:根据端口号获取主机名;
⑤
Getservbyname
()
:根据服务名获取对应的端口号;
import socket
hostname = socket.gethostname()
ip = socket.gethostbyname(hostname)
addr = socket.gethostbyname("www.baidu.com")
host = socket.gethostbyaddr(ip)
sername = socket.getservbyport(3389, "tcp")
port = socket.getservbyname('http')
print("gethostname:",hostname)
print("gethostbyname:",ip)
print("gethostbyname:",addr)
print("gethostbyaddr:",host)
print("getservbyport:",sername)
print("getservbyname:",port)
?三、socket传输文件
fileServer.py
import socketserver
import sys
import re
import json
from optparse import OptionParser
import struct
import os
def operafile(filename):
file_size = os.path.getsize(filename)#获取文件大小
rex = re.compile(r'([^<>/\\\|:""\*\?]+\.\w+$)')#匹配文件名
data = rex.findall(filename)
head_dir={
'filename':data,
'file_size':file_size
}
head_info = json.dumps(head_dir) #json.dump把一个python数据结构转化成json
head_info_len = struct.pack('i',len(head_info))
return head_info_len, head_info
def sendFile(conn,head_info,head_info_len,filename):
try:
conn.send(head_info_len)
conn.send(head_info.encode('utf-8'))
with open(filename,'rb') as f:
conn.sendall(f.read())
print('[+]发送文件成功:' + filename )
except:
print('[+]发送文件失败:'+ filename)
class MyServer(socketserver.BaseRequestHandler):
buffersize = 1024
def handle(self):
print('[+]客户端连接到:',self.client_address[0],'\n')
while True:
filename = input('请输入要发送的文件名>>>').strip()#移除字符串头尾的空格
if filename =='exit':
break
head_info_len, head_info = operafile(filename)#提取文件名
sendFile(self.request,head_info, head_info_len,filename)#文件发送
self.request.close()
def main():
parser = OptionParser("Usage:%prog -p <ip port>")
parser.add_option('-p', type='int', dest='port', help='input the ip port')
options, args = parser.parse_args()
target_port = options.port
print('[+]正在监听端口:',target_port)
s = socketserver.ThreadingTCPServer(('127.0.0.1',target_port), MyServer)#myserever是类
s.serve_forever()
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print('interrupted by user,killing all threads...')
fileClient.py
import socket
import os
import sys
import json
import struct #python与c中的数据类型转化
from optparse import OptionParser
def recv_file(head_dir,tcp_client):
filename = head_dir['filename']
file_size = head_dir['file_size']
print('[+]文件名:' + filename[0])
print('[+]文件大小:' + str(file_size))
print('*'*10 + '文件传输中' + '*'*10)
recv_len = 0
f = open(filename[0],'wb')
while recv_len < file_size:
if file_size > 1024:
recv_mg = tcp_client.recv(1024)
recv_len += len(recv_mg)
f.write(recv_mg)
else:
recv_mg = tcp_client.recv(file_size)
recv_len = len(recv_mg)
f.write(recv_mg)
f.close()
print('[+]文件传输完成...')
def main():
parser = OptionParser("Usage: %prog -u <target ip address> -p <target port>")
parser.add_option('-u',type='string',dest='ip',help='input the ip address')
parser.add_option('-p',type='int',dest='port',help='input the port of ip address')
options,args = parser.parse_args()
target_ip = options.ip
target_port = options.port
#print(target_ip , target_port)
#socket初始化
tcp_client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip_port = (target_ip,target_port)
tcp_client.connect_ex(ip_port)#有返回值的连接socket
print('[+]等待服务器应答......')
struct_len = tcp_client.recv(4)#int类型本机占4位
struct_info_len = struct.unpack('i',struct_len)[0]#i 代表C struct中的int类型,解析得到头部信息
print('[+]接收头部信息长度是:'+ str(struct_info_len))
head_info = tcp_client.recv(struct_info_len)#获取报头内容
head_dir = json.loads(head_info.decode('utf-8'))#报头反序列化
print('[+]接收头部信息:'+str(head_dir))
#接收文件具体内容
recv_file(head_dir,tcp_client)
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print('interrupted by user,killing all threads...')
?
?
|