在网易工作这半年来说,单纯的写了很多奇奇怪怪的脚本,比如说在没有代码权限的情况下如何得到QA测试的代码覆盖率?到头来还是通过这个网络编程来解决,之前没有接触过网络编程,直接现学现卖完成任务。
网易有好处在吧,自己设计规划一个系统,客户端实现的功能,服务端实现的功能,还需要规划每个功能点,画时序图,说实话这是原来在华为根本接触不到的,以前在华为自己只是负责一个小功能的实现,基本上pm给出开发文档,按部就班实现就好了,吃面条,PM说你负责擀面,就把面擀好了就行了,唯一的难度在于读懂原来的代码;在网易,一切从零开始,说白了就是要吃面条,没有面粉,也没有小麦,只有一块地和一把种子。
以上就是发牢骚,没有贬低没有褒奖。
------------------------------------------------------------------------------------------------------------------------------
作者首先就是引用下大佬的话,IPV4用完了,IPV6是出路。
本章内容:简介;客户端/服务器架构;套接字:通信端点; Python 中的网络编程; *SocketServer 模块; *Twisted 框架介绍;相关模块。
2.1简介
简介。
2.2客户端/服务端架构
简要描述下CS架构,用户作为客户端一次性请求永久运行的服务端。软硬件都可以用。
2.2.1硬件客户端/服务器架构
举例子:打印机,文件服务器
2.2.2软件客户端/服务器架构
举例子:web服务器,数据库服务器,窗体服务器(这个有点抽象的)
2.2.3银行出纳员作为服务器吗
举例说明cs架构:出纳员作为服务器“永久”在线服务随时要来的客户。
2.2.4客户端/服务器网络编程
服务器创建通信端点,等待客户端连接并相应他们的请求,结束后通信终止。
2.3套接字:通信端点
套接字就是上面提到的通信端点。
2.3.1套接字
套接字可以比作电话线那个插孔;
AF:address family
现在用于进程间通讯(同一个计算机上),python用的AF_UNIX。
基于网络的,现在用的AF_INET比较广泛
总的来说,Python 只支持 AF_UNIX、 AF_NETLINK、 AF_TIPC 和AF_INET家族。
这章讲的是网络编程,所以使用AF_INET
2.3.3套接字地址:主机-端口对 重点
1.面向连接的套接字(TCP)
第一种TCP:是面向连接的,通讯之前必须建立一个连接。提供序列化的、可靠的和不重复的数据交付,没有记录边界。每条信息都可以拆分成多个片段,并且每一条消息片段都确保能够到达目的地,然后顺序的拼接起来,最后将信息完整的传递给程序。
为了创建TCP套接字,必须使用 SOCK_STREAM 作为套接字类型。
因为这些套接字(AF_INET)的网络版本使用因特网协议( IP) 来搜寻网络中的主机,所以整个系统通常结合这两种协议( TCP 和 IP) 来进行。
TCP也可以用本地的套接字(非网络,比如AF_LOCAL/ AF_UNIX),本地的就没有使用IP地址。
2.无连接的套接字(UDP)
在通讯开始不需要建立连接,传输过程中无法确保它的顺序性、可靠性和重复性,但是却记录了数据边界,也就是说数据是整体发送的,并不是切分片段发送。
这玩意纸面数据这么差谁用?但是它维护成本低,根本不用管,所以性能更好。
使用 SOCK_DGRAM 作为套接字类型。
因为这些套接字也使用因特网协议来寻找网络中的主机,所以这个系统也有一个更加普通的名字,即这两种协议( UDP 和IP)的组合名字,或 UDP/ IP。
2.4Python中的网络编程
2.4.1socket() 模块函数
创建套接字的一般语法是:socket( socket_family, socket_type, protocol = 0)
socket_family 是 AF_UNIX 或 AF_INET
socket_type是 SOCK_STREAM 或 SOCK_DGRAM
protocol通常省略,默认为 0。
创建TCP/IP套接字:tcpSock = socket.socket( socket.AF_INET, socket.SOCK_STREAM)
创建UDP/IP套接字:udpSock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM)
2.4.2套接字对象(内置)方法
2.4.3 创建 TCP 服务器
创建 TCP 服务器伪代码,目的是理解创建过程。
ss = socket() # 创建服务器套接字
ss.bind() # 套接字与地址绑定
ss.listen() # 监听连接
inf_loop: # 服务器无限循环
cs = ss.accept() # 接受客户端连接
comm_loop: # 通信循环
cs.recv()/ cs.send() # 对话(接收/发送)
cs.close() # 关闭客户端套接字
ss.close() # 关闭服务器套接字#(可选)
socket.socket () 所有套接字都是通过使用 socket ()函数来创建的。
ss.listen()监听开始之后,服务器开始无线循环中。
cs = ss.accept(),这个就是接受客户端的函数,没有连接的情况下,这个一般是阻塞的,就是说这个过程运行到这就卡住,指导有人连接后开始下一步。
cs.recv()/ cs.send()这个就是相互发送信息的函数
cs.close()关闭了连接
ss.close()服务端也关闭了。
上面这个是单服务端的例子,也就是服务端一次只能连接一个客户端。
核心提示:多线程处理客户端请求
书里没有写,可以参考下我写的这个例程:https://blog.csdn.net/marwenx/article/details/104760791
接下来是两个例子,一个python2一个python3,直接将上面这些伪代码实例化了,不在赘述。
2.4.4 创建 TCP 客户端
伪代码
cs = socket() # 创建客户端套接字
cs.connect() # 尝试连接服务器
comm_loop: # 通信循环
cs.send()/ cs.recv() # 对话(发送/接收)
cs.close() # 关闭客户端套接字
所有套接字都是利用 socket.socket() 创建的。
利用套接字的 connect() 方法直接创建一个到服务器的连接。
cs.close() 关闭套接字,终止此次连接。
例子不在赘述。
2.4.5 执行 TCP 服务器和客户端
这个就是动手实践下就好,先运行服务端,再运行客户端,第一次就很好玩。
核心提示:优雅地退出和调用服务器 close() 方法
这个书里建议是用一个 try-except 语句中的 except 子句中,监控 EOFError 或KeyboardInterrupt异常,这样你就可以在 except 或 finally 字句中关闭服务器的套接字。
我一般是发送一个特殊的字符串过去,比如说“exit”
2.4.6 创建 UDP 服务器