上节地址:Python网络编程:socket

一、send和sendall区别

send,sendall
        ret = send('safagsgdsegsdgew') #send 发送完成后会有一个返回值,告知发送了多少,并不一定会把数据全部发送过去。
        sendall:内部调用send,将数据全部发送完为止。
        因此我们使用时最好使用sendall

二、粘包

粘包问题需要理解recv()的使用,我们定义接收值的时候会写recv(1024)表示一次接收1024字节,但是有时候接收的数据大于1024字节,这样socket默认变不发送了,等待下次接收其他命令时在将上次没有发送完的数据继续发送过去,这样就形成了粘包问题。对于粘包,可以在正式收发数据之前先判断下数据的大小,然后分片发送。下面是利用socket和subprocess实现的类似cmd的程序,在cmd执行一些命令时,如ipconfig,会因为输出内容过长而造成粘包问题。下面的例子是解决粘包之后的。观察粘包现象的版本就不在提供了。
#!/usr/bin/env python
# _*_ coding:utf_8 _*_
import socket
ip_port=('127.0.0.1',9002)
s = socket.socket()
s.connect(ip_port)
while True:
send_data = input('>>: ').strip()
if len(send_data) == 0:continue
if send_data == 'exit':break
s.send(bytes(send_data,encoding='utf-8'))
#解决粘包问题
ready_tag = s.recv(1024) #收取待发送字节的长度
ready_tag=str(ready_tag,encoding='utf8')
if ready_tag.startswith('Ready'): #数据包格式为Ready|9124
msg_size=int(ready_tag.split('|')[-1])
start_tag = 'Start'
s.sendall(bytes(start_tag,encoding='utf8')) #发送消息,表示开始传输
recv_size = 0
#print(msg_size)
recv_msg = b''
while recv_size < msg_size:
recv_data = s.recv(1024)
recv_msg+=recv_data
recv_size+=len(recv_data)
print(str(recv_msg,encoding='utf8'))
#收消息
# recv_data=s.recv(1024)
# print(str(recv_data,encoding='utf-8')) s.close()

socket_client

#!/use/bin/env python
#_*_ coding:utf_8 _*_
import socket
import subprocess
ip_addr=('127.0.0.1',9002)
s=socket.socket() #创建对象
s.bind(ip_addr) #绑定连接地址
s.listen(5) #设置监听主机数
while True:
conn,addr=s.accept()
i = 0
while True:
print(i)
try:
recv_data = conn.recv(1024)
print('------0')
#print(str(recv_data,encoding='utf-8'))
if len(recv_data) == 0:break
#执行系统命令
p=subprocess.Popen(str(recv_data,encoding='utf-8'),shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)#执行系统命令,windows平台命令的标准输出是gbk编码,需要转换
res = p.stdout.read() #获取标准输出
if len(res) == 0: #执行错误命令,send_data为空
send_data = str(p.stderr.read(),encoding='utf-8')
else:
send_data=str(res,encoding='gbk')
send_data=bytes(send_data,encoding='utf-8') #要发送的数据 #判断粘包
ready_tag='Ready|%s' %len(send_data)
conn.send(bytes(ready_tag,encoding='utf8')) #发送数据长度
feedback=conn.recv(1024) #接收确认信息
feedback=str(feedback,encoding='utf8')
if feedback.startswith('Start'):
print(send_data)
conn.sendall(send_data) #发送命令的执行结果
#conn.sendall(send_data)
print('succeed')
i+=1 except Exception:
break
conn.close()

socket cmd

最新文章

  1. 切分 Tomcat 的 catalina.out 文件,解决日志文件过大的问题
  2. Struts2之文件上传下载
  3. 用jinja做了个E-Letter小项目
  4. docker 报错Failed to start Docker Storage Setup. 的处理基本都是容器满了
  5. Uploadify v3.2.1 属性、事件、方法说明
  6. 【转载】C++ 值传递、指针传递、引用传递详解
  7. WOW: 宏
  8. Android Java汉字转拼音总结
  9. Linux Tweak:交换 Caps_Lock 与 Control_R
  10. 关于iOS自定义控件:在view上实现事件和代理
  11. grunt之connect、watch
  12. Map 基础用法
  13. HDU 1219 AC Me
  14. Java思维导图之Class对象
  15. APP的线程安全
  16. Windows下MySQL重装引起问题的解决
  17. CI持续集成系列之(九)代码发布脚本模板书写
  18. ASP.NET MVC5 及 EF6 学习笔记 - (目录整理)
  19. ubuntu_thunder
  20. vmstat详解

热门文章

  1. HDU - 6621 K-th Closest Distance 主席树+二分答案
  2. unicode字符集范围
  3. 树结构遍历节点名字提取,这里提取的是el-tree数据结构,封装成函数
  4. LOJ 2555 「CTSC2018」混合果汁——主席树
  5. Bugku | 入门逆向
  6. window 2008/2012计划任务配置
  7. CLLocationManager在多线程下使用
  8. vue绑定属性、绑定class及绑定style
  9. setTimeout,clearTimeout,setInterval,clearInteral详解
  10. no sucn file or directory,scandir.......node-sass