zoukankan      html  css  js  c++  java
  • 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
    '
     87         date = 'Date: 2017.12.1
    '
     88         type = 'Content-type: text/html
    '
     89         length = 'Content-Length: ' + str(len(html)) + '
    '
     90         blank = '
    '
     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'
    ' and a != b'
    ':
    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中的内容是不是只有
    
    181         if rst == b'
    ':
    182             #只有
     返回空字符串   返回getAllLines
    183             return ''
    184         else:
    185             #如果里面有东西将其解码后  返回getAllLines
    186             return rst.decode('utf-8').strip('
    ')
    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     #结束程序
  • 相关阅读:
    Go 语言简介(下)— 特性
    Array.length vs Array.prototype.length
    【转】javascript Object使用Array的方法
    【转】大话程序猿眼里的高并发架构
    【转】The magic behind array length property
    【转】Build Your own Simplified AngularJS in 200 Lines of JavaScript
    【转】在 2016 年做 PHP 开发是一种什么样的体验?(一)
    【转】大话程序猿眼里的高并发
    php通过token验证表单重复提交
    windows 杀进程软件
  • 原文地址:https://www.cnblogs.com/zhangboblogs/p/8018807.html
Copyright © 2011-2022 走看看