网络编程

  1):网络编程是什么意思,网络编程指的是不同机器之间通过网编相互发信息,我们常用的“QQ”,“微信”,“邮箱” 都个网编编程的应用;

  网编编程在技术上还有另一个叫法叫“进程间通信”,进程间通信这个名字能更好体现技术的内涵,说白了就是一个进程给另一个进程发

  信息;

  2):网络编程中的两个重要的角色,“服务端”,“客户端” 从技术上来讲“服务端”是被动的,它监听在某个“套结字(socket)”上,被动的

  等待“客户端”的连接;也就是说连接是由“客户端”主动发起的,所以“客户端”是主动的。

  3):主动&被动对应着两套不同的行为,对于被动的“服务端”来说它有三个技术上的步骤要做 “第一步:bind”,“第二步:listen”,“

  三步 accept” 这三步是基本的“套路”不要问我为什么,我也想知道;不过总的来说前两步叫“监听”,第三步叫“接收一个客户端连接

  对于“客户端”它的套路就比较少了只有一步:“唯一一步:connect” 成功后就能与服务器之间有进行信息的收发了。

从最低层的socket来实现一个翻译功能

  我在这要实现的“翻译”功能比较“牛逼”,总的来说是这样的;客户端向服务器发送一串小写字母,服务器端把小写“翻译”成大写后返回

  我的服务器主机的IP是“172.16.192.100”

  1): 服务端代码

#! /usr/bin/env python3

import socket

if __name__ == "__main__":
#定义一个服务端的tcp套节字
with socket.socket(socket.AF_INET,socket.SOCK_STREAM) as s_sock:
s_host = ('172.16.192.100',9999)
s_sock.bind(s_host) # 第一步:bind
s_sock.listen(5) # 第二步:listen
print("服务端启动完成 监听在 {0}".format(s_host))
while True:
c_sock,c_addr = s_sock.accept() # 第三步:接收客户端连接
print("收到来自 {0} 的连接请求".format(c_addr))
c_data = c_sock.recv(1024) # 读取客户端发来的数据
c_str = str(c_data,"utf-8") # 由字节序列转码成utf-8字符串
print("收到来自 {0} 的信息 '{1}' ".format(c_addr,c_str))
c_sock.sendall( bytes(c_str.upper(),"utf-8")) # 翻译成大写发送到客户端

  2): 客户端代码

import socket
from datetime import datetime if __name__ == "__main__":
data = ' '.join(sys.argv[1:])
with socket.socket(socket.AF_INET,socket.SOCK_STREAM) as sock:
sock.connect(('172.16.192.100',9999))
print("client {0} 发送 {1}".format(datetime.now(),data))
sock.sendall(bytes(data,"utf-8")) received_data = sock.recv(1024)
print("client {0} 收到 {1}".format(datetime.now(),received_data))

  3): 服务端的运行情况

python3 server.py
服务端启动完成 监听在 ('172.16.192.100', 9999)
收到来自 ('172.16.192.1', 52160) 的连接请求
收到来自 ('172.16.192.1', 52160) 的信息 'Hello world 123'

  4): 客户端的运行情况

python3 client.py Hello world 123
client 2018-09-19 16:42:46.973864 发送 Hello world 123
client 2018-09-19 16:42:46.974519 收到 b'HELLO WORLD 123'

Python对网络编程做了什么

  从上面的内容可以看出“服务端”是有它的固定套路的,Python把这些通用的“套路”抽象了来了,如果我们使用python写上面的那种“服务端”

  &“客户端”的程序的话就大的方便了。

  服务端直接这样写就行了:

import socketserver

class UpHander(socketserver.BaseRequestHandler):
def handle(self):
"""
self.request 引用的是与客户端通信用的socket对象
"""
data = self.request.recv(1024) # 接收1024个字节
print("接收到来自 {0} 的信息 {1}".format(self.client_address,str(data)))
self.request.sendall(data.upper()) # 把接收到的数据变成大写再发出去 if __name__ == "__main__":
server_ip = ('172.16.192.100',9999) # 定义服务端监听的ip与端口
with socketserver.TCPServer(server_ip,UpHander) as server:
server.serve_forever()

  通过“重写”socketserver.BaseRequestHandler.handle 方法来实现我们要的功能,也就是说我们不要太在意网络编程的技术细节了;注意

  了上面的这个实现是“串行”的,也就是说server端只有一个进程来做处理,如果是要实现一个并行处理的服务端的话也是分分钟的事

多线程版本的服务端编程

  1): 服务端代码

#! /usr/bin/env python3

"""
用python标准库实现一个简单的c/s架构的服务
""" import socketserver
import socket
import time
import threading class UpHander(socketserver.BaseRequestHandler):
def handle(self):
"""
self.request 引用的是与客户端通信用的socket对象
"""
data = self.request.recv(1024) # 接收1024个字节
cur_thread = threading.current_thread()
print("服务端线程号 {0} 接收到来自 {1} 的信息 {2}".format(cur_thread.name,self.client_address,str(data)))
time.sleep(5)
self.request.sendall(data.upper()) # 把接收到的数据变成大写再发出去 class MultiThreadTcpServer(socketserver.ThreadingMixIn,socketserver.TCPServer):
pass if __name__ == "__main__":
with MultiThreadTcpServer(('172.16.192.100',9999),UpHander) as s_sock:
s_thread = threading.Thread(target=s_sock.serve_forever)
s_thread.daemon=True
s_thread.start()
print("多线程版本的服务端已经启动...")
while True:
time.sleep(10) # 使服务端永不退出

  2): 客户端代码

