第7章 Python socket编程

Python socket编程

1、IP地址简介

目的:用来标记网络上的一台电脑

windows和Linux查看网卡信息
Linux中 ifconfig
windows中 ipconfig

IP地址的分类
在这里插入图片描述

端口
在这里插入图片描述

端口分类

1.1 知名端口(well known ports)

80端口分配给HTTP服务
21端口分配给FTP服务
知名端口的范围是从0到1023

1.2 动态端口

动态端口的范围是从1024-65535

2、socket简介

2.1 TCP/IP协议

TCP/IP协议是Transmission Control Protocol/Internet Protocol的简写,即传输控制协议/因特网互联协议,又名网络通讯协议,是Internet最基本的协议、Internet国际互联网络的基础,由网络层的IP协议和传输层的TCP协议组成。

TCP/IP 定义了电子设备如何连入因特网,以及数据如何在它们之间传输的标准。协议采用了4层的层级结构,每一层都呼叫它的下一层所提供的协议来完成自己的需求。

TCP/IP协议
TCP/IP网络模型四层模型从根本上和OSI七层网络模型是一样的,只是合并了几层
在这里插入图片描述

2.2 socket

socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。白话说,socket就是两个节点为了互相通信,而在各自家里装的一部’电话’。

2.2.1 socket的使用

1.创建套接字ipv4(socket.AF_INET),udp套接字(socket.SOCK_DGRAM )
udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
2.使用套接字收/发数据
udp_socket.sendto(send_data.encode(‘gbk’),(ipaddr,8888))
3.关闭套接字
udp_socket.close()

2.3 udp发送与接收程序

2.3.1 udp发送数据

#创建套接字
#family = AF_INET, 协议族     AF_INET ipv4
#套接字类型 type = UDP(数据报套接字 SOCK_DGRAM)、TCP(流式套接字 SOCK_STREAM)
#AF_INET = 2
#AF_INET6 = 23
import socket
def main():
    #创建一个udp套接字
    # ipaddr = '192.168.2.119'
    # ipaddr = '127.0.0.1'
    ipaddr = 'localhost'
    send_data = 'python'
    udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    udp_socket.sendto(send_data.encode('gbk'),(ipaddr,8888))
    udp_socket.close()

if __name__ == '__main__':
    main()

接收数据测试工具:NetAssist.exe
在这里插入图片描述
使用while循环,时刻处于数据发送状态
1 创建套接字
2 发送数据
3 关闭套接字

def main():
    #1、创建一个udp套接字
    ipaddr = '192.168.2.119'
    # ipaddr = '127.0.0.1'
    # ipaddr = 'localhost'
    # send_data = '123'
    udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    #""默认代表本机ip
    bind_str = ("",8080)
    udp_socket.bind(bind_str)
	#发送数据
    while True:
        send_data = input('请输入发送内容:')
        if send_data == 'exit' or send_data == 'quit':
            break
        udp_socket.sendto(send_data.encode('gbk'),(ipaddr,8888))
    udp_socket.close()
if __name__ == '__main__':
    main()

2.3.2 udp接收数据

1 创建套接字
2 绑定本地信息(IP和端口)
3 接收数据
4 打印数据
5 关闭套接字

import socket
def main():
	#1、创建socket套接字
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    
    #2、绑定本地信息 bind_addr的 "" 表示绑定本机任意ip
    bind_addr = ("",7789)
    udp_socket.bind(bind_addr)

    #3、接收数据,1024 表示本次接收的最大字节数
    recv_data = udp_socket.recvfrom(1024)
    #以元组形式接收信息:数据  (发送方的ip,端口号)
    #(b'juran', ('192.168.2.119', 8888))
    
    #4、打印套接字
    print(recv_data)
    
    #5、关闭套接字
    udp_socket.close()

if __name__ == '__main__':
    main()

用 while True 循环持续接收数据

import socket
def main():
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    #bind_addr的 "" 表示绑定本机任意ip
    bind_addr = ("",7789)
    udp_socket.bind(bind_addr)

    while True:
        #1024 表示本次接收的最大字节数
        recv_data = udp_socket.recvfrom(1024)
        #元组  接收到的数据  (发送方的ip,端口号)
        #(b'juran', ('192.168.2.119', 8888))
        recv_addr = recv_data[1]
        recvdata = recv_data[0]
        print('%s:%s'%((str(recv_addr)),(recvdata.decode('gbk'))))

    # print(recv_data)
    udp_socket.close()

if __name__ == '__main__':
    main()

端口绑定问题
如果程序运行时,没有绑定端口,那么操作系统会自动分配一个端口给程序。 而且同一端口,不能用两次。

2.4 udp聊天器

1.创建套接字 套接字是可以同时收发数据的
2.发送数据
3.接收数据

#定义发送数据函数
def send_data(udp_socket):
    ipaddr = '192.168.2.119'
    senddata = input('请输入发送内容:')
    udp_socket.sendto(senddata.encode('gbk'),(ipaddr,8888))

#定义接收数据的函数
def recv_data(udp_socket):
    recv_data = udp_socket.recvfrom(1024)
    print('%s:%s'%(recv_data[1], recv_data[0].decode('gbk')))

import socket
def main():
    #创建UDP套接字
    udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    #绑定本地信息(IP和端口)
    udp_socket.bind(("",8888))
    while True:
        #发送数据
        send_data(udp_socket)

        #接收数据
        recv_data(udp_socket)
    
    #关闭套接字
    udp_socket.close()

if __name__ == '__main__':
    main()

3、TCP

