IP地址
目的:用来标记网络上的一台电脑
windows和Linux查看网卡信息
Linux中 :ifconfig
windows中: ipconfig
IP地址的分类
ipv4的地址最多的可能性为:256 * 256 * 256 * 256
因为ipv4的模式是:192.168.1.123,每个字段的取值范围是0–255,总计4个字段,所以是256 * 256 * 256 * 256。
端口分类
1.知名端口(well known ports) (不能被使用了)
80端口分配给HTTP服务
21端口分配给FTP服务
- 范围是从0到1023
2.动态端口
动态端口的范围是从1024-65535
(主要使用这部分端口)
下图为使用软件占用端口进行发送回复信息的过程:
1、左边发送信息到右边要包含有
对方ip:dest_ip 、对方软件占用的端口:port、本机的ip地址:scr_ip、本机软件占用的端口:scr_port
加上发送的信息,总计5条内容,才能完成通讯。
socket简介
TCP/IP协议
TCP/IP协议是Transmission Control Protocol/Internet Protocol的简写,即传输控制协议/因特网互联协议,又名网络通讯协议,是Internet最基本的协议、Internet国际互联网络的基础,由网络层的IP协议和传输层的TCP协议组成。
TCP/IP 定义了电子设备如何连入因特网,以及数据如何在它们之间传输的标准。协议采用了4层的层级结构,每一层都呼叫它的下一层所提供的协议来完成自己的需求。
TCP/IP网络模型四层模型从根本上和OSI七层网络模型是一样的,只是合并了几层
上图中需要注意的是:应用层的SMTP适用于邮件收发的、DNS是用于网址解析的;
socket
socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。白话说,socket就是两个节点为了互相通信,而在各自家里装的一部’电话’。
网络通信软件中都会用到socket编程
socket通信的使用步骤:
1.创建套接字
2.使用套接字收/发数据
3.关闭套接字
# 创建套接字
import socket
"""socket部分源码
class socket(_socket.socket):
'''A subclass of _socket.socket adding the makefile() method.'''
__slots__ = ["__weakref__", "_io_refs", "_closed"]
def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None):
"""
'''
# 上面源码的解析:默认
# family=AF_INET 协议族 AF_INET是属于ipv4的 AF_INET6是属于ipv6的
# type=SOCK_STREAM 套接字类型 SOCK_STREAM是TCP的流式套接字 SOCK_DGRAM是UDP的数据报套接字
'''
'''
AF_INET = 2 ipv4 默认值 在代码中只写英文用于代表值2,为了避免歧义,数字代码一般看不懂所代表的含义
AF_INET6 = 23 ipv6 默认值
'''
# 使用套接字 收/发 数据
s = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM) # 采用ipv4 和 UDP类型套接字进行创建
# 关闭套接字
s.close()
udp发送数据程序,使用NetAssist软件接收数据
import socket
def main():
# 创建套接字
udp_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
# 发送数据 参数中包含有 发送内容、本机ip地址、端口
# udp_socket.sendto(b'hello world', ('192.168.0.111', 8080))
'''
udp_socket.sendto(b'hello python', ('127.0.0.1', 7080)) # 注意端口的改变,要匹配NetAssist软件上的端口和ip地址
udp_socket.sendto(b'hello world', ('localhost', 7080)) # 本机的localhost就是公网ip=127.0.0.1,所以上下两句功能相同
'''
'''
发送内容必须是字节类型,此时可以在前面加上 b 字符转换成字节类型,即
udp_socket.sendto(b'hello world', ('192.168.0.111', 8080))
'''
send_data = '你好!'
udp_socket.sendto(send_data.encode('gbk'), ('192.168.0.111', 7080))
'''
encode编码 decode解码
window系统中文的编码是gbk 如果要发中文需要使用gbk编码解码
'''
# 关闭
udp_socket.close()
if __name__ == '__main__':
main()
注意下图中的端口的改变,要匹配NetAssist软件上的端口和ip地址
udp持续发送数据程序,使用NetAssist软件持续接收数据
import socket
def main():
# 创建套接字
udp_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
while True: # 死循环为了一直发送数据信息
send_data = input('请输入发送的信息:')
if send_data == 'exit':
break # 输入特殊字符,跳出死循环,程序结束
send_data = send_data.encode('utf-8') # 发送信息是英文的编码方式
udp_socket.sendto(send_data, ('192.168.0.111', 7080)) # 注意ip地址和端口与NetAssist软件中的设置相同
# 注意参数里面有元祖 ('192.168.0.111', 7080),括号的问题
udp_socket.close()
if __name__ == '__main__':
main()
下图为持续发送的信息在NetAssist软件中被接收:
注意发送数据时候,端口没有进行绑定,此时的接收数据端口是随机分配的,当然也可以人为的绑定:
即像下面介绍udp接收数据的绑定相同,此时的接收数据端口就会固定。
使用NetAssist软件发送数据,udp接受数据程序
udp接收数据步骤:
1 创建套接字
2 绑定本地信息(IP和端口)
3 接受数据
4 打印数据
5 关闭套接字
端口绑定问题
如果程序运行时,没有绑定端口,那么操作系统会自动分配一个端口给程序。 而且同一端口,不能用两次。
import socket
def main():
# 创建套接字
udp_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
# 绑定端口 bind()绑定函数 传参表示: ' '代表本机任意ip都可以, 8888代表发送端口
bind_address = ('', 8888) # 绑定的是发送方的ip地址
udp_socket.bind(bind_address)
# 接收数据 1024代表接收数据最大字节限制
recv_data = udp_socket.recvfrom(1024)
# print(recv_data) # 打印出接收到的数据 打印的是源ip地址
recv = recv_data[0] # recv接收到的数据
send_data = recv_data[1] # send_data是接收到的元组中的ip地址
print("%s:%s" % (str(send_data), recv.decode('gbk'))) # str()强制元祖类型转换成str类型 recv.decode解码
# 针对接收到的数据进行gbk解码,并且输出ip地址send_data
udp_socket.close()
if __name__ == '__main__':
main()
下图需要注意标注的红色部分的信息:8888代表发送端口和上面的接收端口是不一样的,需要修改匹配才能收发数据成功。(发送的数据内容超出程序设定的1024字节数,会报错)
udp聊天器程序编写
1.创建套接字:套接字是可以同时收发数据的
2.发送数据
3.接收数据
'''
udp聊天器
'''
import socket
# 发送数据
def send_data(udp_socket): # 传参udp_socket
send_data = input('请输入发送的信息:')
dest_ip = input('请输入发送到的ip:')
dest_port = int(input('请输入发送到的端口:')) # 端口必须是整型数据,需要用int()强转
udp_socket.sendto(send_data.encode('gbk'), (dest_ip, dest_port))
# 接收数据
def recv_data(udp_socket):
# 接收数据 1024代表接收数据最大字节限制
recv_data = udp_socket.recvfrom(1024)
print("%s:%s" % (str(recv_data[1]), recv_data[0].decode('gbk')))
def main():
# 创建套接字 同时接受发送数据
udp_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
# 绑定端口和ip
udp_socket.bind(("", 7777)) # 注意传入的是元祖类型参数
# 注意这里的端口和ip要和send_data()方法中的dest_ip、dest_port要相同才行
while True:
# 发送数据
send_data(udp_socket)
# 接收数据
recv_data(udp_socket)
udp_socket.close()
if __name__ == '__main__':
main()
注意绑定的ip和端口要相同