import socket
from datetime import datetime if __name__ == "__main__":
data = ' '.join(sys.argv[1:])
with socket.socket(socket.AF_INET,socket.SOCK_STREAM) as sock:
sock.connect(('172.16.192.100',9999))
print("client {0} 发送 {1}".format(datetime.now(),data))
sock.sendall(bytes(data,"utf-8")) received_data = sock.recv(1024)
print("client {0} 收到 {1}".format(datetime.now(),received_data))

  开启两个客户端观察效果

1:
python3 client.py Hello world 123
client 2018-09-19 17:47:38.084209 发送 Hello world 123
client 2018-09-19 17:47:43.091790 收到 b'HELLO WORLD 123' 2: python3 client.py Hello world
client 2018-09-19 17:47:38.803440 发送 Hello world
client 2018-09-19 17:47:43.811177 收到 b'HELLO WORLD'

  由时间上可以看出来请求是并行的

总结

  可以看出用socketserver模块来做“服务器”,“客户端”的编程是非常方便的

学习交流

-----------------------------http://www.sqlpy.com-------------------------------------------------

-----------------------------http://www.sqlpy.com-------------------------------------------------

Python 实现进程间通信(网络编程)的更多相关文章

  1. python高级之网络编程

    python高级之网络编程 本节内容 网络通信概念 socket编程 socket模块一些方法 聊天socket实现 远程执行命令及上传文件 socketserver及其源码分析 1.网络通信概念 说 ...

  2. 第六篇:python高级之网络编程

    python高级之网络编程   python高级之网络编程 本节内容 网络通信概念 socket编程 socket模块一些方法 聊天socket实现 远程执行命令及上传文件 socketserver及 ...

  3. Python之路 - 网络编程之粘包

    Python之路 - 网络编程之粘包 粘包

  4. Python之路 - 网络编程初识

    Python之路 - 网络编程初识 前言

  5. python面试题——网络编程和并发

    1.简述 OSI 七层协议. 物理层(电信号.比特流) 基于电器特性发送高低电压(电信号) RJ45.IEEE802.3 数据链路层(数据帧) 定义了电信号的分组方式,分组方式后来形成了统一的标准,即 ...

  6. python之Socket网络编程

    什么是网络? 网络是由节点和连线构成,表示诸多对象及其相互联系.在数学上,网络是一种图,一般认为专指加权图.网络除了数学定义外,还有具体的物理含义,即网络是从某种相同类型的实际问题中抽象出来的模型.在 ...

  7. 【循序渐进学Python】15.网络编程

    Python 内置封装了很多常见的网络协议的库,因此Python成为了一个强大的网络编程工具,这里是对Python的网络方面编程的一个简单描述. 1. 常用的网络设计模块 在标准库中有很多网络设计相关 ...

  8. python 之socket 网络编程

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

  9. python:socket网络编程

    Socket 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket, 又称为“套接字”. 模块 import socket 创建套接字 socket.socket( ...

随机推荐

  1. Mysql的union

    我同事写了一条Sql语句,当时没看明白,下面晒出来: SELECT SUM(new_cart) AS ipv, AS iuv FROM tablename WHERE id = 5 ) as t OR ...

  2. mahout做推荐时uid,pid为string类型

    很幸运找到这篇文件,解了燃眉之急. http://blog.csdn.net/pan12jian/article/details/38703569 mahout做推荐的输入只能是long类型,但在某些 ...

  3. 浅谈Spring的PropertyPlaceholderConfigurer

    大型项目中,我们往往会对我们的系统的配置信息进行统一管理,一般做法是将配置信息配置与一个cfg.properties的文件中,然后在我们系统初始化的时候,系统自动读取cfg.properties配置文 ...

  4. P2093 零件分组【贪心算法练习题】

    题目链接: http://codevs.cn/problem/4888/ https://www.luogu.org/problem/show?pid=2093 题目描述 某工厂生产一批棍状零件,每个 ...

  5. Fiddler拦截并修改移动端请求

    bpu url 由于测试电商平台APP,需测试购买,但又限于公司一提到钱,就给种不给力,所以想到使用Fiddler拦截消息,修改一个虚拟商品ID,虚拟商品价格为0.01元,方便以后测试. 1.打开Fi ...

  6. 生命周期方法调用,以及在onStop()方法中处理草稿信息

    生命周期方法调用顺序 1. 从会话列表界面跳转到信息列表界面. 07-17 17:29:18.718: I/txrjsms(19370): MessageListActivity.onCreate 0 ...

  7. tomcat启动dubbo报IO异常

    严重: Servlet [springDispatcher] in web application [/dubbo-service] threw load() exception java.io.IO ...

  8. 修改谷歌云google cloud engine VM root账户的密码和允许远程ssh登录

      Figured it out. The VM's in cloud engine don't come with a root password setup by default so you'l ...

  9. UCCI协议[转]

    象棋百科全书 中国象棋电脑应用规范(五) 中国象棋通用引擎协议 版本:3.0 象棋百科全书网 (webmaster@xqbase.com) 2004年12月初稿,2007年11月修订 一.概述 中国象 ...

  10. Ubuntu Linux 环境变量PATH设置

    前俩天编译linux下rar解压软件的时候说找不到  /usr/local/linux 路径,在设定path变量的时候,忽然就想看看,path最原始的变量值是多少....(在环境变量文件中保存.... ...