介绍

  • TCP协议,传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议
  • TCP通信需要经过创建连接、数据传送、终止连接三个步骤。
  • TCP通信模型中,在通信开始之前,一定要先建立相关连接,才能收发数据。

3.1TCP特点

  • 面向连接
  1. 通信双方必须先建立连接才能进行数据的传输
  • 可靠传输
  1. TCP采用发送应答机制
  2. 超时重传
  3. 错误校验
  4. 流量控制和阻塞管理

3.2 TCP与UDP区别总结

1、TCP面向连接;UDP是无连接的,即发送数据之前不需要建立连接

2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付

3、UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。

4、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信

5、TCP对系统资源要求较多,UDP对系统资源要求较少。

UDP通信
在这里插入图片描述

TCP通信
在这里插入图片描述

TCP服务器端:就是提供服务的一方
而客户端,就是需要被服务的一方

3.3 TCP客户端构建流程

1.创建socket
2.链接服务器
3.接收数据(最大接收2014个字节)
4.关闭套接字

import socket


def main():
    # 创建 TCP 套接字
    tcp_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    #建立连接,服务器ip 和 服务器端口
    tcp_addr = ('192.168.2.119')
    tcp_client.connect((tcp_addr, 7788))

    #发送数据
    send_data = input("发送数据:")
    tcp_client.send(send_data.encode())

    #接收数据
    recv_data = tcp_client.recv(1024)
    print(recv_data.decode('gbk'))

    #关闭套接字
    tcp_client.close()


if __name__ == '__main__':
    main()

3.4 TCP服务端

1 socket创建套接字
2 bind绑定IP和port
3 listen使套接字变为可以被动链接
4 accept等待客户端的链接
5 recv/send接收发送数据

import socket


def main():
    # 创建 TCP 套接字
    tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    #绑定服务器ip 和 端口号
    tcp_server.bind(("192.168.2.119", 7890))

    #使套接字变为可以被动链接
    tcp_server.listen(128)

    #等待客户端链接
    new_client_socket, client_addr = tcp_server.accept()

    #等待接收客户端数据
    recv_data = new_client_socket.recv(1024)
    print(client_addr, recv_data.decode('gbk'))
    
    #给客户端发送数据
    new_client_socket.send('haha'.encode('gbk'))

    #关闭客户端连接和套接字
    new_client_socket.close()
    tcp_server.close()


if __name__ == '__main__':
    main()

上面代码配合网络调试助手测试

3.5 TCP服务端为多个客户端服务

'''
为多个客户端服务
1 socket创建套接字
2 bind绑定IP和port
3 listen使套接字变为可以被动链接
4 accept等待客户端的链接
5 recv/send接收发送数据
6 关闭连接,关闭套接字
'''
import socket


def main():
    # 创建TCP套接字
    tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    #绑定连接ip 和 端口号
    tcp_server.bind(('', 7788))

    #使套接字变为可以被动链接
    tcp_server.listen(128)
    while True:
        # print('-----1-----')
        #等待客户端连接
        new_client_socket, client_addr = tcp_server.accept()
        # print('-----2-----')

        while True:
            #等待接收客户端数据
            recv_data = new_client_socket.recv(1024)
            print(recv_data.decode('gbk'))

            #1、接收客户端发送的数据;2、接收客户端断开的消息 b''
            if recv_data:
                new_client_socket.send('哈哈,接收到数据反馈'.encode('gbk'))
            else:
                break
        new_client_socket.close()

    tcp_server.close()


if __name__ == '__main__':
    main()

3.6 TCP文件下载器

TCP客户端
1.创建套接字
2.目的信息 服务器的ip port
3.连接服务器
4.输入要下载的文件名称
5.发送文件下载请求
6.接收对方发送过来的数据
7.接收到数据再创建文件
8.关闭套接字

import socket


def main():
    # 创建TCP套接字
    tcp_socket_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 连接服务器
    tcp_socket_client.connect(("192.168.2.119", 7890))
    #
    filename = input('请输入下载文件名:')
    #发送文件下载请求
    tcp_socket_client.send(filename.encode('gbk'))
    #接收文件
    recv_data = tcp_socket_client.recv(1024 * 1024)
    #写入本地文件
    if recv_data:
        with open('接收' + filename, 'wb') as f:
            f.write(recv_data)

    #关闭套接字
    tcp_socket_client.close()


if __name__ == '__main__':
    main()

TCP服务端
1 socket创建套接字
2 bind绑定IP和port
3 listen使套接字变为可以被动链接
4 accept等待客户端的链接
5 recv/send接收发送数据

import socket


def send_file_client(new_client_socket):
    # 接收客户端发送过来的数据
    file_name = new_client_socket.recv(1024).decode()
    print('文件名:', file_name)
    content = b""
    try:
        with open(file_name, 'rb') as f:
            content = f.read()
    except:
        print('no download file:%s' % file_name)
    new_client_socket.send(content)
    new_client_socket.close()


def main():
    # 创建套接字
    tcp_socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    #绑定ip 和 端口
    tcp_socket_server.bind(("192.168.2.119", 7890))

    #使套接字可以变为被动链接
    tcp_socket_server.listen(128)

    #接收客户端连接
    new_client_socket, client_addr = tcp_socket_server.accept()

    #调用客户端函数,返回文件内容
    send_file_client(new_client_socket)

    tcp_socket_server.close()


if __name__ == '__main__':
    main()
发布了31 篇原创文章 · 获赞 0 · 访问量 344

猜你喜欢

转载自blog.csdn.net/weixin_38027481/article/details/103874940