• socket编程


    一.什么是socket?

      socket是应用层与TCP/IP协议族通信的中间软件抽象层,她是一组接口.在设计模式中,socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,为用户提供一组简单的接口.

    二.套接字(socket)分类?

    基于文件类型的套接字家族
    AF_UNLX
    unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进行运行在同一机器,可以通过访问同一文件系统间接完成通信

    基于网络类型的套接字家族
    AF_INET
    AF_INET是运用最广泛的一个,大部分时候我们只关心网络编程,所以大部分时候我们只使用AF_INET

    三.套接字(socket)工作流程?

      先从服务端说起,服务端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接.这个时候客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务端的连接就建立了.客户端发送数据,服务端接受请求并处理数据,然后回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互完成.

    服务端套接字函数
    s.bind() 绑定(主机,端口号)到套接字
    s.listen() 开始TCP监听
    s.accept() 被动接受TCP客户的连接,(阻塞式)等待连接的到来

    客户端套接字函数
    s.connect() 主动初始化TCP服务器连接
    s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常

    公共用途的套接字函数
    s.recv() 接收TCP数据
    s.send() 发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完)
    s.sendall() 发送完整的TCP数据(本质就是循环调用send,sendall在待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完)
    s.recvfrom() 接收UDP数据
    s.sendto() 发送UDP数据
    s.getpeername() 连接到当前套接字的远端的地址
    s.getsockname() 当前套接字的地址
    s.getsockopt() 返回指定套接字的参数
    s.setsockopt() 设置指定套接字的参数
    s.close() 关闭套接字

    面向锁的套接字方法
    s.setblocking() 设置套接字的阻塞与非阻塞模式
    s.settimeout() 设置阻塞套接字操作的超时时间
    s.gettimeout() 得到阻塞套接字操作的超时时间

    面向文件的套接字的函数
    s.fileno() 套接字的文件描述符
    s.makefile() 创建一个与该套接字相关的文件

    四.基于TCP的套接字

    TCP是基于连接的,不许先启动服务端,然后再启动客户端去连接服务端

    TCP服务端:
    import socket
    server = socket.socket() #买手机

    # 默认得到是一个TCP的socket
    # server = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0)
    # 两行代码的效果是一样的
    # socket的家族 AF_INET
    # socket的类型 SOCK_STREAM 对应的是TCP,SOCK_DGRAM 对应的是UDP

    # 创建基于UDP的socket
    # server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0)

    server.bind(('192.168.12.207',4396)) #插手机卡
    server.listen() #开始待机
    #连接循环,可以不断接受新连接
    while True:
      client,address = server.accept()
      #通讯循环可以不断收发数据
      while True:
        try:
        #如果windows系统 对方强行关闭连接,会抛出异常
        #如果linux系统 不会抛出异常 会死循环收到空数据包
          data = client.recv(1024)
          if not data:
            client.close()
            break
          print('来自客户端的数据:%s'%data.decode('utf-8'))
          client.send(data)
        except ConnectionResetError:
          print('客户端异常关闭连接')
          client.close()
          break

    TCP客户端:
    import socket
    client = socket.socket()
    client.connect(('192.168.12.207',4396))
    while True:
      msg = input('请输入>>:').strip()
      client.send(msg.encode('utf-8'))
      data = client.recv(1024)
      print('收到服务器的数据:%s'%data.decode('utf-8'))

    半连接池

    当服务器在响应了客户端的第一次请求后会进入等待状态,等待客户端发送的恢复信息,这个时候这个连接就称为半连接.
    产生半连接的两种情况:1.客户端无法返回ACK信息 2.服务器来不及处理客户端的连接请求
    有一种攻击叫做syn洪水攻击,就是不断产生半连接,使服务器无法处理请求.
    半连接池其实就是一个容器 系统会自动将半连接放入这个容器中,可以避免半连接过多而造成资源耗光.
    在server.listen()括号里面加一个数字,这个数字就是半连接池的容量,最大为5

    五.基于UDP的套接字

    UDP是无链接的,先启动哪一端都不会报错
    UDP协议采取的方法是与TCP完全不同,其根本不关心对方是否接受数据,甚至不关心对方的地址是否有效,只要将数据报发送到网络,便什么都不管了.
    优点:由于不需要传输确认信息,所以传输效率高于TCP协议
    缺点:传输数据可能不完整
    场景:视频聊天,语音聊天等,不要求数据完整性,但是对传输速度要求高

    UDP服务器:
    import socket
    server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0)
    server.bind(('192.168.12.207',4396))
    while True:
      data,addr = server.recvfrom(1024)
      print('收到来自%s的消息%s'%(addr[0],data.decode('utf-8')))
      server.sendto(data.upper(),addr)

    UDP客户端:
    import socket
    client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0)
    while True:
      data = input('请输入>>:').encode('utf-8')
      client.sendto(data,('192.168.12.207',4396))
      d,addr = client.recvfrom(1024)
      print(d.decode('utf-8'))

  • 相关阅读:
    Tomcat服务器安装、配置、测试
    Java开发环境配置
    文件-第12章-《数据结构题集》习题解析-严蔚敏吴伟民版
    12-1-顺序文件归并-文件-第12章-《数据结构》课本源码-严蔚敏吴伟民版
    外部排序-第11章-《数据结构题集》习题解析-严蔚敏吴伟民版
    11-2-置换-选择排序-外部排序-第11章-《数据结构》课本源码-严蔚敏吴伟民版
    11-1-败者树-外部排序-第11章-《数据结构》课本源码-严蔚敏吴伟民版
    内部排序-第10章-《数据结构题集》习题解析-严蔚敏吴伟民版
    10-12-顺序表地址排序-内部排序-第10章-《数据结构》课本源码-严蔚敏吴伟民版
    10-11-基数排序-内部排序-第10章-《数据结构》课本源码-严蔚敏吴伟民版
  • 原文地址:https://www.cnblogs.com/lizeqian1994/p/10175317.html
Copyright © 2020-2023  润新知