Python高级编程技巧第5讲 - Python socket编程

一、IP地址的介绍

1.1 IP地址

windows和Linux查看网卡信息

  • Linux中 ifconfig
  • windows中 ipconfig
1.1.1 IP地址的分类:

在这里插入图片描述

1.2 端口

在这里插入图片描述

1.2.1 端口分类

1.知名端口(well known ports):

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

2.动态端口:

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

二、socket简介

  • TCP/IP协议:TCP/IP协议是Transmission Control Protocol/Internet Protocol的简写,即传输控制协议/因特网互联协议,又名网络通讯协议,是Internet最基本的协议、Internet国际互联网络的基础,由网络层的IP协议和传输层的TCP协议组成。
  • TCP/IP: 定义了电子设备如何连入因特网,以及数据如何在它们之间传输的标准。协议采用了4层的层级结构,每一层都呼叫它的下一层所提供的协议来完成自己的需求。
    在这里插入图片描述

1. socket

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

socket的使用

  1. 创建套接字
  2. 使用套接字收/发数据
  3. 关闭套接字
    在这里插入图片描述

2.创建套接字

import socket
# from socket import socket

# 1、创建套接字
'''
协议族:family = AF_INET,      AF_INET是ipv4     AF_INET6是ipv6
套接字类型:type = SOCK_STREAM,     TCP 流式套接字      UDP SOCK_STREAM数据报套接字
AF_INET = 2
AF_INET6 = 23
'''

s = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)

# 2、使用套接字 收/发 数据

# 3、关闭套接字
s.close()

3.1 udp发送与接收程序

在这里插入图片描述

"""
UDP发送数据
"""
import socket


''''
1、UDP发送数据
'''
def main():
    # 创建一个UDP套接字
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    # 发送数据
        # encode是转码
        # windows  编码是GBK
        # Ubantu   是UTF-8
    send_data = 'CSY is SB 哈哈哈哈,陈思能够与'
    udp_socket.sendto(send_data.encode('gbk'), ('192.168.1.6', 8897))
    # udp_socket.sendto(b'CSY is CQ', ('192.168.1.6', 8897))

    # 关闭连接
    udp_socket.close()


''''
2、UDP循环发送数据
'''
def main1():

    while True:
        send_data = input('输入你想发送的数据:')
        if send_data == '':
            break

        udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

        udp_socket.sendto(send_data.encode('gbk'), ('192.168.1.6', 8897))

	udp_socket.close()


if __name__ == '__main__':
    # main()
    main1()

UDP接收数据

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

'''
UDP接收数据

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

import socket

def main():
    # 1 创建套接字
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    # 2 绑定本地信息(IP和端口)
    bind_addr = ('', 57736)
    udp_socket.bind(bind_addr)

    while True:
        # 3 接受数据
            # 1024 表示本次接收的最大字节数
        recv_data = udp_socket.recvfrom(1024)
            # 元组 接收倒的数据 (发送方的ip , 端口)
            # (b'1', ('192.168.1.6', 8897))

        # 4 打印数据
        recv = recv_data[0]
        send_data = recv_data[1]
        print('发送的ip地址:{},发送的信息:{}'.format(str(send_data), recv.decode('gbk')))

    # 5 关闭套接字
    udp_socket.close()

if __name__ == '__main__':
    main()

3.2 UDP聊天器

udp聊天器

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

import socket


def send_data(udp_socket):
    """发送数据"""
    send_data = input('请输入要发送的数据:')
    dest_ip = input('请输入要发送的IP:')
    dest_port = int(input('请输入要发送的端口:'))

    udp_socket.sendto(send_data.encode('gbk'), (dest_ip, dest_port))


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


def main():
    # 创建套接字  同时接收发送数据
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    # 绑定
    udp_socket.bind(("", 7788))

    while True:
        # 发送
        send_data(udp_socket)
        # 接收
        recv_data(udp_socket)

    # udp_socket.close()

if __name__ == '__main__':
    main()

4.1 TCP介绍

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

4.2 TCP特点

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

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

4.3 TCP客户端构建

TCP客户端构建流程

  • 1.创建socket
  • 2.链接服务器
  • 3.接收数据(最大接收2014个字节)
  • 4.关闭套接字
'''
TCP客户端构建流程
    1.创建socket
    2.链接服务器
    3.接收数据(最大接收1024个字节)
    4.关闭套接字
