【python】-- Socket
socket
socket本质上就是在2台网络互通的电脑之间,架设一个通道,两台电脑通过这个通道来实现数据的互相传递。 我们知道网络 通信 都 是基于 ip+port 方能定位到目标的具体机器上的具体服务,操作系统有0-65535个端口,每个端口都可以独立对外提供服务,如果 把一个公司比做一台电脑 ,那公司的总机号码就相当于ip地址, 每个员工的分机号就相当于端口, 你想找公司某个人,必须 先打电话到总机,然后再转分机 。
一、socket简述
socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求。
socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,对于文件用【打开】【读写】【关闭】模式来操作。socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)
socket和file的区别:
- file模块是针对某个指定文件进行【打开】【读写】【关闭】
- socket模块是针对 服务器端 和 客户端Socket 进行【打开】【读写】【关闭】
1、客户端小实例:
- import socket #导入socket模块
- client = socket.socket() #创建socket实例
- client.connect(("localhost",6969)) #建立连接
- send_data = "hello word!" #发送的字符串
- send_data = send_data.encode() #因为发送是bytes类型,所以这边先转码成bytes类型
- client.send(send_data) #发送数据
- data = client.recv(1024) #接收服务端的数据,这边设置接收1024字节 1kb=1024字节
- print("server rece:",data.decode())
- client.close() #关闭与服务端的链接
2、服务端小实例:
- import socket
- sever = socket.socket() #创建服务端实例
- sever.bind(("localhost",6969)) #绑定客户端ip和端口
- sever.listen() #监听端口
- print("server waiting connect.........")
- conn,addr = sever.accept() #接收客户端,并且返回连接标志位(conn)实例,和对方的ip地址(addr)
- data = conn.recv(1024) #接收客户端发过来的数据,接收的也是bytes类型的数据
- print("成功建立链接")
- print("client data:",data.decode())
- conn.send(data.upper()) #将刚刚接收到数据,发送至服务端,注意这边发送的也是字节类型,是bytes类型
- sever.close() #关闭服务端
3、socket.socket(socket.AF_INET,socket.SOCK_STREAM,0)参数详解:
参数一:地址簇
socket.AF_INET IPv4(默认)
socket.AF_INET6 IPv6
socket.AF_UNIX 只能够用于单一的Unix系统进程间通信
参数二:类型
socket.SOCK_STREAM 流式socket , for TCP (默认)
socket.SOCK_DGRAM 数据报式socket , for UDP
socket.SOCK_RAW 原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。
socket.SOCK_RDM 是一种可靠的UDP形式,即保证交付数据报但不保证顺序。SOCK_RAM用来提供对原始协议的低级访问,在需要执行某些特殊操作时使用,如发送ICMP报文。SOCK_RAM通常仅限于高级用户或管理员运行的程序使用。
socket.SOCK_SEQPACKET 可靠的连续数据包服务
参数三:协议
0 (默认)与特定的地址家族相关的协议,如果是 0 ,则系统就会根据地址格式和套接类别,自动选择一个合适的协议
Demo:
- import socket
- ip_port = ('127.0.0.1',9999)
- sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0)
- sk.bind(ip_port)
- while True:
- data = sk.recv(1024)
- print data
- import socket
- ip_port = ('127.0.0.1',9999)
- sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0)
- while True:
- inp = raw_input('数据:').strip()
- if inp == 'exit':
- break
- sk.sendto(inp,ip_port)
- sk.close()
二、Socket方法、简单ssh实例
1、socket方法:
函数 | 描述 |
---|---|
服务器端套接字 | |
s.bind() | 绑定地址(host,port)到套接字, 在AF_INET下,以元组(host,port)的形式表示地址。 |
s.listen() | 开始TCP监听。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。 |
s.accept() | 被动接受TCP客户端连接,(阻塞式)等待连接的到来 |
客户端套接字 | |
s.connect() | 主动初始化TCP服务器连接,。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。 |
s.connect_ex() | connect()函数的扩展版本,出错时返回出错码,而不是抛出异常 |
公共用途的套接字函数 | |
s.recv() | 接收TCP数据,数据以字符串形式返回,bufsize指定要接收的最大数据量。flag提供有关消息的其他信息,通常可以忽略。 |
s.send() | 发送TCP数据,将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。 |
s.sendall() | 完整发送TCP数据,完整发送TCP数据。将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。 |
s.recvform() | 接收UDP数据,与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。 |
s.sendto() | 发送UDP数据,将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。 |
s.close() | 关闭套接字 |
s.getpeername() | 返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。 |
s.getsockname() | 返回套接字自己的地址。通常是一个元组(ipaddr,port) |
s.setsockopt(level,optname,value) | 设置给定套接字选项的值。 |
s.getsockopt(level,optname[.buflen]) | 返回套接字选项的值。 |
s.settimeout(timeout) | 设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如connect()) |
s.gettimeout() | 返回当前超时期的值,单位是秒,如果没有设置超时期,则返回None。 |
s.fileno() | 返回套接字的文件描述符。 |
s.setblocking(flag) | 如果flag为0,则将套接字设为非阻塞模式,否则将套接字设为阻塞模式(默认值)。非阻塞模式下,如果调用recv()没有发现任何数据,或send()调用无法立即发送数据,那么将引起socket.error异常。 |
s.makefile() | 创建一个与该套接字相关连的文件 |
2、简单ssh实例:
客户端:
客户端实例->建立连接->发送数据->接收数据
- import socket
- client = socket.socket()
- client.connect(("localhost",9999))
- while True:
- cmd = input(">>>:").strip()
- if len(cmd) == 0:continue
- client.send(cmd.encode("utf-8"))
- cmd_res = client.recv(500)
- print(cmd_res.decode("utf-8",'ignore'))
- client.close()
服务端:
服务端实例->绑定ip+端口->监听客户端连接->生成连接实例->接收客户端数据->发送数据至客户端
- import socket,os
- server = socket.socket()
- server.bind(("localhost",9999))
- server.listen()
- while True:
- conn,addr = server.accept()
- print("new addr:",addr)
- while True:
- data = conn.recv(1024)
- if not data:
- print("客户端已断开")
- break
- print("执行指令:",data)
- cmd_res = os.popen(data.decode()).read()
- print("before send:",len(cmd_res))
- if len(cmd_res) == 0:
- cmd_res = "cmd has no output...."
- conn.send(cmd_res.encode("utf-8"))
- print("send done")
- server.close()
效果图:
Pycharm 执行命令:ipconfig
cmd执行命令:ipconfig
通过效果图对比发现Pycharm执行的ipconfig信息显示不完成,原因就是我们在客户端的代码 cmd_res = client.recv(500) 设置接受的字节最大就是500,服务端的发送给客户端的信息大于500 字节,多出的字节就会被存放在IO缓冲区,等待下一次发送。
流程图
ssh 实例小结:
1、服务端第一次全部发送给客户端,客户端只接收设置部分的字节数,剩下的字节数被存储在 IO缓冲区 中,下一次再用send的时候,它会先把缓冲区里的旧数据先发出去,等达到客户端接收的最大值后,然后再把新数据再放到缓冲区中,直到缓冲区满了再发出去
2、客户端虽然写的接收的是500,但它不一定能收到500,recv(500)代表着最多一次只能收500,如果服务端send10个字节,客户端也会正常接收,而不是等着500全收满了
3、两种情况缓冲区会发数据:
- 缓冲区满了会发
- 缓冲区超时:就是手动send
【python】-- Socket的更多相关文章
- 【Python】socket模块应用
[Socket] 本文记录了一些socket模块的简单应用,对于具体原理还没来得及深究. ■ 利用socket模块进行端口连接验证和扫描 在linux中常用nc命令来进行远端端口是否开放的验证.但是这 ...
- 【python】-- Socket接收大数据
Socket接收大数据 上一篇博客中的简单ssh实例,就是说当服务器发送至客户端的数据,大于客户端设置的数据,则就会把数据服务端发过来的数据剩余数据存在IO缓冲区中,这样就会造成我们想要获取数据的完整 ...
- 【Python】socket编程-3
. SocketServer最简单的使用方法: () 创建一个Handler类,继承自BaseRequestHandler,重写其handle(),在该方法中完成对请求的处理. () 实例化一个Ser ...
- 【Python】socket编程-2
#练习3:TCP协议+while循环 服务端: import socket #socket模块 import sys reload(sys) sys.setdefaultencoding(" ...
- 【Python】socket编程-1
一.什么是socket编程:网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket,编程传输层,socket本质是编程接口(API) 二.网络七层协议:物里层 数据链 ...
- 【python】socket
UDP udp_server.py from datetime import datetime import socket server_address = ('localhost', 6789) m ...
- 【python】-- Socket粘包问题 ,解决粘包的几种方法、socket文件下载,md5值检验
上一篇随笔:“socket 接收大数据”,在win系统上能够运行,并且解决了大数据量的数据传输出现的问题,但是运行在linux系统上就会出现如下图所示的情况: 就是服务端两次发送给客户端的数据(第一次 ...
- 【Python】【网络编程】
#[[网络编程]] # 网络通信就是两个进程之间在通信 # [TCP/IP]'''TCP/IP简介 阅读: 125242虽然大家现在对互联网很熟悉,但是计算机网络的出现比互联网要早很多. 计算机为了联 ...
- 【python】列出http://www.cnblogs.com/xiandedanteng中所有博文的标题
代码: # 列出http://www.cnblogs.com/xiandedanteng中所有博文的标题 from bs4 import BeautifulSoup import requests u ...
随机推荐
- 转: Linux 上的常用文件传输方式介绍与比较
from: https://www.ibm.com/developerworks/cn/linux/l-cn-filetransfer/ ftp ftp 命令使用文件传输协议(File Transf ...
- App开发者博客之: 包建强 (专注移动app开发)
http://www.cnblogs.com/Jax/p/4912606.html 著有"App研发录" 一书. Android EventBus源码解析 带你深入理解EventB ...
- Mac OSX下编译安装PostgreSQL
原先使用的是官方提供的安装包,可是安装包会创建postgre这个用户.在登陆界面看的有点不爽,搜索了半天居然没有找到怎样在osx下编译安装的教程,并且假设是依照官方文档的编译安装办法一定会让你崩溃,本 ...
- java起源和基本数据类型
1.Java起源于1994年的sun公司,起初并没有体现出它独特的优势.sun公司一度想要放弃这个项目.亏的领头人的力争.Java才的以存在.二十世纪末.随着互联网的兴起.交互式设计越来越多的应用,对 ...
- Mysql 常用函数汇总
转自:http://blog.csdn.net/qq_27416209/article/details/52020720 一.数学函数ABS(x) 返回x的绝对值BIN(x) 返回x的二进制( ...
- 使用ALAssetsLibrary读取所有照片
一. ALAssetsLibrary 介绍 ALAssetsLibrary 提供了访问iOS设备下”照片”应用下所有照片和视频的接口: 从 ALAssetsLibrary 中可读取所有的相册数据,即 ...
- PATHINFO模式是thinkphp特有的吗?
pathinfo当然不是某个框架特有的,pathinfo严格上讲是HTTP服务器提供的一个预定义变量,在许多的框架中有一个重要的组件叫做路由器,这个组件可以通过使用pathinfo来实现. 考虑以下代 ...
- Apache + Tomcat集群 + 负载均衡
Part I: 取经处: http://www.ramkitech.com/2012/10/tomcat-clustering-series-simple-load.html http://blog ...
- C++11并发学习之三:线程同步(转载)
C++11并发学习之三:线程同步 1.<mutex> 头文件介绍 Mutex又称互斥量,C++ 11中与 Mutex 相关的类(包括锁类型)和函数都声明在 <mutex> 头文 ...
- implicitly declaring function 'malloc' with type void *(unsigned long ) 错误 解决
errror : implicitly declaring function 'malloc' with type void *(unsigned long ) Be sure to includ ...