python之Socket网络编程详解


Posted in Python onSeptember 29, 2016

什么是网络?

网络是由节点和连线构成,表示诸多对象及其相互联系。在数学上,网络是一种图,一般认为专指加权图。网络除了数学定义外,还有具体的物理含义,即网络是从某种相同类型的实际问题中抽象出来的模型。在计算机领域中,网络是信息传输、接收、共享的虚拟平台,通过它把各个点、面、体的信息联系到一起,从而实现这些资源的共享。网络是人类发展史来最重要的发明,提高了科技和人类社会的发展。

网络通信的三要素

IP地址
用来表示一台独立的主机
特殊的IP地址 127.0.0.1或称localhost(表示本地回环地址,保留地址等),可用于本机测试

端口号
要将数据发送到对方指定的应用程序上,为了标识这些应用程序,所以给这些网络应用程序都用数字进行标识。为了方便称呼这些数字,则将这些数字称为端口

传输协议
TCP协议:传输控制协议
面向连接:传输之前需要建立连接
在连接过程中进行大量数据传输
通过三次握手方式连接,属于安全可靠连接
传输速率慢,效率低
UDP协议:用户传输协议
面向无连接:传输过程不需要建立连接即可传输
每个数据传输的大小都限制在64K以内
传输过程不可靠
传输速率快,效率高

SOCKET网络编程

如简单的实现一个WEB小程序

import socket
def handle_request(client):
 buf = client.recv(1024)
 client.send(bytes("HTTP/1.1 200 OK\r\n\r\n",'utf8'))
 client.send(bytes("Hello, World",'utf8'))

def main():
 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 sock.bind(('localhost', 8080))
 sock.listen(5)

 while True:
  connection, address = sock.accept()
  handle_request(connection)
  connection.close()


if __name__ == '__main__':
 main()

Python 提供了两个级别访问的网络服务:

低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的全部方法。
高级别的网络服务模块 SocketServer, 它提供了服务器中心类,可以简化网络服务器的开发。

什么是socket?

Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。

Socket()函数:

socket.socket([family[, type[, proto]]])

参数

family: 套接字家族可以使AF_UNIX或者AF_INET
type: 套接字类型可以根据是面向连接的还是非连接分为SOCK_STREAM或SOCK_DGRAM
protocol: 一般不填默认为0。

通信流程

python之Socket网络编程详解

#######server端##########

import socket

sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.bind(address)
sk.listen(3)

while True:
 conn, addr = sk.accept()
 while True:
  try:
   data = conn.recv(1024)
   print(str(data, 'utf8'))
   if not data:
    break
   inp = input(">>>")
   conn.send(bytes(inp, 'utf8'))
  except Exception:
   break

conn.close()

##########Client端###########
import socket

sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.connect(address)
while True:
 inp = input(">>>")
 if inp == "exit":
  break
 sk.send(bytes(inp, 'utf8'))
 data = sk.recv(1024)
 print(str(data, 'utf8'))
sk.close()

Socket内建方法

s.bind()    绑定地址(host,port)到套接字, 在AF_INET下,以元组(host,port)的形式表示地址。
s.listen()  开始TCP监听。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。
s.accept()  被动接受TCP客户端连接,(阻塞式)等待连接的到来<br>
客户端套接字
s.connect() 主动初始化TCP服务器连接,。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
s.connect_ex()  connect()函数的扩展版本,出错时返回出错码,而不是抛出异常<br>
公共用途的套接字函数
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()    创建一个与该套接字相关连的文件

实例

#########Server端##########

import socket
import subprocess

sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.bind(address)
sk.listen(3)


while True:
 conn, addr = sk.accept()
 while True:
  try:
   data = conn.recv(1024)
  except Exception:
   break
  if not data:
   break

  # print(str(data, 'utf8'))
  # data = str(data, 'utf8')#解码同decode
  obj = subprocess.Popen(data.decode('utf8'), shell=True, stdout=subprocess.PIPE)
  ssh_result = obj.stdout.read()
  result_len = bytes(str(len(ssh_result)),'utf8')
  conn.send(result_len)

  conn.send(ssh_result)

conn.close()


#########Client#########


import socket

sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.connect(address)

while True:
 inp = input(">>>")
 if inp == "exit":
  break
 sk.send(bytes(inp, 'utf8'))
 result_len = int(str(sk.recv(1024), 'utf8'))
 print(result_len)
 data = bytes()
 while len(data) != result_len:
  recv = sk.recv(1024)
  data += recv
 print(str(data, 'gbk'))
sk.close()

文件上传

Server

import socket
import os

sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.bind(address)
sk.listen(3)

BASE_DIR = os.path.dirname(os.path.abspath(__file__))

while True:
 conn, addr = sk.accept()
 while True:
  data = conn.recv(1024)
  cmd, file_name, file_size = str(data, 'utf8').split('|')
  path = os.path.join(BASE_DIR, 'model', file_name)
  file_size = int(file_size)

  f = open(path, 'ab')
  has_recv = 0
  while has_recv != file_size:
   data = conn.recv(1024)
   f.write(data)
   has_recv += len(data)
  f.close()

Client

import socket
import os

sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.connect(address)

BASE_DIR = os.path.dirname(os.path.abspath(__file__))

while True:
 inp = input(">>>>").strip()
 path = os.path.join(BASE_DIR, inp)

 file_name = os.path.basename(path)
 file_size = os.stat(path).st_size
 file_info = 'post|%s|%s' % (file_name, file_size)
 sk.sendall(bytes(file_info, 'utf8'))

 f = open(path, 'rb')
 has_sent = 0
 while has_sent != file_size:
  data = f.read(1024)
  sk.sendall(data)
  has_sent += len(data)

 f.close()
 print("上传成功")