'''

import socket
# from socket import socket


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

    # 2.链接服务器
    server_ip = '192.168.1.6'
    server_port = int(7891)
    tcp_client.connect((server_ip, server_port))

    # 3.1 发送数据
    send_data = input('发送的数据:')
    tcp_client.send(send_data.encode('gbk'))

    # 3.2 接收数据(最大接收1024个字节)
    # 阻塞
    recvdata = tcp_client.recv(1024)
    print(recvdata.decode('gbk'))

    # 4.关闭套接字
    tcp_client.close()

if __name__ == '__main__':
    main()

在这里插入图片描述

4.3.1 TCP服务端

  1. socket创建套接字
  2. List item
  3. bind绑定IP和port
  4. listen使套接字变为可以被动链接
  5. accept等待客户端的链接
  6. recv/send接收发送数据
  7. 关闭套接字
    在这里插入图片描述
'''
TCP服务端
    1 socket:创建套接字
    2 bind:绑定IP和port
    3 listen:使套接字变为可以被动链接
    4 accept:等待客户端的链接
    5 recv/send:接收发送数据
'''
import socket


def main():
    # 1. TCp 套接字
    tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 2. 绑定
    tcp_server.bind(('192.168.1.6', 7890))

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

    # 4. accept:等待客户端的链接
    """
    accept() -> (socket object, address info)
        socket object 是 新生成的套接字
        address info  是 客户端地址
    """
    new_client_socket, client_addr = tcp_server.accept()

    # 5 recv/send:接收发送数据
    # 5.1 recv:接收数据

    recv_data = new_client_socket.recv(1024)
    print(recv_data.decode('gbk'))

    # 5.2 send:发送数据
    # send_data = input('发送的数据:')
    new_client_socket.send('这是发送的数据'.encode('gbk'))

    # 关闭套接字
    new_client_socket.close()
    tcp_server.close()


if __name__ == '__main__':
    main()

在这里插入图片描述

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

import socket


def main():
    # 1. TCp 套接字
    tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 2. 绑定
    tcp_server.bind(('192.168.1.6', 7890))

    # 为多个客户端服务
    while True:
        # 3. listen:使套接字变为可以被动链接
        tcp_server.listen(128)

        # 4. accept:等待客户端的链接
        """
        accept() -> (socket object, address info)
            socket object 是 新生成的套接字
            address info  是 客户端地址
        """
        new_client_socket, client_addr = tcp_server.accept()

        # 5 recv/send:接收发送数据
        # 5.1 recv:接收数据

        # 为一个客户端多次服务
        while True:
            recv_data = new_client_socket.recv(1024)
            # print(recv_data.decode('gbk'))

            # 5.2 send:发送数据
            # send_data = input('发送的数据:')
            if recv_data.decode('gbk'):
                new_client_socket.send('这是发送的数据'.encode('gbk'))
            else:
                break
        # 关闭客户端
        new_client_socket.close()
    tcp_server.close()


if __name__ == '__main__':
    main()

一个服务端多个客户端服务:
在这里插入图片描述
第一个客户端断开连接后,第二个客户端才回收到服务端发送的数据
在这里插入图片描述

5. 文件下载器

先启动服务器,再启动客户端,不然会报错。

5.1 文件下载器——客户端

'''
TCP文件下载客户端
1、创建套接字
2、连接服务器

3、要下载的文件名称
4、发送下载文件的请求
5、接收服务器发送过来的数据
6、保存文件

7、关闭套接字
'''

import socket


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

    # 2、连接服务器
    server_ip = '192.168.1.6'
    server_port = 7890
    tcp_client_socket.connect((server_ip, server_port))

    # 3、要下载的文件名称
    flie_name = input('输入要下载文件的名称:')

    # 4、发送下载文件的请求
    tcp_client_socket.send(flie_name.encode('gbk'))

    # 5、接收服务器发送过来的数据
    recv_data = tcp_client_socket.recv(1024*1024)

    # 6、保存文件
    # wb 读写
    with open('接收'+flie_name, 'wb') as f:
        f.write(recv_data)

    # 7、关闭套接字
    tcp_client_socket.close()

if __name__ == '__main__':
    main()

在这里插入图片描述

5.2 文件下载器——服务端

'''
TCP文件下载-服务端
1、创建套接字
2、绑定信息
3、listen主动变被动
4、accept 等待客户端的连接
5、发送/接收数据
6、关闭套接字
'''

import socket

def send_file_client(new_client_socket):
    # 接收客户端发送过来的数据
    file_name = new_client_socket.recv(1024).decode()

    content = b''

    try:
        with open(file_name, 'rb') as f:
            content = f.read()
    except Exception as e:
        print('【%s】文件不存在'  % file_name)

    new_client_socket.send(content)

    new_client_socket.close()


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

    # 2、绑定信息
    tcp_server_socket.bind(('192.168.1.6', 7890))

    # 3、listen 主动变被动
    tcp_server_socket.listen(128)

    # 4、accept 等待客户端的连接
    new_client_socket, client_addr = tcp_server_socket.accept()

    # 5、给客户端返回文件内容
    send_file_client(new_client_socket)


    # 6、关闭套接字
    tcp_server_socket.close()


if __name__ == '__main__':
    main()

六、TCP与UDP区别总结

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

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

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值