zoukankan      html  css  js  c++  java
  • 第六章

    1.简单的套接字通信

    服务端
     1 '''
     2 服务端 接电话
     3 客户端 打电话
     4 1.先启动服务端
     5 2.服务端有两种套接字
     6     1.phone 用来干接收链接的
     7     2.conn 用来干收发消息的
     8 
     9 '''
    10 import socket
    11 # 1.买手机
    12 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  # 基于网络通信的 基于tcp通信的套接字
    13 # print(phone)
    14 # <socket.socket fd=416, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0>
    15 
    16 # 2.绑定手机卡(IP地址) 运行这个软件的电脑IP地址  ip和端口都应该写到配置文件中
    17 phone.bind(('127.0.0.1',8080)) # 端口0-65535   0-1024 给操纵系统
    18 
    19 # 3.开机
    20 phone.listen(5) # 5 代表最大挂起的链接数
    21 
    22 # 4.等电话链接
    23 print('starting...')
    24 # res = phone.accept()  #底层 就是 tcp 三次握手
    25 # print(res)
    26 # (<socket.socket fd=476, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8080), raddr=('127.0.0.1', 58886)>, ('127.0.0.1', 58886))
    27 conn,client_addr = phone.accept()  # conn 电话线  拿到可以收发消息的管道  conn对象
    28 
    29 # 5.收发消息
    30 data = conn.recv(1024)  # 1024个字节 1.单位:bytes 2.1024代表最大接收1024个bytes
    31 print(data)
    32 
    33 conn.send(data.upper())
    34 
    35 # 6.挂电话
    36 conn.close()
    37 
    38 # 7.关机
    39 phone.close()

    客户端
     1 '''
     2 服务端 接电话
     3 客户端 打电话
     4 1.客户端有一种套接字:
     5     phone 用来建连接请求 并用来收发消息
     6 '''
     7 import socket
     8 # 1.买手机  客户端的phone 相当于服务端的 conn
     9 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  # 基于网络通信的 基于tcp通信的套接字
    10 # print(phone)
    11 
    12 # 2.拨号 (服务端的ip 和服务端的 端口)
    13 phone.connect(('127.0.0.1',8080))   #phone 拿到可以发收消息的管道  phone 对象
    14 
    15 # 3.发收消息  bytes型
    16 phone.send('hello'.encode('utf-8'))
    17 data = phone.recv(1024)
    18 print(data)
    19 
    20 # 4.关闭
    21 phone.close()

    2.加上通信循环
    服务端
     1 import socket
     2 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
     3 phone.bind(('127.0.0.1',8080))
     4 phone.listen(5)
     5 print('strating...')
     6 conn,client_addr = phone.accept()
     7 print(client_addr)
     8 while True: # 通信循环
     9     data = conn.recv(1024)
    10     print('客户端数据:',data)
    11     conn.send(data.upper())
    12 
    13 conn.close()
    14 phone.close()

    客户端
     1 import socket
     2 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
     3 phone.connect(('127.0.0.1',8080))
     4 while True: # 通信循环
     5     msg = input('msg>>>:').strip()
     6     phone.send(msg.encode('utf-8'))
     7     data = phone.recv(1024)
     8     print(data)
     9 
    10 phone.close()
    3.bug修复
    端口已存在 重用一下:
    http://www.cnblogs.com/linhaifeng/articles/6129246.html
    phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    还有一种 linux 操作系统 修改内核参数 让os 尽可能快的回收端口
    有时os回收端口慢

    客户端断开: linux 解决办法:if not data:break
    wwindows 解决办法:try...except
    问题:


    这个是由于你的服务端仍然存在四次挥手的time_wait状态在占用地址

    windows解决办法:
    #加入一条socket配置,重用ip和端口
    phone=socket(AF_INET,SOCK_STREAM)
    phone.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
    phone.bind(('127.0.0.1',8080))

    linux 解决办法:
    发现系统存在大量TIME_WAIT状态的连接,通过调整linux内核参数解决,
    vi /etc/sysctl.conf

    编辑文件,加入以下内容:
    net.ipv4.tcp_syncookies = 1
    net.ipv4.tcp_tw_reuse = 1
    net.ipv4.tcp_tw_recycle = 1
    net.ipv4.tcp_fin_timeout = 30

    然后执行 /sbin/sysctl -p 让参数生效。

    net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;

    net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;

    net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。

    net.ipv4.tcp_fin_timeout 修改系統默认的 TIMEOUT 时间

    服务端 
     1 import socket
     2 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
     3 phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
     4 phone.bind(('127.0.0.1',8080))  #如果端口已被占用 就换一个
     5 phone.listen(5)
     6 print('strating...')
     7 conn,client_addr = phone.accept() # conn 三次握手的成果 双向链接
     8 print(client_addr)
     9 while True: # 通信循环
    10     try:  # try...except 出异常适合windows 出异常这里指客户端断开
    11         data = conn.recv(1024)  # 如何客户端 断开了 linux 就会死循环
    12         # if not data:break       # 出异常才会有  # 这里适合linux  出异常指客户端断开
    13         print('客户端数据:',data)
    14         conn.send(data.upper())
    15     except ConnectionResetError:  # 适用windows os
    16         break
    17 
    18 conn.close()
    19 phone.close()

    客户端
    send  可以发 空  # 发给了os的内存 在调用网卡 发送数据
    recv 不可以 收空 # 到了os的内存 在传给了应用程序内存
    所以 客户端 就卡住了 if not msg:continue 卡住原因 os 不会发''数据
     1 import socket
     2 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
     3 
     4 phone.connect(('127.0.0.1',8080))
     5 while True: # 通信循环
     6     msg = input('msg>>>:').strip() # ''
     7     if not msg:continue
     8     #  这个调用了硬件 应用程序里的内存传给了os的内存,由os 调用网卡传数据
     9     phone.send(msg.encode('utf-8'))  # b''
    10     # print('has send')  # 打印了 证明可以 发 空 ''
    11     # 和os要数据,你帮我调用网卡 收数据
    12     data = phone.recv(1024)
    13     # print('has recv')
    14     # print(data)
    15     print(data.decode('utf-8')) #解码
    16 
    17 phone.close()

    4.加上链接循环

    服务端
     1 '''
     2 服务端:不断的接收客户端的 连接
     3 服务端accept 这里不是并发 的效果 但可以一个一个接收客户端的连接
     4 phone.listen(5) 监听5个
     5 '''
     6 import socket
     7 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
     8 phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
     9 phone.bind(('127.0.0.1',8080))
    10 phone.listen(0)
    11 print('strating...')
    12 while True: #连接循环 没有并发 但可一个一个 接收客户端  干通信活的同时不能干连接
    13     conn,client_addr = phone.accept()  # 现在没并发 只能一个一个
    14     print(client_addr)
    15 
    16     while True:
    17         try:
    18             data = conn.recv(1024)
    19             if not data:break
    20             print('客户端数据:',data)
    21             conn.send(data.upper())
    22         except ConnectionResetError:
    23             break
    24     conn.close()
    25 
    26 phone.close()

    客户端1
     1 import socket
     2 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
     3 phone.connect(('127.0.0.1',8080))
     4 while True:
     5     msg = input('msg>>>:').strip() # ''
     6     if not msg:continue
     7     phone.send(msg.encode('utf-8'))  # b''
     8     data = phone.recv(1024)
     9     print(data.decode('utf-8')) #解码
    10 
    11 phone.close()

    客户端2
     1 import socket
     2 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
     3 phone.connect(('127.0.0.1',8080))
     4 while True:
     5     msg = input('msg>>>:').strip() # ''
     6     if not msg:continue
     7     phone.send(msg.encode('utf-8'))  # b''
     8     data = phone.recv(1024)
     9     print(data.decode('utf-8')) #解码
    10 
    11 phone.close()

    5.模拟ssh远程执行命令
    什么叫命令?
    windows:
    dir:查看某一个文件夹下的子文件名与子文件夹名
    ipconfig:查看本地网卡的ip信息
    tasklist:查看运行的进程
    Linux:
    ls
    ifconfig
    ps aux

    如何执行系统命令: 并拿到执行结果
    import os
    os.system # 只能拿到 运行结果 0 执行成功 非0 失败
    一般用:
    import subprocess
    subprocess.Popen('dir d:',shell=True) # shell 启了一个cmd
    把命令结果丢到管道里面:
    subprocess.Popen('dir d:',shell=True,
    stdout=subprocess.PIPE)
     1 # import os
     2 # res = os.system('dir d:')
     3 # print(os.system('dir d:'))
     4 # # print(res)
     5 
     6 import subprocess
     7 obj=subprocess.Popen('dir d:ss',shell=True,
     8                  stdout=subprocess.PIPE,  # 正确的结果
     9                  stderr=subprocess.PIPE)  # 错误的结果
    10 print(obj)  # 执行的结果 是bytes
    11 print('stdout 1--:',obj.stdout.read().decode('gbk'))  # linux 是 utf-8  windows 是 gbk
    12 print('stdout 2--:',obj.stdout.read().decode('gbk'))  # 因为管道没有了
    13 print('stdout 3--:',obj.stderr.read().decode('gbk'))  # 错误管道里有 原因 拿不到数据

    服务端
     1 import subprocess
     2 import socket
     3 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
     4 # phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # 重用ip和端口 任然存在4次挥手的状态 解决办法
     5 phone.bind(('127.0.0.1',8080))
     6 phone.listen(5)
     7 print('strating...')
     8 while True:
     9     conn,client_addr = phone.accept()
    10     print(client_addr)
    11 
    12     while True:
    13         try:
    14             # 1.收命令
    15             cmd = conn.recv(1024)
    16             if not cmd:break
    17             print('客户端数据:',cmd)
    18 
    19             # 2.执行命令,拿到结果
    20             obj = subprocess.Popen(cmd.decode('utf-8'), shell=True, # 客户端用 utf-8发的
    21                                    stdout=subprocess.PIPE,
    22                                    stderr=subprocess.PIPE)
    23             stdout = obj.stdout.read()
    24             stderr = obj.stderr.read()
    25 
    26             # 3.把命令的结果返回给客户端
    27             print(len(stdout)+len(stderr))
    28             conn.send(stdout+stderr) # 有效率问题的 这里 之后 可以优化
    29         except ConnectionResetError:
    30             break
    31     conn.close()
    32 
    33 phone.close()

    客户端
     1 import socket
     2 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
     3 phone.connect(('127.0.0.1',8080))
     4 while True:
     5     # 1.发命令
     6     cmd = input('msg>>>:').strip()  # dir ls
     7     if not cmd:continue
     8     phone.send(cmd.encode('utf-8'))
     9 
    10     # 2.拿到命令的结果,并打印
    11     data = phone.recv(1024)   # 这里是个坑 有可能会大于1024 接收数据量的最大限制
    12     # data = phone.recv(526)   # 这里是个坑 有可能会大于1024 接收数据量的最大限制
    13 
    14     print(data.decode('gbk'))   # linux:utf-8  windows:gbk
    15 
    16 phone.close()
  • 相关阅读:
    利用 img 和 script 发送跨域请求
    tomcat 内存配置
    servlet request.getParamter 有时获取参数为null
    windows本地无法启动sqlserver服务
    mac用virtualbox 装win7联网及分辨率设置
    奇怪的transform bug
    mysql 同时执行多条update语句
    二进制树形算法
    协议栈中使用crc校验函数
    引用布局
  • 原文地址:https://www.cnblogs.com/mumupa0824/p/9015701.html
Copyright © 2011-2022 走看看