1 import socket 2 3 class WebServer(): 4 5 def __init__(self): 6 ''' 7 1. Create the total socket 8 2. Monitor 9 :param self: 10 :param addr: 11 :return: 12 ''' 13 # What is the essence of creating the socket soncket function? 14 self.skt = socket.socket (socket.AF_INET, socket.SOCK_STREAM) 15 16 # Bind a port and ip address 17 addr = ('127.0.0.1',7866) 18 self.skt.bind(addr) 19 20 # Continuous listening goes to the last call to kaishi 21 self.skt.listen() 22 23 def kaishi(self): 24 #loop, in order to receive everything I send every time I have any questions? 25 while True: 26 #The browser's signal or request message is received from here and sent to in_skt and the address exists in in_addr 27 in_skt,in_addr = self.skt.accept() 28 #Instantiate the object and trigger the init function of the SocketHandler class to go to the init function 29 self.sh = SocketHandler(in_skt) 30 #Call function chuli to return the last call 31 self.sh.chuli () 32 33 class SocketHandler(object): 34 ''' 35 Handle all connections to a single incoming socket 36 ''' 37 def chuli(self): 38 ''' 39 Handling incoming socket connections 40 There are three main tasks 41 1. Receive requests and make judgments 42 2. Send feedback 43 3. Close the request 44 :return: 45 ''' 46 #call method 47 self.printHttp() 48 #Call function to parse http 49 self.parseHttp() 50 #Call the print dictionary method This request is the meaning of the request 51 self.printRequest() 52 #Calling the method router means router 53 self.router() 54 #skt is the channel, this is the end point, close and return to kaishi 55 self.skt.close() 56 #Response method server sends 57 def sendBack(self,url): 58 ''' 59 Return information in the specified format 60 :return: 61 ''' 62 #Declare an empty string outside 63 html = '' 64 #Read the contents of the url file 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 #The read content is accessed to html html is a string type 71 html = f.read() 72 #declare a dictionary of scores for traversal 73 score = {'Liu Ying': 99,'Lao Wang': 33,'Lao Li': 100} 74 #Declare an empty string of content 75 content = '' 76 #items() function The key value of the dictionary score is converted into a tuple-like form to facilitate traversal and return of a tuple-like type 77 # Traverse and traverse the key values and store them in empty k and v respectively 78 for k,v in score.items(): 79 #Format the string and pass k and v into it. What is the meaning of the variable name content_tpl, please help me? ? ? ? ? ? ? ? ? ? ? 80 content_tpl = "<h1 style = 'color:red'>{0}:{1} </h1>".format(k,v) 81 #Store the format string into the content one by one, content is a string type 82 content += content_tpl 83 #Replace the content in ly in the helloworld.html file 84 html = html.replace('ly',content) 85 #The following is what the server wants to return to the client 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 The order of #length date type can be disrupted. It doesn't matter. I have experimented and others have not tried it. Can I ask the teacher how the order here is fixed? ? ? ? ? ? 92 all = head + length + date + type + blank + html 93 #Encode all and return it to the client all is a string type 94 self.skt.send(all.encode('utf-8')) 95 # Temporarily all the work is completed and returns to the router method at 23:00 on December 1st 96 print('return success') 97 98 def router(self):#Why use this method this is a router? ? ? I know the purpose of this function but don't know why it is used like this? ? ? ? 99 #Get the value corresponding to the url in the dictionary request to form a string and translate it to a uniform resource locator 100 url = self.request.get('url','/') 101 #Judging that if the url is only '/', it will be directly passed to sendBack 102 if url == '/': 103 pass 104 else: 105 #Delete the / in front of the obtained string 106 url = url.lstrip('/') 107 #Call the method and pass the url into the method. At this time, it is the string of the file url = 'helloword.html' The url itself contains quotation marks and returns to the chuli method 108 self.sendBack(url) 109 #Construction magic method 110 def __init__(self,skt):# Pass in_skt to skt 111 #Look at what skt is and what type it is 112 print(skt,type(skt)) 113 #Assign skt to the class 114 self.skt = skt 115 #declare a list with string elements 116 self.http = [] 117 #call function go to function 118 self.getAllInfo () 119 #All message information is stored in the list http and then declare a dictionary to store the parsed content and return to the kaishi method 120 self.request = dict() 121 122 def parseHttp(self): 123 # Traverse the elements in the list http where the line is a local variable and has nothing to do with the line in other methods 124 for line in self.http: 125 #The string line is cut according to the specified (: space) to form a list of cut elements 126 items2 = line.split(': ') 127 #Determine the number of elements after forming a list 128 if len(items2) >= 2: 129 #If the cut list has only two elements, the first element is used as the key, and the second element is used as the value to form a pair of key values and add them to the dictionary 130 self.request[items2[0]] = items2[1] 131 continue 132 #The string line is cut according to the specified character (space) to form a list of cut elements 133 items = line.split(' ') 134 #['GET', '/helloworld.html', 'HTTP/1.1'] <class 'list'> This is the print result 135 #print(items,type(items)) 136 # Determine the number of elements after forming a list 137 if len(items) == 3: 138 #Attach his name to each element in the list and form a key-value pair and add it to the dictionary to store the dictionary and return to the chuli method 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 # Traverse the key-value pairs in the dictionary 146 for k in self.request.keys(): 147 #Print the key-value pair in the dictionary and return the chuli method 148 print(k,self.request[k]) 149 150 def getAllInfo (self): 151 ''' 152 Get all the information passed to http at one time 153 :return: 154 ''' 155 #call function 156 self.getAllLines () 157 #call that there is nothing in the body pass and return to the init magic method 158 self.getBody() 159 160 def getLine(self): 161 #The first byte read is assigned to a 162 a = self.skt.recv(1) 163 #Print a and the type of a is b'' byte b'G' <class 'bytes'> 164 #print(a,type(a)) 165 #Declare an integer b function is to re-assign it, should it be declared that b = b'' 166 #b = b'' 167 b = 0 168 #0 <class 'int'> this is the result 169 #print(b,type(b)) 170 #declare a null byte 171 rst = b'' 172 #Enter the loop as long as the two are satisfied at the same time. The purpose is to read the bytes in the message one by one and assign them to b, and then add b to rst 173 while b != b'\r' and a != b'\n': 174 #a The first byte received is assigned to the byte type of ba, and the byte type assigned to bb is changed from an integer to a byte type 175 b = a 176 #After the assignment, a continues to receive the next byte, but I still don't understand how this is implemented 177 a = self.skt.recv(1) 178 #Add the b byte to the byte rst until the while condition is not met to jump out of the loop 179 rst += b 180 #Determine whether the content in the byte rst is only \r 181 if rst == b'\r': 182 #Only \r returns an empty string returns getAllLines 183 return '' 184 else: 185 #If there is something in it, decode it and return getAllLines 186 return rst.decode('utf-8').strip('\r') 187 188 def getAllLines (self): 189 ''' 190 Read everything before the empty line passed in by http line by line 191 read value into self.http 192 The self.http structure is a list that stores str 193 :return: 194 ''' 195 #Call the function and save the return value to the line 196 line = self.getLine() 197 #If line is not empty, enter the loop, if it is empty, jump out of the loop 198 while line != '': 199 #Add the non-empty line to the list http 200 self.http.append(line) 201 #Continue to call the function and return the value until the line is an empty string, then jump out of the loop and return to getAllInfo 202 line = self.getLine() 203 204 def getBody(self): 205 ''' 206 Read the entity content of http 207 :return: 208 ''' 209 pass 210 211 def printHttp(self): 212 ''' 213 Print all incoming Http protocols at once 214 :return: 215 ''' 216 #Print list http return chuli 217 print(self.http) 218 219 #Determine whether it is running on the current page this is the beginning of this program 220 if __name__ == '__main__': 221 #Instantiate the object The next step is to trigger the init magic method 222 ws = WebServer() 223 #Call the function back to the start function 224 ws.kaishi() 225 #End program