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     #结束程序
  • 相关阅读:
    Linux之Permission denied没有权限
    soapUI的简单使用(webservice接口功能测试)
    jmeter学习(二),如何安装jmeter?
    loadrunner检查点设置失败,日志中SaveCount无法被正常统计出来
    loadrunner破解出现“license security violation,Operation is not allowed”的错误提示
    安装LoadRunner11报缺少vc2005_sp1_with_atl_fix_redist的错误
    IOS测试,打不开要测试的APP怎么办?设置信任
    Jmeter的好搭档Badboy的安装与简单使用
    映射网络驱动器会自动断开的解决方法
    oracle中如何修改用户名和密码
  • 原文地址:https://www.cnblogs.com/zhangboblogs/p/8018807.html
Copyright © 2011-2022 走看看