人生苦短,我用Python08:网络编程
目录:
单例模式
单例模式的例是指实例(对象)
实现方式为静态方法+静态字段
在所有的实例中封装的内容相同的时候使用单例模式
模拟连接池
class ConnectionPool:
__instance = None
def __init__(self, port, host, name, passwd):
self.port = port
self.host = host
self.name = name
self.passwd = passwd
@staticmethod
def get_instance():
if ConnectionPool.__instance:
return ConnectionPool.__instance
else:
ConnectionPool.__instance = ConnectionPool()
return ConnectionPool.__instance
def get_connection(self):
import random
r = random.randrange(1, 11)
return r
pool = ConnectionPool.get_instance()
for i in range(10):
conn = pool
网络编程
socket是提供TCP/IP协议进行封装和反解传递数据的一个工具,也称为套接字,用于描述IP地址和端口,应用程序通过其发送和应答请求。
socket起源于Unix/Linux的基本哲学,一切事物皆文件
简单的HTTP服务
# -*- coding: utf-8 -*-
from wsgiref.simple_server import make_server
def RunServer(environ, start_response):
start_response(status='200 OK', headers=[('Content-Type', 'text/html')])
url = environ['PATH_INFO']
return "why"
if __name__ == "__main__":
httpd = make_server("", 8000, RunServer)
print("Serving HTTP on port 8000......")
httpd.serve_forever()
访问127.0.0.1:8000
png0801
# -*- coding: utf-8 -*-
from wsgiref.simple_server import make_server
def RunServer(environ, start_response):
start_response(status='200 OK', headers=[('Content-Type', 'text/html')])
url = environ['PATH_INFO']
if url.endswith("index"):
return "index"
elif url.endswith("blog"):
return "why"
else:
return "404"
if __name__ == "__main__":
httpd = make_server("", 8000, RunServer)
print("Serving HTTP on port 8000......")
httpd.serve_forever()
png0802 png0803 png0804 根据不同url会有不同的返回值
httpd.serve_forever()的内部实质也为while循环
server端和client端进行连接
server
# -*- coding: utf-8 -*-
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',9999, ))
sk.listen(5) # socket允许接受的最大连接数
# 以上为接收客户端请求
# 连接客户端地址信息
while True:
conn, address = sk.accept() # accept会堵塞进程
print(conn, address)
client
# -*- conding: utf-8 -*-
import socket
obj = socket.socket()
obj.connect(('127.0.0.1', 9999,))
obj.close()
执行结果(先启动server端,然后执行多次client端连接操作)
(<socket._socketobject object at 0x00000000024EC798>, ('127.0.0.1', 53464))
(<socket._socketobject object at 0x00000000024EC800>, ('127.0.0.1', 53465))
(<socket._socketobject object at 0x00000000024EC798>, ('127.0.0.1', 53466))
(<socket._socketobject object at 0x00000000024EC800>, ('127.0.0.1', 53468))
(<socket._socketobject object at 0x00000000024EC798>, ('127.0.0.1', 53469))
(<socket._socketobject object at 0x00000000024EC800>, ('127.0.0.1', 53470))
server端对client端连接进行应答,client接收应答
对于python2
server端
# -*- coding: utf-8 -*-
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',9999, ))
sk.listen(5) # socket允许接受的最大连接数
# 以上为接收客户端请求
# 连接客户端地址信息
while True:
conn, address = sk.accept() # accept会堵塞进程
conn.sendall("Connect server success!") # 对连接进行应答
print(conn, address)
client端
# -*- conding: utf-8 -*-
import socket
obj = socket.socket()
obj.connect(('127.0.0.1', 9999,))
a = obj.recv(1024)
print a
obj.close()
执行结果
Connect server success!
另外对于
对于python3
其实主要的差别还是在于python2对于传输数据,直接就转换成byte,而对于python3,要通过byte方法进行转化,接收的时候也需要将字节转化成字符串。只需要对这个点进行修改即可
server端
conn.sendall(bytes("Connect server success!", encoding = "utf-8"))
client端
ret_str = str(a, encoding = "utf-8")
print(ret_str)
server端对client端的输入进行处理和应答
对于python2
server端
# -*- coding: utf-8 -*-
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',9999, ))
sk.listen(5) # socket允许接受的最大连接数
# 以上为接收客户端请求
# 连接客户端地址信息
while True:
conn, address = sk.accept() # accept会堵塞进程
conn.sendall("Connect server success!") # 对连接进行应答
# conn.sendall(bytes("Connect server success!", encoding = "utf-8"))
while True:
ret_str = conn.recv(1024)
# ret_bytes = conn.recv(1024)
# ret_str = str(ret_bytes, encoding = "utf-8")
if ret_str == "q": # 如果接收到q,退出循环
break
else: # 进行返回
conn.sendall(ret_str + " why get")
# conn.sendall(bytes(ret_str + " why get", encoding = "utf-8"))
client
# -*- conding: utf-8 -*-
import socket
obj = socket.socket()
obj.connect(('127.0.0.1', 9999,))
ret_str = obj.recv(1024)
# ret_bytes = obj.recv(1024)
# ret_str = str(ret_bytes, encoding = "utf-8")
print ret_str
while True:
inp = raw_input("sendmsg:")
# inp = input("sendmsg:")
if inp == "q":
obj.sendall(inp)
# obj.sendall(bytes(inp, encoding = "utf-8"))
break
else:
obj.sendall(inp)
# obj.sendall(bytes(inp, encoding = "utf-8"))
ret_str = obj.recv(1024)
# ret_bytes = obj.recv(1024)
# ret_str = str(ret_bytes, encoding = "utf-8")
print(ret_str)
obj.close()
执行结果
Connect server success!
sendmsg:1
1 why get
sendmsg:2
2 why get
sendmsg:q
对于python3
server端
# -*- coding: utf-8 -*-
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',9999, ))
sk.listen(5) # socket允许接受的最大连接数
# 以上为接收客户端请求
# 连接客户端地址信息
while True:
conn, address = sk.accept() # accept会堵塞进程
conn.sendall("Connect server success!") # 对连接进行应答
# conn.sendall(bytes("Connect server success!", encoding = "utf-8"))
while True:
ret_str = conn.recv(1024)
# ret_bytes = conn.recv(1024)
# ret_str = str(ret_bytes, encoding = "utf-8")
if ret_str == "q": # 如果接收到q,退出循环
break
else: # 进行返回
conn.sendall(ret_str + " why get")
# conn.sendall(bytes(ret_str + " why get", encoding = "utf-8"))
client端
模拟FTP
server端
# -*- coding=utf-8 -*-
import socket
sk = socket.socket()
sk.bind(('127.0.0.1', 50070,))
sk.listen(5)
while True:
conn, address = sk.accept()
conn.sendall("welcome use why ftp")
# 需要传输文件大小
file_size = conn.recv(1024)
print(file_size)
total_size = int(file_size)
# 需要传递
has_recv = 0
f = open("text.txt","wb")
while True:
if total_size == has_recv:
break
data = conn.recv(1024)
f.write(data)
has_recv += len(data)
f.close()
client端
# -*- coding=utf-8 -*-
import socket
import os
obj = socket.socket()
obj.connect(("127.0.0.1", 50070,))
ret = obj.recv(1024)
print ret
# 发送数据长度
size = os.stat("httpd.py").st_size
obj.sendall(str(size)) # 获取的长度为int类型,需要转化为str
# 发送数据
with open("httpd.py","rb") as f:
for line in f:
obj.sendall(line)
obj.close()
执行结果
- 在本地生成了text.txt文件,内容与httpd.py内容一样。
- 不过也会出现失败的情况,主要原因是粘包的问题导致的
粘包问题的产生主要是因为发送文件长度和数据同时写入文件缓冲区进行发送,导致的