python select网络编程详细介绍
刚看了反应堆模式的原理,特意复习了socket编程,本文主要介绍python的基本socket使用和select使用,主要用于了解socket通信过程
一、socket模块
socket
— Low-level networking interface
This module provides access to the BSD socket interface. It is available on all modern Unix systems, Windows, MacOS, and probably additional platforms.
更多详细信息请看官方文档 https://docs.python.org/3/library/socket.html
1、Socket类型
socket 常量 |
描述 |
socket.AF_UNIX |
只能够用于单一的Unix系统进程间通信 |
socket.AF_INET |
服务器之间网络通信 |
socket.AF_INET6 |
IPv6 |
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_SEQPACKET |
可靠的连续数据包服务 |
创建TCP Socket: |
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) |
创建UDP Socket: |
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) |
2、socket函数
服务器端 Socket 函数
Socket 函数 | 描述 |
---|---|
s.bind(address) | 将套接字绑定到地址,在AF_INET下,以tuple(host, port)的方式传入,如s.bind((host, port)) |
s.listen(backlog) | 开始监听TCP传入连接,backlog指定在拒绝链接前,操作系统可以挂起的最大连接数,该值最少为1,大部分应用程序设为5就够用了 |
s.accpet() | 接受TCP链接并返回(conn, address),其中conn是新的套接字对象,可以用来接收和发送数据,address是链接客户端的地址。 |
客户端 Socket 函数
Socket 函数 | 描述 |
---|---|
s.connect(address) | 链接到address处的套接字,一般address的格式为tuple(host, port),如果链接出错,则返回socket.error错误 |
s.connect_ex(address) | 功能与s.connect(address)相同,但成功返回0,失败返回errno的值 |
公共 Socket 函数
Socket 函数 | 描述 |
---|---|
s.recv(bufsize[, flag]) | 接受TCP套接字的数据,数据以字符串形式返回,buffsize指定要接受的最大数据量,flag提供有关消息的其他信息,通常可以忽略 |
s.send(string[, flag]) | 发送TCP数据,将字符串中的数据发送到链接的套接字,返回值是要发送的字节数量,该数量可能小于string的字节大小 |
s.sendall(string[, flag]) | 完整发送TCP数据,将字符串中的数据发送到链接的套接字,但在返回之前尝试发送所有数据。成功返回None,失败则抛出异常 |
s.recvfrom(bufsize[, flag]) | 接受UDP套接字的数据u,与recv()类似,但返回值是tuple(data, address)。其中data是包含接受数据的字符串,address是发送数据的套接字地址 |
s.sendto(string[, flag], address) | 发送UDP数据,将数据发送到套接字,address形式为tuple(ipaddr, port),指定远程地址发送,返回值是发送的字节数 |
s.close() | 关闭套接字 |
s.getpeername() | 返回套接字的远程地址,返回值通常是一个tuple(ipaddr, port) |
s.getsockname() | 返回套接字自己的地址,返回值通常是一个tuple(ipaddr, port) |
s.setsockopt(level, optname, value) | 设置给定套接字选项的值 |
s.getsockopt(level, optname[, buflen]) | 返回套接字选项的值 |
s.settimeout(timeout) | 设置套接字操作的超时时间,timeout是一个浮点数,单位是秒,值为None则表示永远不会超时。一般超时期应在刚创建套接字时设置,因为他们可能用于连接的操作,如s.connect() |
s.gettimeout() | 返回当前超时值,单位是秒,如果没有设置超时则返回None |
s.fileno() | 返回套接字的文件描述 |
s.setblocking(flag) | 如果flag为0,则将套接字设置为非阻塞模式,否则将套接字设置为阻塞模式(默认值)。非阻塞模式下,如果调用recv()没有发现任何数据,或send()调用无法立即发送数据,那么将引起socket.error异常。 |
s.makefile() | 创建一个与该套接字相关的文件 |
3、socket异常
Exception | 解释 |
socket.error |
由Socket相关错误引发 |
socket.herror | 由地址相关错误引发 |
socket.gaierror | 由地址相关错误,如getaddrinfo()或getnameinfo()引发 |
socket.timeout | 当socket出现超时时引发。超时时间由settimeout()提前设定 |
二、socket编程
1、基于TCP(面向连接)的Socket编程(C++)
(5. 关闭套接字(closesocket)
3、socket tcp 编程实例,c/s程序
#!/bin/env python # -*- coding:utf8 -*- """ server.py """ import socket host = ('10.1.32.80', 33333) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 网络通信, TCP流 s.bind(host) s.listen(5) # listen 5 client print "i'm waiting for connection..." while True: conn, addr = s.accept() # connection and ip address print 'connected by', addr while True: data = conn.recv(1024) print "receive from %s:%s" % (addr, data) conn.sendall("server receive your messages, good bye.") conn.close() break # s.close()
#!/bin/env python # -*- coding:utf8 -*- import socket """ client.py """ host = ('10.1.32.80', 33333) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 网络通信, TCP流 s.connect(host) while True: msg = raw_input("Please input message: ") try: s.sendall(msg) except socket.error: print "i'm die, bye bye~" break data = s.recv(1024) print data if "good bye" in data: break s.close()
三、基于select的网络编程
1、select介绍
2、使用select编程,聊天室程序如下。运行多个client,则可互相聊天,输入"exit"即可退出
服务器代码
#!/bin/env python #-*- coding:utf8 -*-""" server select """import sys import time import socket import select import logging import Queueg_select_timeout = 10class Server(object):def __init__(self, host='10.1.32.80', port=33333, timeout=2, client_nums=10):self.__host = hostself.__port = portself.__timeout = timeoutself.__client_nums = client_numsself.__buffer_size = 1024self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)self.server.setblocking(False)self.server.settimeout(self.__timeout)self.server.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) #keepaliveself.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) #端口复用server_host = (self.__host, self.__port)try:self.server.bind(server_host)self.server.listen(self.__client_nums)except:raiseself.inputs = [self.server] #select 接收文件描述符列表 self.outputs = [] #输出文件描述符列表self.message_queues = {}#消息队列self.client_info = {}def run(self):while True:readable , writable , exceptional = select.select(self.inputs, self.outputs, self.inputs, g_select_timeout)if not (readable or writable or exceptional) :continuefor s in readable :if s is self.server:#是客户端连接connection, client_address = s.accept()#print "connection", connectionprint "%s connect." % str(client_address)connection.setblocking(0) #非阻塞self.inputs.append(connection) #客户端添加到inputsself.client_info[connection] = str(client_address)self.message_queues[connection] = Queue.Queue() #每个客户端一个消息队列else:#是client, 数据发送过来try:data = s.recv(self.__buffer_size)except:err_msg = "Client Error!"logging.error(err_msg)if data :#print datadata = "%s %s say: %s" % (time.strftime("%Y-%m-%d %H:%M:%S"), self.client_info[s], data)self.message_queues[s].put(data) #队列添加消息 if s not in self.outputs: #要回复消息 self.outputs.append(s)else: #客户端断开#Interpret empty result as closed connectionprint "Client:%s Close." % str(self.client_info[s])if s in self.outputs :self.outputs.remove(s)self.inputs.remove(s)s.close()del self.message_queues[s]del self.client_info[s]for s in writable: #outputs 有消息就要发出去了try:next_msg = self.message_queues[s].get_nowait() #非阻塞获取except Queue.Empty:err_msg = "Output Queue is Empty!"#g_logFd.writeFormatMsg(g_logFd.LEVEL_INFO, err_msg) self.outputs.remove(s)except Exception, e: #发送的时候客户端关闭了则会出现writable和readable同时有数据,会出现message_queues的keyerrorerr_msg = "Send Data Error! ErrMsg:%s" % str(e)logging.error(err_msg)if s in self.outputs:self.outputs.remove(s)else:for cli in self.client_info: #发送给其他客户端if cli is not s:try:cli.sendall(next_msg)except Exception, e: #发送失败就关掉err_msg = "Send Data to %s Error! ErrMsg:%s" % (str(self.client_info[cli]), str(e))logging.error(err_msg)print "Client: %s Close Error." % str(self.client_info[cli])if cli in self.inputs:self.inputs.remove(cli)cli.close()if cli in self.outputs:self.outputs.remove(s)if cli in self.message_queues:del self.message_queues[s]del self.client_info[cli]for s in exceptional:logging.error("Client:%s Close Error." % str(self.client_info[cli]))if s in self.inputs:self.inputs.remove(s)s.close()if s in self.outputs:self.outputs.remove(s)if s in self.message_queues:del self.message_queues[s]del self.client_info[s]if "__main__" == __name__:Server().run()
客户端代码
#!/usr/local/bin/python # *-* coding:utf-8 -*-""" client.py """import sys import time import socket import threadingclass Client(object):def __init__(self, host, port=33333, timeout=1, reconnect=2):self.__host = hostself.__port = portself.__timeout = timeoutself.__buffer_size = 1024self.__flag = 1self.client = Noneself.__lock = threading.Lock() @propertydef flag(self):return self.__flag@flag.setterdef flag(self, new_num):self.__flag = new_numdef __connect(self):client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)#client.bind(('0.0.0.0', 12345,)) client.setblocking(True)client.settimeout(self.__timeout)client.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) #端口复用server_host = (self.__host, self.__port)try:client.connect(server_host)except:raisereturn clientdef send_msg(self):if not self.client:returnwhile True:time.sleep(0.1)#data = raw_input()data = sys.stdin.readline().strip()if "exit" == data.lower():with self.__lock:self.flag = 0breakself.client.sendall(data)returndef recv_msg(self):if not self.client:returnwhile True:data = Nonewith self.__lock:if not self.flag:print 'ByeBye~~'breaktry:data = self.client.recv(self.__buffer_size)except socket.timeout:continueexcept:raiseif data:print "%s\n" % datatime.sleep(0.1)returndef run(self):self.client = self.__connect()send_proc = threading.Thread(target=self.send_msg)recv_proc = threading.Thread(target=self.recv_msg)recv_proc.start()send_proc.start()recv_proc.join()send_proc.join()self.client.close()if "__main__" == __name__:Client('10.1.32.80').run()
四、多路IO复用介绍和区别
转载于:https://www.cnblogs.com/lxmhhy/p/6091730.html
python select网络编程详细介绍相关推荐
- java socket 高级编程_Java高级编程-网络编程详细介绍 (一)
java.net 包中的类和接口提供了可用于低层和高层网络编程的 API.低层 API 可以让你直接访问网络协议,但是为此你不得不使用低层的 TCP 套接字和 UDP 数据包.高层的 API (如 U ...
- Python之网络编程(TCP套接字与UDP套接字)
文章目录 基于tcp的套接字 实现目标 tcp服务端源码 tcp客户端源码 tcp效果实现 基于udp的套接字 udp作用介绍 udp服务端源码 udp客户端源码 udp效果实现 用udp实现一个时间 ...
- Python 异步网络编程实战
Python 异步网络编程实战 - songcser - 掘金小册 小册介绍 第一部分是对 Python 协程的讲解,从字节码开始简单讲解了 Python 虚拟机的执行过程,可以大体了解到 Pytho ...
- Python高级网络编程系列之第一篇
在上一篇中我们简单的说了一下Python中网络编程的基础知识(相关API就不解释了),其中还有什么细节的知识点没有进行说明,如什么是TCP/IP协议有几种状态,什么是TCP三次握手,什么是TCP四次握 ...
- Python Socket网络编程(二)局域网内和局域网与广域网的持续通信
目录 前言 IP地址 简介 公有IP 私有IP 局域网之间网络通信 前提 功能描述 源码 运行结果 局域网与广域网网络通信 前提 源码 结语 前言 本系列博客是笔者学习Python Socket的过程 ...
- Python Socket网络编程(一)初识Socket和Socket初步使用
目录 前言 网络编程 实质 IP地址和端口 数据传输协议 协议 Socket 概念 套接字 socket对象方法 初步使用 功能 源码 运行结果 结语 前言 本系列博客是笔者学习Python Sock ...
- python recv_python网络编程调用recv函数完整接收数据的三种方法
最近在使用python进行网络编程开发一个通用的tcpclient测试小工具.在使用socket进行网络编程中,如何判定对端发送一条报文是否接收完成,是进行socket网络开发必须要考虑的一个问题.这 ...
- java 网络编程详细解析
文章目录 java 网络编程详细解析 网络编程的常识 七层网络模型 相关的协议(笔试题) 协议的概念 TCP协议 UDP协议 IP地址(重点) 查看IP地址的方式: 特殊的地址 端口号(重点) 基于t ...
- 用 Python 写网络编程(四)
本文首发于TesterHome社区,作者是资深游戏测试开发工程师陈子昂.用 Python 写网络编程共四篇,今天分享的是第四篇.原文链接:https://testerhome.com/topics/2 ...
- 0x011.Python学习-网络编程、PortScan
Python3 网络编程 Python 提供了两个级别访问的网络服务.: 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口 ...
最新文章
- 对我国6G早期研究布局的几点建议
- 应该始终以PreparedStatement代替Statement
- js断点和调试学习总结3
- Windows下的bat文件的@echo off 作用
- 推荐一套开源通用后台管理系统(附源码)
- wxWidgets:wxLogFormatter类用法
- 20个jQuery 图片及多媒体画廊插件
- 注塑模介绍、设计中文语音多媒体教学光盘 1CD
- 如何一键下载或保存微博里面的短视频?
- 《计算机视觉工程师养成计划》·开篇
- 深度学习中的batch、epoch、iteration
- 做哪些事情可以提升生活品质?四十七个小建议
- Ubuntu20.04+Nvidia RTX 3060 显卡驱动安装
- NLP算法之一(朴素贝叶斯理论部分)
- java代码:双色球号随机生成(极其简洁!)
- 阿里云Maven仓库地址及设置
- python网络爬虫——pyquery的使用(六)
- 环洋市场调研-2021年全球抗衰老肽护肤品行业调研及趋势分析报告
- 【APICloud系列|5】一键生成APP所有图标
- redhat7.6添加中文语言支持