網絡模塊socket

網絡模塊socket

實現本地收發

  • 簡單的尷聊,實現服務器和客戶端的文字傳輸
    ###TCP協議狀況算法

    #server.py
      import socket   #導入socket模塊
      from socket import SOL_SOCKET, SO_REUSEADDR #記住這個模塊
    
      sk = socket.socket()    #實例化socket對象
      sk.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)  #這行代碼是爲了實現端口繼續利用的
      sk.bind(('127.0.0.1', 8080))    #爲sk對象綁定一個ip和一個端口
      sk.listen() #啓動監聽
      conn, addr = sk.accept()    #等待一個客戶端的鏈接
      while 1:
          ret = conn.recv(1024).decode('utf-8')   #等待客戶端發送消息
    
          if ret == 'bye':
              break
          print(ret)
          info = input('反饋: ')
          conn.send(bytes(info, encoding='utf-8'))    #向客戶端發動消息
    
      conn.close()
      sk.close()
      ___________________________________________________
      ___________________________________________________
      #client
      import socket
    
      sk = socket.socket()
      sk.connect(('127.0.0.1', 8080))
      while 1:
          info = input('輸入: ')
          sk.send(bytes(info, encoding='utf-8'))
          if info == 'bye':
              break
    
          ret = sk.recv(1024).decode('utf-8')
          print(ret)
    
      sk.close()

    ###改進版,爲聊天消息加入時間shell

    #server
      import socket
      from socket import SOL_SOCKET, SO_REUSEADDR
      from time import ctime, time
    
      sk = socket.socket()
      sk.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
      sk.bind(('127.0.0.1', 8080))
      sk.listen()
      conn, addr = sk.accept()
      while 1:
          t = ctime(float(conn.recv(1024).decode('utf-8')))
          ret = conn.recv(1024).decode('utf-8')
    
          if ret == 'bye':
              break
          print('{}收到{}'.format(t, ret))
          info = input('反饋: ')
          conn.send(bytes(info, encoding='utf-8'))
          conn.send(bytes(str(time()), encoding='utf-8'))
    
      conn.close()
      sk.close()
      ----------------------------------------------
      ----------------------------------------------
      #client
      import socket
      from time import time, ctime
    
      sk = socket.socket()
    
      sk.connect(('127.0.0.1', 8080))
      while 1:
          info = input('輸入: ')
          sk.send(bytes(str(time()), encoding='utf-8'))
          sk.send(bytes(info, encoding='utf-8'))
          if info == 'bye':
              break
    
          ret = sk.recv(1024).decode('utf-8')
          t = ctime(float(sk.recv(1024).decode('utf-8')))
          print(t, ret)
    
      sk.close()
    • TCP協議下只能容許一個客戶端連接,多個客戶端鏈接須要排隊,等待第一個鏈接斷開才能接入鏈接

    ###__UDP協議__狀況服務器

    #server
      #建立一個UDP協議的服務器
      import socket
    
      sk = socket.socket(type=socket.SOCK_DGRAM)    #實例化一個socket對象
      sk.bind(('127.0.0.1', 8081))    #給服務器綁定一個ip和端口
    
      conn, addr = sk.recvfrom(1024)  #接受消息,接收到消息內容和對方機器地址
      print(conn.decode('utf-8'), addr)
    
      sk.sendto(b'bye', addr)
    
      sk.close()
      --------------------------------
      --------------------------------
      #client
      #建立一個UDP客戶端
      import socket
    
      sk = socket.socket(type=socket.SOCK_DGRAM)    #建立socket對象
    
      ip_port = ('127.0.0.1', 8081)
      sk.sendto(b'hello', ip_port)
    
      conn, addr = sk.recvfrom(1024)
      print(conn.decode('utf-8'), addr)
    
      sk.close()

黏包現象

  • 出如今TCP協議中,若是一個包在一次發送中沒有徹底接收將會在下一次接收時繼續接收
  • 能夠理解成管道擁堵,再次接收會獲取管道中的信息
  • 在UDP協議中沒有黏包現象,沒有接收完畢的包將直接丟棄
  • 黏包涉及到TCP協議自帶的拆包機制,一種優化文件傳輸的機制網絡

    ###黏包出現的兩種狀況
    1. 數據包太長,服務器接收參數小於數據包的長度
    2. 兩個數據包的發送時間太近,神奇的某算法將其整合成一個數據包發送
    ###解決黏包的方案
    • 每次發送信息以前,先向服務器反饋信息的長度,告知服務器即將接收數據的長度socket

      #server
        import socket
        from socket import SOL_SOCKET, SO_REUSEADDR
      
        sk = socket.socket()
        sk.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        sk.bind(('127.0.0.1', 8080))
        sk.listen()
        conn, addr = sk.accept()
        #服務器發送命令
        cmd = input('輸入須要發送的命令: ')
        conn.send(bytes(cmd, encoding='utf-8'))
        print('命令已經發送!')
      
        #接收命令反饋信息的長度
        num = int(conn.recv(10).decode('utf-8'))
        print('接收到長度,長度是{}'.format(num))
      
        #反饋給客戶端已經收到長度信息
        conn.send(b'Roger that')
      
        #接收命令反饋信息
        msg = conn.recv(num).decode('utf-8')
        print('接收到信息')
        #打印命令返回信息
        print(msg)
        #反饋信息給客戶端
        conn.send(bytes('服務器說:接收完畢', encoding='utf-8'))
        #關閉服務
        conn.close()
        sk.close()
      
        -----------------------------
        -----------------------------
        #client
        import socket
        import subprocess
        import time
      
        sk = socket.socket()
        sk.connect(('127.0.0.1', 8080))
        #接收服務器命令
        cmd = sk.recv(1024).decode('utf-8')
        print(cmd)
        #將命令傳給控制檯
        ret = subprocess.Popen(cmd, shell=True,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE)
        print('控制檯已經接收到命令')
        #將控制檯傳回的信息長度反饋給服務器
        std_out = ret.stdout.read()
        std_err = ret.stderr.read()
        num = len(std_out) + len(std_err)
        sk.send(bytes(str(num), encoding='utf-8'))
        print('控制檯輸出信息的長度已經反饋')
      
        #詢問服務器收到長度了不
        has_len = sk.recv(1024)
        print(has_len.decode('utf-8'))
      
      
        #將控制檯傳回的信息內容反饋給服務器
        sk.send(std_out)
        sk.send(std_err)
        print('控制檯輸出的信息內容已經反饋')
      
        #接收服務器反饋的信息
        info = sk.recv(1024).decode('utf-8')
        print(info)
      
        #關閉客戶端
        sk.close()
相關文章
相關標籤/搜索