1.IP地址
以下均为初学者的理解:
- IP地址:用来在网络中标记一台电脑,比如192.168.249.1;在本地局域网上是唯一的。(就像家庭地址一样,通过这个地址可以找到你。)
- IP地址分为:IPv4和IPv6
IPv4:
- IPv4由四组数字(192.168.249.1)组成,每组最小数值为0,最大数值为255,也就是0-255共256个数字。共有256**4种排列方式。
- IPv4地址被全世界不同的国家划分,现在已经被划分完了(由于计算机是美国人发明的当时计算机不普及,256**4已经是很大的一组数字了,没想到后来计算机这么普及,就出现了不够用的情况)。比如中国划分其中的一部分,然后再在各个省就行划分,依次向下划分。所以,如果你再网络上犯罪的话,通过IPv4地址可以准确的找到你。
- IPv4地址分为A、B、C、D、E五大类。
- 其中D类分用于多点广播:
单播:一对一
多播:一对多,我理解为:就像QQ群,群主说话只有群里的人能听的到
广播:一对所有,我理解为:就像微博,大家都可以看到
IPv6:
- 由于IPv4地址已经被划分完了,所以出现了IPv6地址(IPv5是实验室的测试版本,还是以IPv4的四组数字进行扩展的,最终失败,现在已经死掉了。)
2.端口
-
比如一台电脑PC1上装有QQ,微信,微博等等,
-
另外一台电脑PC2上也装有QQ,微信,微博等等。
-
现在你要把PC1上QQ的数据内发到PC2上的QQ中,首先要知道PC2的IP地址(为了找到这台电脑),其次还要知道QQ的端口号(不然找到了,这台电脑,数据就不知道该发给QQ,还是微信或者微博)
-
端口号分为知名端口号(Well Known Ports)和动态端口号(Dynamic Ports):
知名端口是众所周知的端口号,范围从0到1023,如:
80端口分配给HTTP服务
21端口分配给FTP服务
22端口分配给SSH服务
详情点击端口号对照表动态端口的范围是从1024到65535
之所以称为动态端口,是因为它一般不固定分配某种服务,而是动态分配。
动态分配是指当一个系统程序或应用程序程序需要网络通信时,它向主机申请一个端口,主机从可用的端口号中分配一个供它使用。
当这个程序关闭时,同时也就释放了所占用的端口号
socket
socket(简称 套接字) 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:
它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的
例如我们每天浏览网页、QQ 聊天、收发 email 等等
函数 socket.socket 创建一个 socket,该函数带有两个参数:
Address Family:可以选择 AF_INET(用于 Internet 进程间通信) 或者
AF_UNIX(用于同一台机器进程间通信),实际工作中常用AF_INET
Type:套接字类型,可以是SOCK_STREAM(流式套接字,主要用于 TCP 协议)或者 SOCK_DGRAM(数据报套接字,主要用于 UDP 协议)
UDP流程图
- 关于编码问题:Windows默认使用的是gbk编码,Linux默认使用的是utf-8编码。
- 发数据用encode()指定编码,如encode(“utf-8”)
- 接收数据使用decode()指定解码,如decode(“gbk”)
- yy_01_socket的基本使用
import socket
def main():
# 创建一个udp套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 可以使用套接字收发数据
# udp_socket.sendto("hahah", 对方ip以及port)
udp_socket.sendto(b"haha", ("10.10.33.103", 8080))
# 关闭套接字
udp_socket.close()
if __name__ == '__main__':
main()
- yy_02_发送任意数据给windows中的网络调试助手
import socket
def main():
# 创建一个udp套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 可以使用套接字收发数据
# udp_socket.sendto("hahah", 对方ip以及port)
i = input("请输入要发送的内容:")
# udp_socket.sendto(b"haha", ("10.10.33.103", 8080))
udp_socket.sendto(i.encode("utf-8"), ("10.10.33.103", 8080))
# 关闭套接字
udp_socket.close()
if __name__ == '__main__':
main()
- yy_03_循环发送数据
import socket
def main():
# 创建一个udp套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
# 可以使用套接字收发数据
# udp_socket.sendto("hahah", 对方ip以及port)
i = input("请输入要发送的内容:")
if i == "exit":
break
# udp_socket.sendto(i.encode('utf-8'), ("192.168.245.8", 8080))
udp_socket.sendto(i.encode('gbk'), ("192.168.245.8", 8080))
# 关闭套接字
udp_socket.close()
if __name__ == '__main__':
main()
yy_04_绑定端口用来接收数据
import socket
def main():
# 1.创建套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 2.绑定一个本地信息
localaddr = ("", 7788)
# udp_socket.bind(第一个数据填ip地址 ""是默认本地, 第二个数据填端口号)
udp_socket.bind(localaddr)
# 3.接收数据
resv_date = udp_socket.recvfrom(1024) # 1024表示只能接收1024个字节
# 4.打印接收到的数据
print(resv_date)
# 5.关闭套接字
udp_socket.close()
if __name__ == '__main__':
main()
yy_05_解析出接收到的数据
import socket
def main():
# 1.创建套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 2.绑定一个本地信息
localaddr = ("", 7788)
# udp_socket.bind(第一个数据填ip地址 ""是默认本地, 第二个数据填端口号)
udp_socket.bind(localaddr)
# 3.接收数据
resv_date = udp_socket.recvfrom(1024)
# resc_date这个变量中储存的是一个元组(接收到的数据, (发送方的ip,发送方的端口port))
resv_msq = resv_date[0] # 存储接收到的数据
send_addr = resv_date[1] # 存储发送方的ip,发送方的端口port
# 4.打印接收到的数据
# print("接收到的数据:%s \n发送方信息:%s" % (resv_msq.decode('utf-8'), str(send_addr)))
print("接收到的数据:%s \n发送方信息:%s" % (resv_msq.decode('gbk'), str(send_addr)))
# 5.关闭套接字
udp_socket.close()
if __name__ == '__main__':
main()
yy_06_循环接受数据并显示数据
import socket
def main():
# 1.创建套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 2.绑定一个本地信息
localaddr = ("", 7788)
# udp_socket.bind(第一个数据填ip地址 ""是默认本地, 第二个数据填端口号)
udp_socket.bind(localaddr)
while True:
# 3.接收数据
resv_date = udp_socket.recvfrom(1024)
# resc_date这个变量中储存的是一个元组(接收到的数据, (发送方的ip,发送方的端口port))
resv_msq = resv_date[0] # 存储接收到的数据
send_addr = resv_date[1] # 存储发送方的ip,发送方的端口port
# 4.打印接收到的数据
# print("接收到的数据:%s \n发送方信息:%s" % (resv_msq.decode('utf-8'), str(send_addr)))
print("%s: %s" % (str(send_addr), resv_msq.decode('gbk')))
# 5.关闭套接字
udp_socket.close()
if __name__ == '__main__':
main()
- 未完待续
yy_07_先绑定端口然后再循环发送
import socket
def main():
# 创建一个udp套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 绑定本地信息
udp_socket.bind(("", 6666))
while True:
# 可以使用套接字收发数据
# udp_socket.sendto("hahah", 对方ip以及port)
i = input("请输入要发送的内容:")
if i == "exit":
break
# udp_socket.sendto(i.encode('utf-8'), ("192.168.249.1", 8080))
udp_socket.sendto(i.encode('gbk'), ("192.168.249.1", 8080))
# 关闭套接字
udp_socket.close()
if __name__ == '__main__':
main()
yy_08_使用同一个套接字进行收发数据
import socket
def main():
# 创建一个udp套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 绑定ip/port
udp_socket.bind(("", 7788))
# 获取对方ip/port
dest_ip = input("请输入对方的ip:")
while True:
try:
dest_port = int(input("请输入对方的port:"))
break
except Exception as e:
print("输入错误,请输入正确的port")
while True:
# 可以使用套接字收发数据
# udp_socket.sendto("hahah", 对方ip以及port)
i = input("请输入要发送的内容:")
if i == "exit":
break
# udp_socket.sendto(i.encode('utf-8'), ("192.168.249.1", 8080))
udp_socket.sendto(i.encode('utf-8'), (dest_ip, dest_port))
# 接收送回的数据
resv_date = udp_socket.recvfrom(1024)
resv_msq = resv_date[0]
send_addr = resv_date[1]
if resv_date:
print("%s: %s" % (send_addr, resv_msq.decode("utf-8")))
# 关闭套接字
udp_socket.close()
if __name__ == '__main__':
main()
yy_09_udp聊天
import socket
def send_msg(udp_socket):
"""发送内容"""
dest_ip = input("请输入对方ip:")
while True:
try:
dest_port = int(input("请输入对方port:"))
break
except Exception as e:
print("请输入正确的port")
send_data = input("请输入要发送的内容:")
if send_data == "exit":
exit()
udp_socket.sendto(send_data.encode("utf-8"), (dest_ip, dest_port))
def recv_msg(udp_socket):
"""接收数据"""
recv_data = udp_socket.recvfrom(1024)
print("%s:%s" % (recv_data[1], recv_data[0].decode("utf-8")))
def main():
# 创建套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 绑定信息
udp_socket.bind(("", 7788))
# 利用循环处理事情
while True:
# 发送
send_msg(udp_socket)
# 接收
recv_msg(udp_socket)
if __name__ == '__main__':
main()
yy_10_udp聊天升级,可控制流程
import socket
def send_msg(udp_socket):
"""发送内容"""
dest_ip = input("请输入对方ip:")
while True:
try:
dest_port = int(input("请输入对方port:"))
break
except Exception as e:
print("请输入正确的port")
send_data = input("请输入要发送的内容:")
if send_data == "exit":
exit()
udp_socket.sendto(send_data.encode("utf-8"), (dest_ip, dest_port))
def recv_msg(udp_socket):
"""接收数据"""
recv_data = udp_socket.recvfrom(1024)
print("%s:%s" % (recv_data[1], recv_data[0].decode("utf-8")))
def main():
# 创建套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 绑定信息
udp_socket.bind(("", 7788))
# 利用循环处理事情
while True:
print("-" * 50)
print("yy聊天器 v1.0")
print("1.发送消息:")
print("2.接收消息:")
print("0.推出程序")
a = input("请输入选择")
if a in ["1", "2", "0"]:
if a == "1":
# 发送
send_msg(udp_socket)
elif a == "2":
# 接收
recv_msg(udp_socket)
elif a == "0":
print("退出程序")
break
else:
print("请输入正确的选项")
if __name__ == '__main__':
main()
目前还没学进程,只能实现要么收要么发,不能同时进行,后续学完进行代码改进。