1、socket介绍

socket的英文原义是“孔”或“插座”。作为BSD UNIX的进程通信机制,取后一种意思。通常也

称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。在Internet上的主机一 般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。Socket正如其英文原 意那样,像一个多孔插座。一台主机犹如布满各种插座的房间,每个插座有一个编号,有的插座提供220伏交流电, 有的提供110伏交流电,有的则提供有线电视节目。 客户软件将插头插到不同编号的插座,就可以得到不同的服务

2、连接原理

根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认。

(1)服务器监听:是服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。

(2)客户端请求:是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。

(3)连接确认:是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。

案例:

1、最简单的web服务器

  1. #!/usr/bin/env python
  2. #coding:utf-8
  3. #导入socket模块
  4. import socket
  5. #开启ip和端口
  6. ip_port = ('127.0.0.1',8080)
  7. #生成句柄
  8. web = socket.socket()
  9. #绑定端口
  10. web.bind(ip_port)
  11. #最多连接数
  12. web.listen(5)
  13. #等待信息
  14. print ('nginx waiting...')
  15. #开启死循环
  16. while True:
  17. #阻塞
  18. conn,addr = web.accept()
  19. #获取客户端请求数据
  20. data = conn.recv(1024)
  21. #打印接受数据 注:当浏览器访问的时候,接受的数据的浏览器的信息等。
  22. print(data)
  23. #向对方发送数据
  24. conn.send(bytes('<h1>welcome nginx</h1>','utf8'))
  25. #关闭链接
  26. conn.close()

2.简单的聊天工具

1.service端

  1. #!/usr/bin/env python
  2. #coding:utf-8
  3. import socket
  4. #开启ip和端口
  5. ip_port = ('127.0.0.1',9999)
  6. #生成一个句柄
  7. sk = socket.socket()
  8. #绑定ip端口
  9. sk.bind(ip_port)
  10. #最多连接数
  11. sk.listen(5)
  12. #开启死循环
  13. while True:
  14. print ('server waiting...')
  15. #等待链接,阻塞,直到渠道链接 conn打开一个新的对象 专门给当前链接的客户端 addr是ip地址
  16. conn,addr = sk.accept()
  17. #获取客户端请求数据
  18. client_data = conn.recv(1024)
  19. #打印对方的数据
  20. print (str(client_data,'utf8'))
  21. #向对方发送数据
  22. conn.sendall(bytes('不要回答,不要回答,不要回答','utf8'))
  23. #关闭链接
  24. conn.close()

2)client端

  1. #!/usr/bin/env python
  2. #coding:utf-8
  3. import socket
  4. #链接服务端ip和端口
  5. ip_port = ('127.0.0.1',9999)
  6. #生成一个句柄
  7. sk = socket.socket()
  8. #请求连接服务端
  9. sk.connect(ip_port)
  10. #发送数据
  11. sk.sendall(bytes('yaoyao','utf8'))
  12. #接受数据
  13. server_reply = sk.recv(1024)
  14. #打印接受的数据
  15. print (str(server_reply,'utf8'))
  16. #关闭连接
  17. sk.close()