socketserver

socketserver模块简化了网络编程服务程序的任务,同时SocketServer模块也是Python标准库中很多服务器框架的基础。

学习它的最好办法是自己浏览一遍它的源码。

首先先看一下如何去运用

import socketserver

class MyServer(socketserver.BaseRequestHandler):
 def handle(self):
  print("服务端启动")
  while True:
   conn = self.request

   while True:
    data = conn.recv(1024)
    print(str(data, 'utf8'))
    inp = input(">>>>>")

    conn.sendall(bytes(inp, 'utf8'))
   conn.close()

if __name__ == '__main__':
 server = socketserver.ThreadingTCPServer(('127.0.0.1', 8080), MyServer)
 server.serve_forever()

server
import socket

sk = socket.socket()

address = ('127.0.0.1', 8080)

sk.connect(address)
print("客户端启动")

while True:
 inp = input(">>>>>")
 sk.sendall(bytes(inp, 'utf8'))
 if inp == "q":
  break
 data = sk.recv(1024)
 print(str(data, 'utf8'))
sk.close()

此代码简单的实现了server端能同时和多个client聊天的功能。

我们在看源码前,首先要明确的是它分了几个类及每个类的功能作用等。

There are five classes in an inheritance diagram, four of which represent
synchronous servers of four types:

python之Socket网络编程详解

 下面的就不一一详细说了,想要了解的更透彻,还是看一遍源码吧。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python深入学习之上下文管理器
Aug 31 Python
详解Python的Flask框架中的signals信号机制
Jun 13 Python
python使用电子邮件模块smtplib的方法
Aug 28 Python
Python自定义简单图轴简单实例
Jan 08 Python
python matplotlib 注释文本箭头简单代码示例
Jan 08 Python
scrapy爬虫完整实例
Jan 25 Python
python2.7到3.x迁移指南
Feb 01 Python
python实现自动网页截图并裁剪图片
Jul 30 Python
查看python下OpenCV版本的方法
Aug 03 Python
Python手绘可视化工具cutecharts使用实例
Dec 05 Python
在python3.64中安装pyinstaller库的方法步骤
Jun 02 Python
用Python监控你的朋友都在浏览哪些网站?
May 27 Python
python 排序算法总结及实例详解
Sep 28 #Python
一些常用的Python爬虫技巧汇总
Sep 28 #Python
Python三级目录展示的实现方法
Sep 28 #Python
Python黑帽编程 3.4 跨越VLAN详解
Sep 28 #Python
python 采集中文乱码问题的完美解决方法
Sep 27 #Python
20招让你的Python飞起来!
Sep 27 #Python
python搭建虚拟环境的步骤详解
Sep 27 #Python
You might like
解析php中const与define的应用区别
2013/06/18 PHP
php根据日期判断星座的函数分享
2014/02/13 PHP
PHP中使用CURL模拟登录并获取数据实例
2014/07/01 PHP
php版本CKEditor 4和CKFinder安装及配置方法图文教程
2019/06/05 PHP
js跨域问题浅析及解决方法优缺点对比
2014/11/08 Javascript
SyntaxHighlighter 3.0.83使用笔记
2015/01/26 Javascript
js给网页加上背景音乐及选择音效的方法
2015/03/03 Javascript
浅谈javascript中for in 和 for each in的区别
2015/04/23 Javascript
JS中多种方式创建对象详解
2016/03/22 Javascript
js计算时间差代码【包括计算,天,时,分,秒】
2016/04/26 Javascript
轻松掌握JavaScript中的Math object数学对象
2016/05/26 Javascript
JS检测移动端横竖屏的代码
2016/05/30 Javascript
jQuery中的一些常见方法小结(推荐)
2016/06/13 Javascript
angular.js之路由的选择方法
2016/09/24 Javascript
JS制作适用于手机和电脑的通知信息效果
2016/10/28 Javascript
浅谈DOM的操作以及性能优化问题-重绘重排
2017/01/08 Javascript
JavaScript基本类型值-Number类型
2017/02/24 Javascript
vue-router项目实战总结篇
2018/02/11 Javascript
AngularJs用户输入动态模板XSS攻击示例详解
2018/04/21 Javascript
解决angularjs WdatePicker ng-model的问题
2018/09/13 Javascript
maptalks+three.js+vue webpack实现二维地图上贴三维模型操作
2020/08/10 Javascript
Python 文件管理实例详解
2015/11/10 Python
Python实现自动登录百度空间的方法
2017/06/10 Python
Python多进程multiprocessing.Pool类详解
2018/04/27 Python
Python爬虫之网页图片抓取的方法
2018/07/16 Python
pandas 把数据写入txt文件每行固定写入一定数量的值方法
2018/12/28 Python
Python 列表去重去除空字符的例子
2019/07/20 Python
python使用docx模块读写docx文件的方法与docx模块常用方法详解
2020/02/17 Python
Python selenium键盘鼠标事件实现过程详解
2020/07/28 Python
Python爬虫之Selenium下拉框处理的实现
2020/12/04 Python
Yahoo-PHP面试题3
2012/01/14 面试题
在校学生职业规划范文
2014/01/08 职场文书
校运会入场式解说词
2014/02/10 职场文书
金融学专业大学生职业生涯规划
2014/03/07 职场文书
市场营销方案范文
2014/03/11 职场文书
幼儿园健康教育方案
2014/06/14 职场文书