1、套接字

  进程通信的接口。

  可以看做对 TCP/IP协议的封装。 

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,

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

  所以,我们无需深入理解tcp/udp协议,socket已经为我们封装好了,我们只需要遵循socket的规定去编程,写出的程序自然就是遵循tcp/udp标准的。


2、目的

  通过编程语言提供的套接字编程接口,可以更简单的完成基于tcp和udp的编程

3、套接字类别

  【1】流式套接字(SOCK_STREAM):

      传输层基于tcp的协议通信, 面向连接可靠的传输

  【2】数据报套接字(SOCK_DGRAM):

      传输层基于udp协议传输 ,面向无连接不可靠的传输 

  【3】底层套接字 (SOCK_RAM): 访问底层协议套接字

4、tcp粘包

  【1】产生原因:

      ① tcp传输以字节流的方式发送消息,消息之间没有边界,每次收发有大小限制

      ② 发送比接受的速度快

  【2】影响 : 对每次发送的内容是一个独立的意思需要单独识别

  【3】如何处理:

      ① 每次发送后加一个结尾标志

      ② 发送一个数据结构

      ③ 每次发送有一个间隔

5、tcp流式套接字和udp数据报套接字区别

  【1】 流式套接字采用字节流方式进行传输,而数据报套接字 使用数据报形式传输数据

  【2】 tcp套接字会产生粘包,udp不会

  【3】 tcp编程可以保证消息的完整性,udp则不能保证

  【4】 tcp需要listen accept,udp不用

  【5】 tcp消息的发送接收使用recv send sendall,udp使用 recvfrom,sendto

6、套接字编程应用--TCP


  【1】服务端:

    ① 创建套接字对象

        sock = socket.socket(sock_family = AF_INET, sock_type = SOCK_STREAM, proto = 0)

        参数 : sock_family,地址族类型 ,通常为AF_INET,表示 ipv4网络通信

            sock_type, 套接字类型, SOCK_STREAM,表示流式套接字。 SOCK_DGRAM,表示数据报套接字

            proto, 通常为0,表示选定的子协议类型 

        功能 : 创建套接字

        返回值 : 返回套接字对象

    ② 绑定地址

        sock.bind(addr) 

        参数 : addr,(ip,port)组成的一个元组 ('0.0.0.0',1234)

        功能 : 绑定地址

    ③ 设置监听套接字

        sock.listen(n)   

        参数: 监听队列大小

        功能: 将套接字设置为监听套接字,创建监听队列

           * 一个监听套接字可以连接多个客户端

    ④ 等待接受客户端连接

        connfd,addr = sock.accept()  

        功能 : 阻塞等待处理客户端连接

        返回值 : connfd 新的套接字,用于和客户端通信

              addr 连接的客户端的地址 (ip,port)

        * 阻塞函数 : 当程序运行到阻塞函数位置,如果某种条件没有达成则暂停程序运行,直到条件达成结束阻塞

    ⑤ 消息的收发

        接收消息:

          data = connfd.recv(buffersize)   

          参数 : 一次接受消息的大小 ,为字节

          功能 : 接受消息

          返回值 : 返回接受到的内容

        发送消息:

          n = connfd.send()   

          参数 : 要发送的内容 (bytes格式)

          功能 : 发送消息

          返回值 : 返回实际发送的字节数

    ⑥ 关闭套接字

        sock.close()

  【客户端】

    ①  创建套接字对象 (和服务端套接字类型相同)

      sock = socket.socket(sock_family = AF_INET, sock_type = SOCK_STREAM, proto = 0)

    ②  发起连接 connect(addr)  

)

      参数 : 服务端地址,是一个元组(ip,port) # 服务端绑定的地址  

      功能 : 向服务端发起连接  

    ③  消息收发

      发送消息:

"Msg>>")

          sock.send(msg.encode())

      接收消息:

1024) # recv方法参数,一次接收数据的大小

          print(data)

    ④  关闭套接字

       sock.close()

7、套接字编程应用-UDP


  【服务端】

     ① 创建套接字对象

      sock = socket(AF_INET,SOCK_DGRAM)

  ②  绑定地址

        sock.bind()

      ③ 消息收发

        【接收消息】:

        data,addr = sock.recvfrom(buffersize)

        功能: 接受UDP消息

        参数: 每次最多接受消息的大小, 字节

        返回值:data, 接收到的内容

            addr, 消息发送方的地址

        * recvfrom每次接收一个报文,如果没有接收完全则丢弃没有收到的内容

        【发送消息】:

          sock.sendto(data,addr)

          功能: UDP消息发送

          参数: data, 要发送的内容 ,bytes

             addr 目标地址

          返回值:发送字节数

     ④  关闭套接字

        sock.close()

  【客户端】

    ① 创建套接字对象

      sock = socket(AF_INET,SOCK_DGRAM)

    ② 消息收发

        【给服务端发送消息】

          sock.sendto(data.encode(),ADDR)

          # data,要发送的数据

          # ADDR,服务端地址(ip,port)

        【接收服务端返回的消息】

1024)

    ③ 关闭套接字

      sock.close()