HTTP socket网络通信
import socket
class WebServer():
def __init__(self):
'''
1.创建总的socket
2.监听
:param self:
:param addr:
:return:
'''
# 创建socket soncket函数到底是什么 本质是干嘛的?
self.skt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定一个端口和ip地址
addr = ('127.0.0.1',7866)
self.skt.bind(addr)
# 持续的监听 转到最后调用kaishi
self.skt.listen()
def kaishi(self):
#循环,为了让每次发送过来的东西都能接收到 我有疑问?
while True:
#浏览器的信号或者请求报文从这里开始接收 传到in_skt 还有地址存在in_addr
in_skt,in_addr = self.skt.accept()
#实例化对象以及触发SocketHandler类的init函数 转到init函数
self.sh = SocketHandler(in_skt)
#调用函数chuli 返回 最后的调用
self.sh.chuli()
class SocketHandler(object):
'''
处理所有单个传入socket的连接
'''
def chuli(self):
'''
处理传入的socket连接
主要有三个任务
1.接收请求并作出判断
2.发送反馈
3.关闭请求
:return:
'''
#调用方法
self.printHttp()
#调用函数 解析http
self.parseHttp()
#调用打印字典方法 这个request是请求的意思
self.printRequest()
#调用方法 router是路由器的意思
self.router()
#skt 就是通道,这是终点,关闭 返回kaishi
self.skt.close()
#响应方法 服务器发送
def sendBack(self,url):
'''
按照指定格式返回信息
:return:
'''
#在外面声明一个空的字符串
html = ''
#读取url文件里面的内容
if url == '/':
with open('./index.html','r') as fp:
html = fp.read()
else:
with open(url,'r') as f:
#读取的内容存取到html html是字符串类型
html = f.read()
#声明一个分数的字典 用于遍历
score = {'刘应' : 99,'老王' : 33,'老李' : 100}
#声明一个内容的空字符串
content = ''
#items()的作用 字典score的键值转化成类似元组的形式方便遍历 返回类似元组的类型
#遍历 将键值分别遍历存放到空k,v中
for k,v in score.items():
#字符串格式化 并将k,v传入进去 content_tpl这个变量命名的意义是什么,求大神帮忙???????????
content_tpl = "<h1 style = 'color:red'>{0}:{1} </h1>".format(k,v)
#将格式化字符串一个一个存入内容当中 content是字符串类型
content += content_tpl
#将helloworld.html文件中的ly中content替换
html = html.replace('ly',content)
#以下是服务器要返回给客户端的内容
head = 'HTTP/1.1 200 OK\r\n'
date = 'Date: 2017.12.1\r\n'
type = 'Content-type: text/html\r\n'
length = 'Content-Length: ' + str(len(html)) + '\r\n'
blank = '\r\n'
#length date type 之间的顺序可以打乱没有关系 实验过 其他没有试过 可以问一下老师这里的顺序是怎么样的 是固定的吗??????
all = head + length + date + type + blank + html
#将all编码后返回给客户端 all是字符串类型
self.skt.send(all.encode('utf-8'))
# 暂时所有的工作完成 12月1号晚上23点 返回router方法
print('返回成功')
def router(self):#为什么要用这个方法 这是一个路由器??? 我知道这个函数的目的 但是不知道为什么这样去用????
#获取字典request中的url对应的值 形成一个字符串 翻译过来是统一资源定位符
url = self.request.get('url','/')
#判断url如果只是‘/’则直接传给sendBack
if url == '/':
pass
else:
#将得到的字符串前面的/删掉
url = url.lstrip('/')
#调用方法 并将url传入方法 这个时候是文件的字符串 url = ‘helloword.html’ url本身包含引号 返回chuli方法
self.sendBack(url)
#构造魔术方法
def __init__(self,skt):# 将in_skt传给skt
#看一下skt到底是什么什么东西 以及类型
print(skt,type(skt))
#将skt赋值到类中
self.skt = skt
#声明一个含有字符串元素的列表
self.http = []
#调用函数 转到函数
self.getAllInfo()
#所有的报文信息存到列表http以后 声明一个字典用于存放解析之后的内容 回到kaishi方法
self.request = dict()
def parseHttp(self):
#遍历列表http中的元素 这里的line是局部变量 与其他方法中的line无关
for line in self.http:
#将字符串line按照指定的(:空格)进行切割操作 切割后的元素组成列表
items2 = line.split(': ')
#判断形成列表后的元素个数
if len(items2) >= 2:
#如果切割后的列表只有两个元素,则第一个元素做键,第二个元素做值 形成一对键值 加入到字典中
self.request[items2[0]] = items2[1]
continue
#将字符串line按照指定的字符(空格)进行切割操作 切割后的元素组成列表
items = line.split(' ')
#['GET', '/helloworld.html', 'HTTP/1.1'] <class 'list'> 这是打印结果
#print(items,type(items))
# 判断形成列表后的元素个数
if len(items) == 3:
#给列表中的每个元素附上他的名称 并组成键值对加到字典当中去 字典存入完成 返回chuli方法
self.request['method'] = items[0]
self.request['url'] = items[1]
self.request['version'] = items[2]
continue
def printRequest(self):
#遍历字典中的键值对
for k in self.request.keys():
#打印字典中的键值对 返回chuli方法
print(k,self.request[k])
def getAllInfo(self):
'''
获取一次传入http的所有信息
:return:
'''
#调用函数
self.getAllLines()
#调用body里面 里面没有东西 pass 回到init魔术方法
self.getBody()
def getLine(self):
#读到的第一个字节赋值给a
a = self.skt.recv(1)
#打印a 和a的类型是 b‘’ 字节 b'G' <class 'bytes'>
#print(a,type(a))
#声明一个 整型b 作用是从新给他赋值 是不是应该声明的是 b = b''
#b = b''
b = 0
#0 <class 'int'> 这是结果
#print(b,type(b))
#声明一个空字节
rst = b''
#只要两个同时满足就进入循环 目的是为了一个一个读取报文中的字节 并赋值给b 再将b 加到rst中
while b != b'\r' and a != b'\n':
#a接收的第一个字节赋值给b a的字节类型赋值给b b由整型变成了字节类型
b = a
#赋值完之后a继续接收下一个字节 但是这是如何实现的 我还是有点不懂
a = self.skt.recv(1)
#将b字节加到字节rst中 直到不满足while条件 跳出循环
rst += b
#判断字节rst中的内容是不是只有\r
if rst == b'\r':
#只有\r 返回空字符串 返回getAllLines
return ''
else:
#如果里面有东西将其解码后 返回getAllLines
return rst.decode('utf-8').strip('\r')
def getAllLines(self):
'''
按行读取http传入的空行以前的所有内容
读取值放入self.http
self.http结构为存储str的list
:return:
'''
#调用函数 并将返回值存到line
line = self.getLine()
#如果line不为空则进入循环 如果为空则跳出循环
while line != '':
#将不为空的line加到列表http中
self.http.append(line)
#继续调用函数,并返回值,直到line为空字符串则跳出循环 回到getAllInfo
line = self.getLine()
def getBody(self):
'''
读取http的实体内容
:return:
'''
pass
def printHttp(self):
'''
打印一次传入的所有Http协议
:return:
'''
#打印列表http 返回chuli
print(self.http)
#判断是否在当前页面运行 这是此程序的开始
if __name__ == '__main__':
#实例化对象 下一步是触发init魔术方法
ws = WebServer()
#调用函数 回到开始函数
ws.kaishi()
#结束程序
HTTP socket网络通信的更多相关文章
- Socket 网络通信
Socket 网络通信 1.OSI (Open System Interconnect Reference Model)(开放系统互联参考模型) 从下低到高 :物理层.数据链路层.网络层.传输层.会话 ...
- Socket网络通信之NIO
Socket网络通信之NIO NIO:new io ,java1.4开始推出的可非阻塞IO. java.nio 包,可解决BIO阻塞的不足 但比BIO学习.使用复杂. 可以以阻塞.非阻塞两种方式工作. ...
- Socket网络通信之BIO
Socket网络通信之BIO 如果要让两台计算机实现通信,需要的条件:ip,port,协议. 目前我们用的最多的就是TCP/IP协议和UDP协议.TCP三次握手,所以比较慢,且安全:UDP速度快,但是 ...
- socket网络通信
1.socket通常也称作"套接字",用于描述IP地址和端口.在internet上的主机一般运行了多个服务软件,同时提供几种服务,每种服务都打开一个socket,并绑定到一个端口上 ...
- java实现最基础的socket网络通信
一.网络通信基础 网络中存在很多的通信实体,每一个通信实体都有一个标识符就是IP地址. 而现实中每一个网络实体可以和多个通信程序同时进行网络通信,这就需要使用端口号进行区分. 二.java中的基本网络 ...
- Socket网络通信编程(二)
1.Netty初步 2.HelloWorld 3.Netty核心技术之(TCP拆包和粘包问题) 4.Netty核心技术之(编解码技术) 5.Netty的UDP实现 6.Netty的WebSocket实 ...
- TCP/UDP,SOCKET网络通信,C++/Java实现
趁这两天没事干,就把网络通信这一块搞一搞,C/S方面的了解一下,很重要! TCP Server/Client
- UDP SOCKET网络通信 C#
接收端 using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Thread ...
- [Socket]BSD Socket网络通信
http://blog.csdn.net/dongfengsun/article/details/4802925 文章有一些错误 #define KENTER @"/r/n" 应该 ...
- Socket网络通信之数据传递
Socket通信的步骤: 1.创建ServerSocket和Socket 2.打开连接到Socket的输入/输出流 3.按照协议对Socket进行读/写操作 4.关闭输入输出流.关闭Socket 服务 ...
随机推荐
- vmware linux root密码破解
centOS: 1.开机过程按上下箭头键,让系统不要进入到引导程序中, 2.按 'e' 进入到编辑模式 3.找到linux16开始的首行,在末尾加入'rw init=/bin/sh' (会出现修改密码 ...
- 爬虫之Js混淆&加密案例
需求: 中国空气质量在线监测分析平台是一个收录全国各大城市天气数据的网站,包括温度.湿度.PM 2.5.AQI 等数据,链接为:https://www.aqistudy.cn/html/city_de ...
- UVALive 6270 Edge Case(找规律,大数相加)
版权声明:本文为博主原创文章,未经博主同意不得转载. vasttian https://blog.csdn.net/u012860063/article/details/36905379 转载请注明出 ...
- JavaScript 正则表达式-严格匹配
创建语法 var pattern = /test/; 或者 var pattern = new RegExp("test"); 可配合使用以下三个标志 1) .i 可以使 ...
- 手写call、apply、bind
区别&联系 三者都是指定函数执行时的上下文,第一个参数都是上下文: call从第二个参数开始,后续所有的参数传递给函数执行: apply第二个参数是一个数组,传递给函数执行: bind返回一个 ...
- eclipse不小心删除文件如何恢复
转自:https://blog.csdn.net/u012129031/article/details/78791277 1.右键点击java项目工程名,选择restort from history, ...
- LOJ149 0/1分数规划
竟然没有写过分数规划的题解 考前挣扎一发板子( 二分答案k 然后0/1分数规划的方法就是 分母乘过去然后贪心解决 注意实数二分的精度 一般估计一个次数比较好不然容易出现精度比较误差[惨痛教训 就做完了 ...
- checked属性 详解
注意:当元素中有checked属性时,其值无论是什么,都是被选中状态,那怎么才能让其不被选中呢,就是用jquery或js代码实现 1.html中的checked属性.仔细研究下会发现一个很怪异的现象. ...
- js 运动框架-轻量级
具体代码如下: function move(obj,json,sv,fnEnd){ //CSS样式值 function getStyle(obj,attr){ if(obj.currentStyle) ...
- boost Shared Memory
Shared Memory Shared memory is typically the fastest form of interprocess communicatioin. It provide ...