zoukankan      html  css  js  c++  java
  • 网络编程

    网络编程 
    什么socket?

    TCP(Transmission Control Protocol)可靠的、面向连接的协议(eg:打电话)、传输效率低全双工通信(发送缓存&接收缓存)、面向字节流。
    使用TCP的应用:Web浏览器;电子邮件、文件传输程序。

    UDP(User Datagram Protocol)不可靠的、无连接的服务,传输效率高(发送前时延小),一对一、一对多、多对一、多对多、面向报文,尽最大
    努力服务,无拥塞控制。使用UDP的应用:域名系统 (DNS);视频流;IP语音(VoIP)。
       
    软件
    客户端:CS架构, client -> server
    浏览器:BS架构, browser -> server

    为什么要网络通信发送的是字节?而不是字符串?
    py3, send/recv 都是字节
    py2, send/recv 都是字符串


    服务端:
    accept,阻塞:等待客户端来连接。
    recv, 阻塞:等待客户端发来数据。

    客户端:
    connect,阻塞:一直在连接,直到连接成功才往下运行其他代码。
    recv, 阻塞:等待服务端发来数据。

    服务端:
     1 import socket
     2 
     3 server = socket.socket()
     4 
     5 server.bind(('127.0.0.1',8001))
     6 
     7 server.listen(5)
     8 
     9 while True:
    10     conn,addr = server.accept()
    11     # 字节类型
    12     try:
    13         while True:
    14             data = conn.recv(1024) # 阻塞
    15             if data == b'exit':
    16                 break
    17             response = data + b' SB'
    18             conn.send(response)
    19     except ConnectionResetError:#防止客户端终端后 服务端异常  window环境下使用
    20         break
    21 
    22     conn.close()

    客户端:

     1 import socket
     2 
     3 sk = socket.socket()
     4 
     5 sk.connect(('127.0.0.1',8001))
     6 
     7 while True:
     8     name = input("请输入姓名:")
     9     sk.send(name.encode('utf-8')) # 字节
    10 
    11     if name == 'exit':
    12         break
    13 
    14     response = sk.recv(1024) # 字节
    15     print(response.decode('utf-8'))
    16 
    17 sk.close()

    socket粘包

    socket的粘包为在数据量小与时间间隔短的情况下 优化算法使数据减少IO以达到提高效率,减少网络IO的一种方式

    socket下的send与recv并不是一对一的  可以一对多 多对一即可  

    粘包主要是接收端不知所接收的大小(即不知数据的开头与结尾)  只要明确数据的大小 即可解决粘包导致的缺点 

    一般可以使用struck来达到效果

    send  : 只需要copy data     send不是直接操作网卡的   本质上是数据由用户程序copy到操作系统缓存    操作系统来调用网卡传输     

    recv: 1. wait data   2. copy data  时间较长   

    struct用法

     1 import struct
     2 res=struct.pack("i","")
     3 print(res)
     4 print(len(res))
     5 obj=struct.unpack("i",res)
     6 print(obj[0])import struct
     7 res=struct.pack("i","")
     8 print(res)
     9 print(len(res))
    10 obj=struct.unpack("i",res)
    11 print(obj[0])
    struct

    subprocess用法

    import subprocess
    
    res=subprocess.Popen("dir",
                         shell=True,
                         stderr=subprocess.PIPE,
                         stdout=subprocess.PIPE)
    print(res.stdout.read().decode("gbk"))
    subprocess

    SSH Server

     1 import socket
     2 import subprocess
     3 
     4 server = socket.socket()
     5 
     6 server.bind(('127.0.0.1',8008))
     7 
     8 server.listen(5)
     9 
    10 while True:
    11     print("server is working.....")
    12     conn,addr = server.accept()
    13     # 字节类型
    14     while True:
    15         # 针对window系统
    16 
    17         try:
    18             cmd = conn.recv(1024).decode("utf8") # 阻塞
    19             if cmd.encode("utf-8") == b'exit':
    20                 break
    21             res=subprocess.Popen(cmd,
    22                              shell=True,
    23                              stderr=subprocess.PIPE,
    24                              stdout=subprocess.PIPE,
    25                              )
    26             # print("stdout",res.stdout.read())
    27             # print("stderr",res.stderr.read().decode("gbk"))
    28             out=res.stdout.read()
    29             err=res.stderr.read()
    30 
    31             print("out响应长度",len(out))
    32             print("err响应长度",len(err))
    33             if err:
    34                  import struct
    35                  header_pack = struct.pack("i", len(err))
    36                  conn.send(header_pack)
    37                  conn.send(err)
    38             else:
    39                  #构建报头
    40                  import struct
    41                  header_pack=struct.pack("i",len(out))
    42                  print("header_pack",header_pack)
    43                  # # 发送报头
    44                  conn.send(header_pack)
    45                  # 发送数据
    46                  conn.send(out)
    47 
    48         except Exception as e:
    49             break
    50 
    51 
    52     conn.close()
    View Code

    SSH Client

     1 import socket
     2 import struct
     3 sk = socket.socket()
     4 
     5 sk.connect(('127.0.0.1',8008))
     6 
     7 while 1:
     8     cmd = input("请输入命令:")
     9     sk.send(cmd.encode('utf-8')) # 字节
    10     if cmd=="":
    11         continue
    12     if cmd == 'exit':
    13         break
    14 
    15     header_pack=sk.recv(4)
    16     data_length=struct.unpack("i",header_pack)[0]
    17     print("data_length",data_length)
    18     '''
    19     b'xxx/xxx/xxx/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'
    20 
    21 
    22     '''
    23 
    24     recv_data_length=0
    25     recv_data=b""
    26 
    27     while recv_data_length<data_length:
    28         data=sk.recv(1024)
    29         recv_data_length+=len(data)
    30         recv_data+=data
    31 
    32     print(recv_data.decode("gbk"))
    33 
    34 
    35 sk.close()
    View Code

    socketserver可以实现并发的网络通信

    server

     1 import socketserver
     2 
     3 class Myserver(socketserver.BaseRequestHandler):
     4     def handle(self):# handel之内的逻辑由程序员编写,request等同于socket对象conn
     5         # 字节类型
     6         while 1:
     7             # 针对window系统
     8             try:
     9                 print("等待信息")
    10                 data = self.request.recv(1024)  # 阻塞
    11                 # 针对linux
    12                 if len(data) == 0:
    13                     break
    14                 if data == b'exit':
    15                     break
    16                 response = data + b'SB'
    17                 self.request.send(response)
    18             except Exception as e:
    19                 break
    20 
    21         self.request.close()
    22 
    23 
    24 # 1 创建socket对象 2 self.socket.bind()  3 self.socket.listen(5)
    25 # server=socketserver.ForkingUDPServer(("127.0.0.1",8899),Myserver)
    26 server=socketserver.ThreadingTCPServer(("127.0.0.1",8899),Myserver) # socket建立,bind,listen方法
    27 
    28 server.serve_forever()#类似于accept方法

     client

     1 import socket
     2 
     3 sk = socket.socket()
     4 
     5 sk.connect(('127.0.0.1',8899))
     6 
     7 while 1:
     8     name = input(">>>>:")
     9     sk.send(name.encode('utf-8')) # 字节
    10 
    11     response = sk.recv(1024) # 字节
    12     print(response.decode('utf-8'))
  • 相关阅读:
    [BZOJ1492][NOI2007]货币兑换Cash(斜率优化+CDQ分治)
    [P1768]天路(分数规划+SPFA判负环)
    [BZOJ5109][LOJ #6252][P4061][CodePlus 2017 11月赛]大吉大利,今晚吃鸡!(最短路+拓扑排序+传递闭包+map+bitset(hash+压位))
    [BZOJ1040][ZJOI2008]骑士(环套树dp)
    [P3759][TJOI2017]不勤劳的图书管理员(分块+树状数组)
    [CF665F]Four Divisors
    [LOJ6235]区间素数个数
    [SDOI2015]约数个数和
    [BZOJ3944]Sum
    [BZOJ2671]Calc
  • 原文地址:https://www.cnblogs.com/kxuan/p/14083912.html
Copyright © 2011-2022 走看看