zoukankan      html  css  js  c++  java
  • 4.1 socket

    socket 

    背景概念

    脑图结构

    OSI 模型

    socket 概念特性

    脑图结构

    理解示意图

     额外补充

      Socket是应用层与 TCP/IP协议族通信的中间软件抽象层,它是一组接口。

      在设计模式中, Socket其实就是一个门面模式

      它把复杂的 TCP/IP协议族隐藏在 Socket接口后面,对用户来说,一组简单的接口就是全部,让 Socket去组织数据,以符合指定的协议。

    TCP_socket

    server

    import socket
    sk = socket.socket()
    sk.bind(('127.0.0.1',8898))  # 把地址绑定到套接字
    sk.listen()  # 监听链接
    conn,addr = sk.accept()  # 接受客户端链接
    ret = conn.recv(1024)  # 接收客户端信息
    print(ret)  # 打印客户端信息
    conn.send(b'hi')  # 向客户端发送信息
    conn.close()  # 关闭客户端套接字
    sk.close()  # 关闭服务器套接字(可选)

    client

    import socket
    sk = socket.socket()  # 创建客户套接字
    sk.connect(('127.0.0.1',8898))  # 尝试连接服务器
    sk.send(b'hello!')
    ret = sk.recv(1024)  # 对话(发送/接收)
    print(ret)
    sk.close()  # 关闭客户套接字

    特性

    粘包

     

    额外补充

      TCP (Transmission Control Protocol)可靠的、面向连接的协议(eg:打电话)、传输效率低全双工通信(发送缓存&接收缓存)、面向字节流。

      使用TCP的应用:Web浏览器;电子邮件、文件传输程序。

    UDP_socket

     

     server

    import socket
    udp_sk = socket.socket(type=socket.SOCK_DGRAM)   #创建一个服务器的套接字
    udp_sk.bind(('127.0.0.1',9000))        #绑定服务器套接字
    msg,addr = udp_sk.recvfrom(1024)
    print(msg)
    udp_sk.sendto(b'hi',addr)                 # 对话(接收与发送)
    udp_sk.close()                         # 关闭服务器套接字

    client

    import socket
    ip_port=('127.0.0.1',9000)
    udp_sk=socket.socket(type=socket.SOCK_DGRAM)
    udp_sk.sendto(b'hello',ip_port)
    back_msg,addr=udp_sk.recvfrom(1024)
    print(back_msg.decode('utf-8'),addr)

    额外补充

      UDP (User Datagram Protocol)不可靠的、无连接的服务,传输效率高(发送前时延小),一对一、一对多、多对一、多对多、面向报文,尽最大努力服务,无拥塞控制。

      使用UDP的应用:域名系统 (DNS);视频流;IP语音(VoIP)。

    其他补充方法

     

    文本笔记

    socket概念
        套接字:实现网络编程进行数据传输的一种技术手段
        相关模块: import  socket
        分类
             流式套接字(SOCK_STREAM): 以字节流方式传输数据,实现tcp网络传输方案。
             数据报套接字(SOCK_DGRAM):以数据报形式传输数据,实现udp网络传输方案。
    
             面向连接--tcp协议--可靠的--流式套接字
             无连接--udp协议--不可靠--数据报套接字
    
    
    tcp套接字编程
        服务端流程
            1. 创建套接字
                sk = socket.socket(socket_family=AF_INET,socket_type=SOCK_STREAM,proto=0)
                功能: 创建套接字
                参数:
                    socket_family       网络地址类型 AF_INET-->ipv4
                    socket_type         选择类型,与 TCP/UDP 中选择, 默认就是 TCP 模式
                        套接字类型 SOCK_STREAM 流式(TCP)
                        SOCK_DGRAM 数据报(UDP)
                    proto  通常为0,可以忽略       选择子协议
                返回值: 套接字对象
            2. 绑定地址
                sk.bind(addr)
                功能: 绑定本机网络地址
                参数: 二元元组 (ip,port)  例如:('0.0.0.0',8888)
            3. 设置监听
                sk.listen(n)
                功能 : 将套接字设置为监听套接字,确定监听队列大小
                参数 : 监听队列大小
            4. 等待处理客户端连接请求
                conn,addr = sk.accept()
                功能: 阻塞等待处理客户端请求
                返回值: conn  客户端连接套接字
                         addr  连接的客户端地址
                * 阻塞函数 : 程序运行过程中遇到阻塞函数则暂停执行,直到达成某种条件后继续运行。
            5. 消息收发
                data = conn.recv(buffersize)
                    功能 : 接受客户端消息
                    参数 :每次最多接收消息的大小
                    返回值: 接收到的内容
    
                n = conn.send(data)
                    功能 : 发送消息
                    参数 :要发送的内容  bytes格式
                    返回值: 发送的字节数
    
                *  str --> bytes   string.encode()
                   bytes --> str   bytes.decode()
            6. 关闭套接字
                sk.close()
                功能:关闭套接字
        """
        import socket
        sk = socket.socket()
        sk.bind(("127.0.0.1", 8008))
        sk.listen()
        conn, addr = sk.accept()
        conn.send(b"hello")
        conn.close()
        sk.close()
        """
    
        客户端流程
            1. 创建套接字
                sk = socket.socket()
               * 只有相同类型的套接字才能进行通信
            2. 请求连接
                sk.connect(server_addr)
                    功能:连接服务器
                    参数:元组  服务器地址
            3. 收发消息
                print(sk.recv(1024))
               * 防止两端都阻塞,recv send要配合
            4. 关闭套接字
        """
        import socket
        sk = socket.socket()
        sk.connect(("127.0.0.1", 8008))
        print(sk.recv(1024))
        sk.close()
        """
    
        代码流程总结
            服务端:socket() --> bind() --> listen() --> accept() --> recv(),send() --> close()
            客户端:socket() --> connect() --> send(),recv() --> close()
    
        整体过程总结
            * tcp连接中当一端退出,另一端如果阻塞在recv,此时recv会立即返回一个空字串。
            * tcp连接中如果一端已经不存在,让然试图通过send发送则会产生BrokenPipeError
            * 一个监听套接字可以同时连接多个客户端,也能够重复被连接
            * 网络收发缓冲区
                【1】网络缓冲区有效的协调了消息的收发速度
                【2】send和recv实际是向缓冲区发送接收消息,当缓冲区不为空recv就不会阻塞。
            * tcp粘包
                【1】 原因:tcp以字节流方式传输,没有消息边界。多次发送的消息被一次接收,此时就会形成粘包。
                【2】 影响:如果每次发送内容是一个独立的含义,需要接收端独立解析此时粘包会有影响。
                【3】 处理:
                    1. 人为的添加消息边界
                    2. 控制发送速度
    
    UDP套接字编程
        服务端流程
            1. 创建数据报套接字
                sk = socket(AF_INET,SOCK_DGRAM)
            2. 绑定地址
                sk.bind(addr)
            3. 消息收发
                data,addr = sockfd.recvfrom(buffersize)
                    功能: 接收UDP消息
                    参数: 每次最多接收多少字节
                    返回值: data  接收到的内容
                            addr  消息发送方地址
                n = sockfd.sendto(data,addr)
                    功能: 发送UDP消息
                    参数: data  发送的内容 bytes格式
                           addr  目标地址
                    返回值:发送的字节数
            4. 关闭套接字
                sockfd.close()
        """
        import socket
    
        udp_sk = socket.socket(type=socket.SOCK_DGRAM)
        udp_sk.bind(('127.0.0.1', 9000))
        msg, addr = udp_sk.recvfrom(1024)
        print(msg)
        udp_sk.sendto(b'hi', addr)
        udp_sk.close()
        """
    
        客户端流程
            1. 创建套接字
                sk=socket.socket(type=socket.SOCK_DGRAM)
            2. 收发消息
                sk.sendto(data,("127.0.0.1",8000))
                sk.recvfrom(1024)
            3. 关闭套接字
                sk.close()
        """
        import socket
    
        sk = socket.socket(type=socket.SOCK_DGRAM)
        addr = ("127.0.0.1", 9000)
        sk.sendto(b"hello", addr)
        data, addr = sk.recvfrom(1024)
        print(data)
        sk.close()
        """
  • 相关阅读:
    Error Creating Deployment 有关Tomcat配置问题
    XML约束
    动态代理的一些问题。
    内部类的原理理解
    子父类覆盖方法和实现接口时牵扯到的细节问题。
    JavaSE 复习_4 接口多态和内部类
    JavaSE复习_3 继承
    JavaSE复习_2 对象与类
    JavaSE复习_1 Java的基本格式和运算符
    Linux 添加用户(user),组(Group)以及权限(Permission)
  • 原文地址:https://www.cnblogs.com/shijieli/p/10339969.html
Copyright © 2011-2022 走看看