HTTP socket网络通信
Posted zxf123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HTTP socket网络通信相关的知识,希望对你有一定的参考价值。
1 import socket 2 3 class WebServer(): 4 5 def __init__(self): 6 ‘‘‘ 7 1.创建总的socket 8 2.监听 9 :param self: 10 :param addr: 11 :return: 12 ‘‘‘ 13 # 创建socket soncket函数到底是什么 本质是干嘛的? 14 self.skt = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 15 16 # 绑定一个端口和ip地址 17 addr = (‘127.0.0.1‘,7866) 18 self.skt.bind(addr) 19 20 # 持续的监听 转到最后调用kaishi 21 self.skt.listen() 22 23 def kaishi(self): 24 #循环,为了让每次发送过来的东西都能接收到 我有疑问? 25 while True: 26 #浏览器的信号或者请求报文从这里开始接收 传到in_skt 还有地址存在in_addr 27 in_skt,in_addr = self.skt.accept() 28 #实例化对象以及触发SocketHandler类的init函数 转到init函数 29 self.sh = SocketHandler(in_skt) 30 #调用函数chuli 返回 最后的调用 31 self.sh.chuli() 32 33 class SocketHandler(object): 34 ‘‘‘ 35 处理所有单个传入socket的连接 36 ‘‘‘ 37 def chuli(self): 38 ‘‘‘ 39 处理传入的socket连接 40 主要有三个任务 41 1.接收请求并作出判断 42 2.发送反馈 43 3.关闭请求 44 :return: 45 ‘‘‘ 46 #调用方法 47 self.printHttp() 48 #调用函数 解析http 49 self.parseHttp() 50 #调用打印字典方法 这个request是请求的意思 51 self.printRequest() 52 #调用方法 router是路由器的意思 53 self.router() 54 #skt 就是通道,这是终点,关闭 返回kaishi 55 self.skt.close() 56 #响应方法 服务器发送 57 def sendBack(self,url): 58 ‘‘‘ 59 按照指定格式返回信息 60 :return: 61 ‘‘‘ 62 #在外面声明一个空的字符串 63 html = ‘‘ 64 #读取url文件里面的内容 65 if url == ‘/‘: 66 with open(‘./index.html‘,‘r‘) as fp: 67 html = fp.read() 68 else: 69 with open(url,‘r‘) as f: 70 #读取的内容存取到html html是字符串类型 71 html = f.read() 72 #声明一个分数的字典 用于遍历 73 score = {‘刘应‘ : 99,‘老王‘ : 33,‘老李‘ : 100} 74 #声明一个内容的空字符串 75 content = ‘‘ 76 #items()的作用 字典score的键值转化成类似元组的形式方便遍历 返回类似元组的类型 77 #遍历 将键值分别遍历存放到空k,v中 78 for k,v in score.items(): 79 #字符串格式化 并将k,v传入进去 content_tpl这个变量命名的意义是什么,求大神帮忙??????????? 80 content_tpl = "<h1 style = ‘color:red‘>{0}:{1} </h1>".format(k,v) 81 #将格式化字符串一个一个存入内容当中 content是字符串类型 82 content += content_tpl 83 #将helloworld.html文件中的ly中content替换 84 html = html.replace(‘ly‘,content) 85 #以下是服务器要返回给客户端的内容 86 head = ‘HTTP/1.1 200 OK\r\n‘ 87 date = ‘Date: 2017.12.1\r\n‘ 88 type = ‘Content-type: text/html\r\n‘ 89 length = ‘Content-Length: ‘ + str(len(html)) + ‘\r\n‘ 90 blank = ‘\r\n‘ 91 #length date type 之间的顺序可以打乱没有关系 实验过 其他没有试过 可以问一下老师这里的顺序是怎么样的 是固定的吗?????? 92 all = head + length + date + type + blank + html 93 #将all编码后返回给客户端 all是字符串类型 94 self.skt.send(all.encode(‘utf-8‘)) 95 # 暂时所有的工作完成 12月1号晚上23点 返回router方法 96 print(‘返回成功‘) 97 98 def router(self):#为什么要用这个方法 这是一个路由器??? 我知道这个函数的目的 但是不知道为什么这样去用???? 99 #获取字典request中的url对应的值 形成一个字符串 翻译过来是统一资源定位符 100 url = self.request.get(‘url‘,‘/‘) 101 #判断url如果只是‘/’则直接传给sendBack 102 if url == ‘/‘: 103 pass 104 else: 105 #将得到的字符串前面的/删掉 106 url = url.lstrip(‘/‘) 107 #调用方法 并将url传入方法 这个时候是文件的字符串 url = ‘helloword.html’ url本身包含引号 返回chuli方法 108 self.sendBack(url) 109 #构造魔术方法 110 def __init__(self,skt):# 将in_skt传给skt 111 #看一下skt到底是什么什么东西 以及类型 112 print(skt,type(skt)) 113 #将skt赋值到类中 114 self.skt = skt 115 #声明一个含有字符串元素的列表 116 self.http = [] 117 #调用函数 转到函数 118 self.getAllInfo() 119 #所有的报文信息存到列表http以后 声明一个字典用于存放解析之后的内容 回到kaishi方法 120 self.request = dict() 121 122 def parseHttp(self): 123 #遍历列表http中的元素 这里的line是局部变量 与其他方法中的line无关 124 for line in self.http: 125 #将字符串line按照指定的(:空格)进行切割操作 切割后的元素组成列表 126 items2 = line.split(‘: ‘) 127 #判断形成列表后的元素个数 128 if len(items2) >= 2: 129 #如果切割后的列表只有两个元素,则第一个元素做键,第二个元素做值 形成一对键值 加入到字典中 130 self.request[items2[0]] = items2[1] 131 continue 132 #将字符串line按照指定的字符(空格)进行切割操作 切割后的元素组成列表 133 items = line.split(‘ ‘) 134 #[‘GET‘, ‘/helloworld.html‘, ‘HTTP/1.1‘] <class ‘list‘> 这是打印结果 135 #print(items,type(items)) 136 # 判断形成列表后的元素个数 137 if len(items) == 3: 138 #给列表中的每个元素附上他的名称 并组成键值对加到字典当中去 字典存入完成 返回chuli方法 139 self.request[‘method‘] = items[0] 140 self.request[‘url‘] = items[1] 141 self.request[‘version‘] = items[2] 142 continue 143 144 def printRequest(self): 145 #遍历字典中的键值对 146 for k in self.request.keys(): 147 #打印字典中的键值对 返回chuli方法 148 print(k,self.request[k]) 149 150 def getAllInfo(self): 151 ‘‘‘ 152 获取一次传入http的所有信息 153 :return: 154 ‘‘‘ 155 #调用函数 156 self.getAllLines() 157 #调用body里面 里面没有东西 pass 回到init魔术方法 158 self.getBody() 159 160 def getLine(self): 161 #读到的第一个字节赋值给a 162 a = self.skt.recv(1) 163 #打印a 和a的类型是 b‘’ 字节 b‘G‘ <class ‘bytes‘> 164 #print(a,type(a)) 165 #声明一个 整型b 作用是从新给他赋值 是不是应该声明的是 b = b‘‘ 166 #b = b‘‘ 167 b = 0 168 #0 <class ‘int‘> 这是结果 169 #print(b,type(b)) 170 #声明一个空字节 171 rst = b‘‘ 172 #只要两个同时满足就进入循环 目的是为了一个一个读取报文中的字节 并赋值给b 再将b 加到rst中 173 while b != b‘\r‘ and a != b‘\n‘: 174 #a接收的第一个字节赋值给b a的字节类型赋值给b b由整型变成了字节类型 175 b = a 176 #赋值完之后a继续接收下一个字节 但是这是如何实现的 我还是有点不懂 177 a = self.skt.recv(1) 178 #将b字节加到字节rst中 直到不满足while条件 跳出循环 179 rst += b 180 #判断字节rst中的内容是不是只有\r 181 if rst == b‘\r‘: 182 #只有\r 返回空字符串 返回getAllLines 183 return ‘‘ 184 else: 185 #如果里面有东西将其解码后 返回getAllLines 186 return rst.decode(‘utf-8‘).strip(‘\r‘) 187 188 def getAllLines(self): 189 ‘‘‘ 190 按行读取http传入的空行以前的所有内容 191 读取值放入self.http 192 self.http结构为存储str的list 193 :return: 194 ‘‘‘ 195 #调用函数 并将返回值存到line 196 line = self.getLine() 197 #如果line不为空则进入循环 如果为空则跳出循环 198 while line != ‘‘: 199 #将不为空的line加到列表http中 200 self.http.append(line) 201 #继续调用函数,并返回值,直到line为空字符串则跳出循环 回到getAllInfo 202 line = self.getLine() 203 204 def getBody(self): 205 ‘‘‘ 206 读取http的实体内容 207 :return: 208 ‘‘‘ 209 pass 210 211 def printHttp(self): 212 ‘‘‘ 213 打印一次传入的所有Http协议 214 :return: 215 ‘‘‘ 216 #打印列表http 返回chuli 217 print(self.http) 218 219 #判断是否在当前页面运行 这是此程序的开始 220 if __name__ == ‘__main__‘: 221 #实例化对象 下一步是触发init魔术方法 222 ws = WebServer() 223 #调用函数 回到开始函数 224 ws.kaishi() 225 #结束程序
以上是关于HTTP socket网络通信的主要内容,如果未能解决你的问题,请参考以下文章