Python的socket模块与交互式指令
socket简介
在编程的过程中,我们需要使用网络编程,这时我们不得不和网络通信的底层基础打交道了.我们必须让自己传输的数据符合网络通信的基本协议,即TCP/IP协议,但是网络通信协议本身很复杂.我们不可能在编程的过程中还自己去对数据进行封包处理,这是便出现了socket帮助我们处理相关的数据传输,在其他语言里也可以使用socket帮我们处理相关问题.
socket本质就是一组接口,是在应用层与TCP/IP协议族通信中间的一个抽象层,庞大复杂的TCP/IP协议族我们便可以不用过多关注,而只需要通过socket提供的接口就可以相互连接.
socke模块中的基本命令
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服务端
import socket
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
##网络编程需要调用AF_INET,而SOCK_STREAM代表数据流,即TCP方式
phone.bind(('192.168.1.101',9000))
##绑定IP地址和端口,必须是元组
phone.listen(5)
##设置监听数量
while True:
conn, addr = phone.accept()
##得到内容对象和地址
while True:
try: ##异常处理特殊情况
feedback = conn.recv(1024)
##得到内容对象传来的值,里面规定字节数量
print(feedback.decode("UTF-8"))
##编译,因为只有被编译的字符才能被传输
msg = input(">>:")
conn.send(msg.encode("UTF-8"))
##发送
except Exception:
break
conn.close() ##关闭连接了的对象
phone.close() ##关闭服务器
TCP客户端
import socket
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.connect_ex(('192.168.1.101',9000)) ##连接对象
while True:
msg = input(">>:")
phone.send(msg.encode("UTF-8")) ##发送消息
feedback = phone.recv(1024) ##返回消息
print(feedback.decode("UTF-8"))
phone.close() ##关闭对象
问题
可能在多次开启关闭服务器的时候,会出现IP地址已经被使用了的情况,我们可以用以下方法解决:
phone = socket(AF_INIT, SOCKET_STREAM)
phone.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
phone.bind(('192.168.1.101',9000))
UDP的服务端和客户端示例
UDP的服务端
from socket import *
ip_addr = ('192.168.1.101',9000)
buff_size = 1024
udp_server = socket(AF_INET, SOCK_DGRAM)
##SOCK_DGRAM表示UDP方式
udp_server.bind(ip_addr)
##绑定IP地址和端口
while True:
data, addr = udp_server.recvfrom(buff_size)
##受信息
print(data.decode("utf-8"))
udp_server.sendto(data.upper(), addr)
##发信息
UDP的客户端
from socket import *
ip_addr = ('192.168.1.101',9000)
buff_size = 1024
udp_client = socket(AF_INET, SOCK_DGRAM)
while True:
msg = input(">>:")
udp_client.sendto(msg.encode("utf-8"), ip_addr)
##不需要绑定,只需要传一个地址
date, addr = udp_client.recvfrom(buff_size)
print(date.decode("utf-8"))
subprogress模块
TCP和UDP比较
TCP | UDP | |
---|---|---|
传输方式 | 数据流(STREAM) | 数据报(DGRAM) |
导致问题 | 粘包 | 丢包 |
接待对象 | 一个 | 多个 |
连接 | 需要连接线 | 不需要连接线 |
TCP是以数据流的方式,在数据很多时,会多次地不分内容关联性地传输给对方内核态缓存,当用户态缓存来取数据时,并不知道数据的开头和结尾,那么就出现了粘包现象.因此粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的,所以通过TCP方式不能发送空.
然而,UDP方式是以信息为单位传输数据,在数据里面包含了开头和结尾的界限,因此不会出现粘包的现象,但是当传输来的数据被储存在内核态缓存里面时,如果应用态缓存没有一次性的取完数据,那么数据就会被丢弃
解决了粘包现象的远程指令程序
客户端
from socket import *
ip_port = ('127.0.0.1', 9000)
client = socket(AF_INET, SOCK_STREAM)
client.connect_ex(ip_port)
while True:
command = input(">>:")
if not command: continue
client.send(command.encode("utf-8"))
feedback_of_length = int(client.recv(1024).decode("gbk")) #先得到数据的长度
client.send("OK".encode("gbk")) #并且发送可以传输了的命令
all_data = b""
data_length = 0
while data_length < feedback_of_length:
all_data += client.recv(1024) #循环地把数据联结在一起
data_length = len(all_data)
last_date = all_data.decode("gbk") ##最后解码
print(last_date)
client.close()
服务端
from socket import *
import subprocess
ip_port = ('127.0.0.1', 9000)
buff_size = 5
server = socket(AF_INET, SOCK_STREAM)
server.bind(ip_port)
server.listen(buff_size)
while True:
conn, addr = server.accept()
while True:
try:
cmd = conn.recv(1024)
if not cmd: continue
res = subprocess.Popen(cmd.decode("utf-8"), shell=True,
stderr = subprocess.PIPE,
stdin = subprocess.PIPE,
stdout = subprocess.PIPE
)
err = res.stderr.read()
if not res:
get_res = "Run Perfectly"
elif err:
get_res = err
else:
get_res = res.stdout.read()
length_of_res = len(get_res) #发送数据长度
conn.send(str(length_of_res).encode("gbk"))
last_info = conn.recv(1024) #得到是否传输的指令
if last_info.decode("utf-8") == "OK":
conn.send(get_res)
except Exception:
break
socketserver实现并发
TCP版服务端
import socketserver
class MyServer(socketserver.BaseRequestHandler): ##必须要继承这个父类
def handle(self): ##必须要重新定义这个方法
while True:
try:
data = self.request.recv(1024) ##recv就相当于conn了
if not data: break
print(data.decode("utf-8"), self.client_address) ##只有data和client_address这两个量
self.request.sendall(data)
except Exception:
break
if __name__ == "__main__":
s = socketserver.ThreadingTCPServer(('192.168.1.101',9001), MyServer) ##实例化一个对象
s.serve_forever() ##永远运行
UDP版服务端
import socketserver
class MyServer(socketserver.BaseRequestHandle):
def handle(self):
##(b'ad', <socket.socket fd=444, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=0,
## laddr=('192.168.1.101', 8081)>) request是一个元组
print(self.request[0].decode("utf-8"))
self.request[1].sendto(self.request[0], self.client_address)
if __name__ == "__main__":
s = socketserver.ThreadingUDPServer(('192.168.1.101',8080), MyServer)
s.server_forever()
Python的socket模块与交互式指令的更多相关文章
- 老李分享:使用 Python 的 Socket 模块开发 UDP 扫描工具
老李分享:使用 Python 的 Socket 模块开发 UDP 扫描工具 poptest是业内唯一的测试开发工程师培训机构,测试开发工程师主要是为测试服务开发测试工具,在工作中要求你做网络级别的安全 ...
- python中socket模块详解
socket模块简介 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket.socket通常被叫做"套接字",用于描述IP地址和端口,是一个通信 ...
- Python基于socket模块实现UDP通信功能示例
Python基于socket模块实现UDP通信功能示例 本文实例讲述了Python基于socket模块实现UDP通信功能.分享给大家供大家参考,具体如下: 一 代码 1.接收端 import ...
- 【Python】socket模块应用
[Socket] 本文记录了一些socket模块的简单应用,对于具体原理还没来得及深究. ■ 利用socket模块进行端口连接验证和扫描 在linux中常用nc命令来进行远端端口是否开放的验证.但是这 ...
- python基础===socket模块的讲解(转)
一.网络知识的一些介绍 socket 是网络连接端点.例如当你的Web浏览器请求www.jb51.net上的主页时,你的Web浏览器创建一个socket并命令它去连接 www.jb51.net的Web ...
- python之socket模块详解--小白博客
主要是创建一个服务端,在创建服务端的时候,主要步骤如下:创建socket对象socket——>绑定IP地址和端口bind——>监听listen——>得到请求accept——>接 ...
- 使用 Python 的 Socket 模块构建一个 UDP 扫描工具
译文:oschina 英文:bt3gl 当涉及到对一些目标网络的侦察时,出发点无疑是首先发现宿主主机.这个任务还可能包含嗅探和解析网络中数据包的能力. 几周前,我曾经谈到了如何使用Wireshark来 ...
- python之socket模块
UDP client #!/usr/bin/env python2.7 #-*-coding:utf-8 -*- import socket s=socket.socket(socket.AF_INE ...
- python的socket模块
sk.bind(address) s.bind(address) 将套接字绑定到地址.address地址的格式取决于地址族.在AF_INET下,以元组(host,port)的形式表示地址. sk.li ...
随机推荐
- JS实现定时器
导出:jquery.timers-1.2.js jQuery Timers提供了三个函式 1. everyTime(时间间隔, [定时器名称], 函式名称, [次数限制], [等待函式程序完成])2. ...
- 设置Linux环境变量的方法和区别_Ubuntu
设置 Linux 环境变量可以通过 export 实现,也可以通过修改几个文件来实现,有必要弄清楚这两种方法以及这几个文件的区别. 通过文件设置 Linux 环境变量 首先是设置全局环境变量,对所有用 ...
- Caused by: java.io.FileNotFoundException: velocity.log (No such file or directory)
Caused by: org.apache.velocity.exception.VelocityException: Error initializing log: Failed to initia ...
- Node.js作web服务器总结
1.为什么Node.js用JS开发 Node.js 含有一系列内置模块,使得程序可以脱离 Apache HTTP Server 或 IIS,作为独立服务器运行. 首先,我们都清楚的是,同时接收数 ...
- (转)Spring Boot 2 (四):使用 Docker 部署 Spring Boot
http://www.ityouknow.com/springboot/2018/03/19/spring-boot-docker.html Docker 技术发展为微服务落地提供了更加便利的环境,使 ...
- C#事件の.net下的EventArgs和EventHandler
事件参数(EventArgs) .Net框架里边提供的一个委托EventHandler来Handle事件. 一样,搞一个场景(这个场景是书里的):买车.经销商(CarDealer)会上新车(NewCa ...
- Linux 大爆炸:一个内核,无数发行版
即使你是一个 Linux 新人,你可能也已经知道它不是一个单一的.整体的操作系统,而是一群项目.这个星座中不同的“星”组成了“发行版”.每个都提供了自己的 Linux 模式. 感谢这一系列发行版所提供 ...
- 自己动手写处理器之第二阶段(1)——可编程逻辑器件与PLD电路设计流程
将陆续上传本人写的新书<自己动手写处理器>(尚未出版),今天是第五篇,我尽量每周四篇 通过上一章的介绍,读者应该知道CPU内部有一些主要的电路,比方:译码电路.运算电路.控 ...
- Python之requests库
Request库 r = requests.get(url) 这个包括两个语句:Response.Request,我们重点来看一下Response Response包含了页面返回的所有信息,下面是它的 ...
- YOLO 从数据集制作到训练
1.图片数据集收集 共 16种 集装箱船 container ship 散货船 bulker 油船 tanker 游轮 / 客轮 / 邮轮 passenger liner 渔船 fishing boa ...