python高级编程学习——05—(TCP/IP协议、socket编程:应用于网络通信软件中的方法)

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.关闭套接字
socket编程在网络协议中的位置

# 创建套接字
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和端口要相同
在这里插入图片描述
在这里插入图片描述

发布了50 篇原创文章 · 获赞 9 · 访问量 2082

猜你喜欢

转载自blog.csdn.net/weixin_42118531/article/details/103870153