3、更多功能

  1. 更多功能
  2. sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0)
  3. 参数一:地址簇
  4. socket.AF_INET IPv4(默认)
  5. socket.AF_INET6 IPv6
  6. socket.AF_UNIX 只能够用于单一的Unix系统进程间通信
  7. 参数二:类型
  8. socket.SOCK_STREAM  流式socket , for TCP (默认)
  9. socket.SOCK_DGRAM   数据报式socket , for UDP
  10. socket.SOCK_RAW 原始套接字,普通的套接字无法处理ICMPIGMP等网络报文,而
  11. SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以
  12. 通过IP_HDRINCL套接字选项由用户构造IP头。
  13. socket.SOCK_RDM 是一种可靠的UDP形式,即保证交付数据报但不保证顺序。
  14. SOCK_RAM用来提供对原始协议的低级访问,在需要执行某些特殊操作时使用,
  15. 如发送ICMP报文。SOCK_RAM通常仅限于高级用户或管理员运行的程序使用。
  16.   socket.SOCK_SEQPACKET 可靠的连续数据包服务
  17. 参数三:协议
  18. 0  (默认)与特定的地址家族相关的协议,如果是 0
  19. 则系统就会根据地址格式和套接类别,自动选择一个合适的协议
  20. sk.bind(address)
  21. s.bind(address) 将套接字绑定到地址。address地址的格式取决于地址族。
  22. AF_INET下,以元组(host,port)的形式表示地址。
  23. sk.listen(backlog)
  24. 开始监听传入连接。backlog指定在拒绝连接之前,可以挂起的最大连接数量。
  25. backlog等于5,表示内核已经接到了连接请求,但服务器还没有调用accept进行处理的
  26. 连接个数最大为5,这个值不能无限大,因为要在内核中维护连接队列
  27. sk.setblocking(bool)
  28. 是否阻塞(默认True),如果设置False,那么acceptrecv时一旦无数据,则报错。
  29. sk.accept()
  30. 接受连接并返回(conn,address),其中conn是新的套接字对象,可以用来接收
  31. 和发送数据。address是连接客户端的地址。接收TCP 客户的连接(阻塞式)等待连接的到来
  32. sk.connect(address)
  33. 连接到address处的套接字。一般,address的格式为元组(hostname,port),
  34. 如果连接出错,返回socket.error错误。
  35. sk.connect_ex(address)
  36. 同上,只不过会有返回值,连接成功时返回 0 ,连接失败时候返回编码,例如:10061
  37. sk.close()
  38. 关闭套接字
  39. sk.recv(bufsize[,flag])
  40. 接受套接字的数据。数据以字符串形式返回,bufsize指定最多可以接收的数量。
  41. flag提供有关消息的其他信息,通常可以忽略。
  42. sk.recvfrom(bufsize[.flag])
  43. recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,
  44. address是发送数据的套接字地址。
  45. sk.send(string[,flag])
  46. string中的数据发送到连接的套接字。返回值是要发送的字节数量,
  47. 该数量可能小于string的字节大小。即:可能未将指定内容全部发送。
  48. sk.sendall(string[,flag])
  49. string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。
  50. 成功返回None,失败则抛出异常。
  51. 内部通过递归调用send,将所有内容发送出去。
  52. sk.sendto(string[,flag],address)
  53. 将数据发送到套接字,address是形式为(ipaddrport)的元组,指定远程地址。
  54. 返回值是发送的字节数。该函数主要用于UDP协议。
  55. sk.settimeout(timeout)
  56. 设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。
  57. 一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作
  58. (如 client 连接最多等待5s
  59. sk.getpeername()
  60. 返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。
  61. sk.getsockname()
  62. 返回套接字自己的地址。通常是一个元组(ipaddr,port)
  63. sk.fileno()
  64. 套接字的文件描述符

案例:

机器人:

1.服务端:

  1. #!/usr/bin/env python3
  2. #coding:utf8
  3. import socket
  4. #开启端口和ip
  5. ip_port = ('127.0.0.1',8888)
  6. #生成句柄
  7. server = socket.socket()
  8. #绑定ip和端口
  9. server.bind(ip_port)
  10. #最大连接数
  11. server.listen(5)
  12. while True:
  13. #阻塞
  14. conn,addr = server.accept()
  15. #传出数据
  16. conn.sendall(bytes('欢迎使用多功能机器人,请输入1','utf8'))
  17. Falg =True
  18. while Falg:
  19. #接受数据
  20. data = conn.recv(1024)
  21. if data == '1':
  22. conn.sendall(bytes('ok'))
  23. else:
  24. conn.sendall(bytes('no'))
  25. conn.close()

2.客户端:

  1. #!/usr/bin/env python3
  2. #coding:utf8
  3. import socket
  4. #监听端口
  5. ip_port = ('127.0.0.1',8888)
  6. #生成句柄
  7. client = socket.socket()
  8. #绑定
  9. client.connect(ip_port)
  10. #设置超时时间
  11. client.settimeout(5)
  12. while True:
  13. #接受数据
  14. data = client.recv(1024)
  15. #打印数据
  16. print(str(data,'utf8'))
  17. #输入
  18. wait = input('请输入')
  19. #把输入的数值进行传值
  20. client.sendall(wait)
  21. if wait == 'exit':
  22. break
  23. client.close()

一.SocketServer

SocketServer内部使用 IO多路复用 以及 “多线程” 和 “多进程” ,从而实现并发处理多个客户端请求的Socket服务端。即:每个客户端请求连接到服务器时,Socket服务端都会在服务器是创建一个“线程”或者“进程” 专门负责处理当前客户端的所有请求。

注:导入模块的时候 3.x版本是socketserver 2.x版本是SocketServer

1.ThreadingTCPServer

ThreadingTCPServer实现的Soket服务器内部会为每个client创建一个 “线程”,该线程用来和客户端进行交互。

  1. ThreadingTCPServer基础

    使用ThreadingTCPServer:

创建一个继承自 SocketServer.BaseRequestHandler 的类

类中必须定义一个名称为 handle 的方法

启动ThreadingTCPServer

服务端:

  1. import SocketServer
  2. class MyServer(SocketServer.BaseRequestHandler):
  3. def handle(self):
  4. conn = self.request
  5. conn.sendall('我是多线程')
  6. Flag = True
  7. while Flag:
  8. data = conn.recv(1024)
  9. if data == 'exit':
  10. Flag = False
  11. elif data == '0':
  12. conn.sendall('您输入的是0')
  13. else:
  14. conn.sendall('请重新输入.')
  15. if __name__ == '__main__':
  16. server = SocketServer.ThreadingTCPServer(('127.0.0.1',8009),MyServer)
  17. server.serve_forever()

客户端:

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. import socket
  4. ip_port = ('127.0.0.1',8009)
  5. sk = socket.socket()
  6. sk.connect(ip_port)
  7. while True:
  8. data = sk.recv(1024)
  9. print 'receive:',data
  10. inp = input('please input:')
  11. sk.sendall(inp)
  12. if inp == 'exit':
  13. break
  14. sk.close()

内部调用流程为:

  • 启动服务端程序
  • 执行 TCPServer.init 方法,创建服务端Socket对象并绑定 IP 和 端口
  • 执行 BaseServer.init 方法,将自定义的继承自SocketServer.BaseRequestHandler 的类 - MyRequestHandle赋值给 self.RequestHandlerClass
  • 执行 BaseServer.server_forever 方法,While 循环一直监听是否有客户端请求到达 ...

    当客户端连接到达服务器
  • 执行 ThreadingMixIn.process_request 方法,创建一个 “线程” 用来处理请求
  • 执行 ThreadingMixIn.process_request_thread 方法
  • 执行 BaseServer.finish_request 方法,执行 self.RequestHandlerClass() 即:执行 自定义 MyRequestHandler 的构造方法(自动调用基类BaseRequestHandler的构造方法,在该构造方法中又会调用 MyRequestHandler的handle方法)
ForkingTCPServer

ForkingTCPServer和ThreadingTCPServer的使用和执行流程基本一致,只不过在内部分别为请求者建立 “线程” 和 “进程”。

  1. server = socketserver.ThreadingTCPServer(('127.0.0.1',8009),MyRequestHandler)
  2. 变更为:
  3. server = socketserver.ForkingTCPServer(('127.0.0.1',8009),MyRequestHandler)
  4. socketserverThreadingTCPServer之所以可以同时处理请求得益于 select os.fork
  5. 两个东西,其实本质上就是在服务器端为每一个客户端创建一个进程,
  6. 当前新创建的进程用来处理对应客户端的请求,所以,可以支持同时n个客户端链接(长连接)。

完毕!

10.python之socket和socketserver的更多相关文章

  1. python_way day10 python和其他语言的作用域 、 python2.7多继承和3.5多继承的区别 、 socket 和 socketserver源码(支持并发处理socket,多进程,多线程)

    python_way day10 1.python的作用域和其他语言的作用域 2.python2.7多继承和3.5多继承的区别 3.socket和socketserver源码(并发处理socket) ...

  2. python socket和socketserver

    Python提供了两个基本的socket模块.一个是socket,它提供了标准的BSD Socket API:另一个是socketServer,它提供了服务器中心类,可以简化网络服务器的开发. 下面先 ...

  3. Python自动化运维之15、网络编程之socket、socketserver、select、twisted

    一.TCP/IP相关知识 TCP/UDP提供进程地址,两个协议互不干扰的独自的协议       TCP :Transmission Control Protocol 传输控制协议,面向连接的协议,通信 ...

  4. Python进阶----UDP协议使用socket通信,socketserver模块实现并发

    Python进阶----UDP协议使用socket通信,socketserver模块实现并发 一丶基于UDP协议的socket 实现UDP协议传输数据 代码如下:

  5. python之socket

    一.初识socket      socket 是网络连接端点,每个socket都被绑定到一个特定的IP地址和端口.IP地址是一个由4个数组成的序列,这4个数均是范围 0~255中的值(例如,     ...

  6. Python之socket(套接字)

    Socket 一.概述 socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. ...

  7. Python基础socket编程

    Python 提供了两个基本的 socket 模块. 第一个是 Socket,它提供了标准的 BSD Sockets API. 第二个是 SocketServer, 它提供了服务器中心类,可以简化网络 ...

  8. python实现socket上传下载文件-进度条显示

    在python的socket编程中,可以实现上传下载文件,并且在下载的时候,显示进度条,具体的流程如下图所示: 1. 服务器端代码如下: [root@python 519]# cat server.p ...

  9. 「Python」socket指南

    开始 网络中的 Socket 和 Socket API 是用来跨网络的消息传送的,它提供了 进程间通信(IPC) 的一种形式.网络可以是逻辑的.本地的电脑网络,或者是可以物理连接到外网的网络,并且可以 ...

随机推荐

  1. TCP/IP详解 学习六

    从ip层看路由表  选路策略 选路策略:决定把哪些路由放到路由表的规则. Ip执行选路机制,而路由守护程序则提供选路策略. Netstat –rn 打印路由表,如果没有-n命令会搜索配置文件,将网络地 ...

  2. java判断list为空

    isEmpty()判断有没有元素而size()返回有几个元素 list.isEmpty()和list.size()==0 没有区别 list!=null跟!list.isEmpty()有什么区别? 这 ...

  3. JAVA中toString方法的作用

    因为它是Object里面已经有了的方法,而所有类都是继承Object,所以“所有对象都有这个方法”. 它通常只是为了方便输出,比如System.out.println(xx),括号里面的“xx”如果不 ...

  4. HDU #5507 GT and Strings

    这是AC自动机系列的第一篇 传送门 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Othe ...

  5. JAVA-封装

    1.什么是封装? 顾名思义,封装就是装起来,圈起来的意思,用于类与对象中来讲,就是在一个类中把对象拥有的属性和隐藏信息(条件)进行封装,不允许外部程序直接访问,而必须要通过该类提供的方法来实现对隐藏信 ...

  6. SOAP 格式设置选项

    SOAP 格式设置选项 两个格式设置选项为: Style:适用于 SOAP 消息中 Body 元素的子元素(也可能是孙级).此选项指定为 binding WSDL 元素(通常情况下)或 operati ...

  7. struct和union分析实例

    1.#include <stdio.h>#include <malloc.h>typedef struct _soft_array{    int len;    int ar ...

  8. C++ map 映照容器

    map映照容器的元素数据是一个键值和一个映照数据组成的,键值与映照数据之间具有一一映照的关系. map映照容器的数据结构是采用红黑树来实现的,插入键值的元素不允许重复,比较函数只对元素的键值进行比较, ...

  9. SSL协议运行机制

    SSL/TLS协议运行机制 一.作用 不使用SSL/TLS的HTTP通信,就是不加密的通信.所有信息明文传播,带来了三大风险. (1) 窃听风险(eavesdropping):第三方可以获知通信内容. ...

  10. Metasploit自动攻击和选择模块攻击详解

    Author:魔术@Freebuf.com 0×1自动攻击 终端启动Metasploit,因为我现在Source Code,所以这样启动! 连接数据库 安装方法,执行以下命令即可(请用ROOT执行). ...