[500lines]500行代码写web server

项目地址:https://github.com/aosabook/500lines/tree/master/web-server.作者是来自Mozilla的Greg Wilson.项目是用py2写成.下面文章中贴出的是已经转换后的能在python3.4下运行的代码,所以可能会与原先的有少许不同.

 

简单地讲,你在浏览器里输入一个网址,浏览器作为客户端会通过DNS解析域名找到对应的IP,并将这串字符串的一部分作为请求发给这个IP的服务器,服务器解析字符串,解析出你的请求内容做出相应处理,然后把一串字符串回复给浏览器,浏览器以一定格式展现这些字符串,就是你看到的网页.

由于协议是固定的HTTP协议,所以解析这一步基本上可以认为是一样的,同样的,将字符串回复给浏览器也可以认为是一样的,所以对不同的server来讲,不同的是解析出请求后的处理逻辑.正是基于这一点,python的标准库里已经给我们提供了很多好用的模块.

先看一个最简单的helloworld版的webserver

 1 import http.server
 2 
 3 class RequestHandler(http.server.BaseHTTPRequestHandler):
 4     '''Handle HTTP requests by returning a fixed 'page'.'''
 5 
 6     # Page to send back.
 7     Page = '''\
 8 <html>
 9 <body>
10 <p>Hello, web!</p>
11 </body>
12 </html>
13 '''
14 
15     # Handle a GET request.                       
16 
17     def do_GET(self):
18         self.send_response(200)
19         self.send_header("Content-type", "text/html")
20         self.send_header("Content-Length", str(len(self.Page))) 21  self.end_headers() 22 self.wfile.write(bytearray(page,"gbk")) 23 24 #---------------------------------------------------------------------- 25 26 if __name__ == '__main__': 27 serverAddress = ('', 8080) 28 server = http.server.HTTPServer(serverAddress, RequestHandler) 29 server.serve_forever()

代码非常易懂,main函数里在8080端口启动http监听.RequestHandler继承自http.server.BaseHTTPRequestHandler,这个BaseHTTPRequestHandler已经帮我们做好了解析浏览器发来的HTTP请求并调用相应的do_GET()方法的工作.所以我们要做的仅仅是在do_GET()内实现我们的逻辑就好了.

 ___________________________________________________________________________________________________________________________

现在来看看第二个例子:

 1 import http.server
 2 
 3 class RequestHandler(http.server.BaseHTTPRequestHandler):
 4     '''Respond to HTTP requests with info about the request.'''
 5 
 6     # Template for page to send back.
 7     Page = '''\
 8 <html>
 9 <body>
10 <table>
11 <tr>  <td>Header</td>         <td>Value</td>           </tr>
12 <tr>  <td>Date and time</td>  <td>%(date_time)s</td>   </tr>
13 <tr>  <td>Client host</td>    <td>%(client_host)s</td> </tr>
14 <tr>  <td>Client port</td>    <td>%(client_port)s</td> </tr>
15 <tr>  <td>Command</td>        <td>%(command)s</td>     </tr>
16 <tr>  <td>Path</td>           <td>%(path)s</td>        </tr>
17 </table>
18 </body>
19 </html>
20 '''
21 
22     # Handle a request by constructing an HTML page that echoes the
23     # request back to the caller.
24     def do_GET(self):
25         page = self.create_page()
26         self.send_page(page)
27 
28     # Create an information page to send.
29     def create_page(self): 30 values = { 31 'date_time' : self.date_time_string(), 32 'client_host' : self.client_address[0], 33 'client_port' : self.client_address[1], 34 'command' : self.command, 35 'path' : self.path 36  } 37 page = self.Page % values 38 return page 39 40 # Send the created page. 41 def send_page(self, page): 42 self.send_response(200) 43 self.send_header("Content-type", "text/html") 44 self.send_header("Content-Length", str(len(page))) 45  self.end_headers() 46 self.wfile.write(bytearray(page,"gbk")) 47 48 #---------------------------------------------------------------------- 49 50 if __name__ == '__main__': 51 serverAddress = ('', 8080) 52 server = http.server.HTTPServer(serverAddress, RequestHandler) 53 server.serve_forever()

 这个例子也很好懂,例子一里是返回一个静态的页面,这一次我们写一个页面的模板,然后将解析出来的datatime,clientaddress啥的填充到模板,然后返回这个页面给浏览器.这样我们就算是能看到一个每次请求内容都会变化的动态的页面了.

 

___________________________________________________________________________________________________________________________

现在来看看第三个例子,与例子二相比,这个例子稍微复杂了一些,它添加了一些错误处理的代码,并且不再是简单地提供一个写好了模板的页面:

 1 import sys, os, http.server
 2 
 3 class ServerException(Exception):
 4     '''For internal error reporting.'''
 5     pass
 6 
 7 class RequestHandler(http.server.BaseHTTPRequestHandler):
 8     '''
 9     If the requested path maps to a file, that file is served.
10     If anything goes wrong, an error page is constructed.
11     '''
12 
13     # How to display an error.
14     Error_Page = """\
15         <html>
16         <body>
17         <h1>Error accessing %(path)s</h1>
18         <p>%(msg)s</p>
19         </body>
20         </html>
21         """
22 
23     # Classify and handle request.
24     def do_GET(self):
25         try:
26 
27             # Figure out what exactly is being requested.
28             full_path = os.getcwd() + self.path 29 print(self.path," ",full_path) 30 # It doesn't exist... 31 if not os.path.exists(full_path): 32 raise ServerException("'%s' not found" % self.path) 33 34 # ...it's a file... 35 elif os.path.isfile(full_path): 36  self.handle_file(full_path) 37 38 # ...it's something we don't handle. 39 else: 40 raise ServerException("Unknown object '%s'" % self.path) 41 42 # Handle errors. 43 except Exception as msg: 44  self.handle_error(msg) 45 46 def handle_file(self, full_path): 47 try: 48 with open(full_path, 'r') as input: 49 content = input.read() 50  self.send_content(content) 51 except IOError as msg: 52 msg = "'%s' cannot be read: %s" % (self.path, msg) 53  self.handle_error(msg) 54 55 # Handle unknown objects. 56 def handle_error(self, msg): 57 content = self.Error_Page % {'path' : self.path, 58 'msg' : msg} 59  self.send_content(content) 60 61 # Send actual content. 62 def send_content(self, content): 63 self.send_response(200) 64 self.send_header("Content-type", "text/html") 65 self.send_header("Content-Length", str(len(content))) 66  self.end_headers() 67 self.wfile.write(bytearray(content,"gbk")) 68 69 #---------------------------------------------------------------------- 70 71 if __name__ == '__main__': 72 serverAddress = ('', 8080) 73 server = http.server.HTTPServer(serverAddress, RequestHandler) 74 server.serve_forever()

这个例子读取程序所在的当前目录下的某个文件,将文件内容返回给浏览器.我们看看do_GET(self)这个函数内干了什么,首先是获取一个全路径,然后判断这个全路径是否存在,存在的话指向的是否为一个文件,是文件则读取这个文件并返回给浏览器,否则则返回一个error_page。

 

___________________________________________________________________________________________________________________________

现在来看看第四个例子:

 1 import sys, os, http.server
 2 
 3 class ServerException(Exception):
 4     '''For internal error reporting.'''
 5     pass
 6 
 7 class RequestHandler(http.server.BaseHTTPRequestHandler):
 8     '''
 9     If the requested path maps to a file, that file is served.
10     If anything goes wrong, an error page is constructed.
11     '''
12 
13     # How to display a directory listing.
14     Listing = '''\
15 <html>
16 <body>
17 <ul>
18 %s
19 </ul>
20 </body>
21 </html>
22 '''
23 
24     # How to display an error.
25     Error_Page = """\
26         <html>
27         <body>
28         <h1>Error accessing %(path)s</h1>
29         <p>%(msg)s</p>
30         </body>
31         </html>
32         """
33 
34     # Classify and handle request.
35     def do_GET(self):
36         try:
37 
38             # Figure out what exactly is being requested.
39             full_path = os.getcwd() + self.path 40 41 # It doesn't exist... 42 if not os.path.exists(full_path): 43 raise ServerException("'%s' not found" % self.path) 44 45 # ...it's a file... 46 elif os.path.isfile(full_path): 47  self.handle_file(full_path) 48 49 # ...it's a directory... 50 elif os.path.isdir(full_path): 51  self.list_dir(full_path) 52 53 # ...it's something we don't handle. 54 else: 55 raise ServerException("Unknown object '%s'" % self.path) 56 57 # Handle errors. 58 except Exception as msg: 59  self.handle_error(msg) 60 61 def handle_file(self, full_path): 62 try: 63 with open(full_path, 'r') as input: 64 content = input.read() 65  self.send_content(content) 66 except IOError as msg: 67 msg = "'%s' cannot be read: %s" % (self.path, msg) 68  self.handle_error(msg) 69 70 def list_dir(self, full_path): 71 try: 72 entries = os.listdir(full_path) 73 bullets = ['<li>%s</li>' % e for e in entries if not e.startswith('.')] 74 page = self.Listing % '\n'.join(bullets) 75  self.send_content(page) 76 except OSError as msg: 77 msg = "'%s' cannot be listed: %s" % (self.path, msg) 78  self.handle_error(msg) 79 80 # Handle unknown objects. 81 def handle_error(self, msg): 82 content = self.Error_Page % {'path' : self.path, 83 'msg' : msg} 84  self.send_content(content) 85 86 # Send actual content. 87 def send_content(self, content): 88 self.send_response(200) 89 self.send_header("Content-type", "text/html") 90 self.send_header("Content-Length", str(len(content))) 91 self.end_headers() 92 self.wfile.write(bytearray(content,"gbk")) 93 94 #---------------------------------------------------------------------- 95 96 if __name__ == '__main__': 97 serverAddress = ('', 8080) 98 server = http.server.HTTPServer(serverAddress, RequestHandler) 99 server.serve_forever()

这个例子和上个例子是类似的,不过是多了个对全路径指向的是一个目录而不是一个文件这种状况的处理.

 

——————————————————————————————————————————————————————————————————————————————————

第五个例子比上述的看起来又要复杂一些,不过其实只是多了一个命令行的处理以及一些错误处理函数而已.getopt模块用法看这里:https://docs.python.org/3/library/getopt.html?highlight=getopt#module-getopt,

在例子4和例子3中,我们拼接全路径是通过full_path = os.getcwd() + self.path来拼接.也就是说比如你的server.py位于D盘,那么你的full_path就只能是D:\xxxxx这种形式.

那么在例子5里,我们通过在启动server.py时通过命令行的方式(比如:python server.py -v C:\)传参一个根目录,那么这时候就能处理C:\XXXX路径的文件了.

 

  1 import sys, os, http.server
  2 
  3 class RequestHandler(http.server.BaseHTTPRequestHandler):
  4 
  5     # Root of files being served.
  6     Root_Directory = None
  7 
  8     # Is debugging output on?
  9     Debug = False
 10 
 11     # HTTP error codes.
 12     ERR_NO_PERM   = 403
 13     ERR_NOT_FOUND = 404
 14     ERR_INTERNAL  = 500
 15 
 16     # How to display a single item in a directory listing.
 17     Listing_Item = "<li>%s</li>"
 18 
 19     # How to display a whole page of listings.
 20     Listing_Page = """\
 21         <html>
 22         <body>
 23         <h1>Listing for %(path)s</h1>
 24         <ul>
 25         %(filler)s
 26         </ul>
 27         </body>
 28         </html>
 29         """
 30 
 31     # Classify and handle request.
 32     def do_GET(self):
 33 
 34         self.log("path is '%s'" % self.path) 35 36 # Handle any errors that arise. 37 try: 38 39 # Class not yet initialized. 40 if self.Root_Directory is None: 41 self.err_internal("Root directory not set") 42 return 43 44 # Figure out what exactly is being requested. 45 abs_path = self.create_abs_path() 46 self.log("abs_path is '%s'" % abs_path) 47 48 # It isn't below the root path. 49 if not self.is_parent_dir(self.Root_Directory, abs_path): 50 self.log("abs_path not below root directory") 51 msg = "Path '%s' not below root directory '%s'" % \ 52  (abs_path, self.Root_Directory) 53  self.err_no_perm(msg) 54 55 # It doesn't exist. 56 elif not os.path.exists(abs_path): 57 self.log("abs_path doesn't exist") 58  self.err_not_found(abs_path) 59 60 # It's a file. 61 elif os.path.isfile(abs_path): 62 self.log("abs_path is a file") 63  self.handle_file(abs_path) 64 65 # It's a directory. 66 elif os.path.isdir(abs_path): 67 self.log("abs_path is a directory") 68  self.handle_dir(abs_path) 69 70 # ...we can't tell. 71 else: 72 self.log("can't tell what abs_path is") 73  self.err_not_found(abs_path) 74 75 # Handle general errors. 76 except Exception as msg: 77 self.err_internal("Unexpected exception: %s" % msg) 78 79 def create_abs_path(self): 80 head = os.path.abspath(self.Root_Directory) 81 result = os.path.normpath(head + self.path) 82 return result 83 84 def is_parent_dir(self, left, right): 85 return os.path.commonprefix([left, right]) == left 86 87 def handle_file(self, abs_path): 88 try: 89 input = open(abs_path, "r") 90 content = input.read() 91  input.close() 92  self.send_content(content) 93 except IOError as msg: 94 msg = "'%s' cannot be read: %s" % (self.path, msg) 95  self.err_no_perm(msg) 96 97 def handle_dir(self, abs_path): 98 try: 99 listing = os.listdir(abs_path) 100 filler = '\n'.join([(self.Listing_Item % item) for item in listing]) 101 content = self.Listing_Page % {'path' : self.path, 102 'filler' : filler} 103  self.send_content(content) 104 except IOError as msg: 105 msg = "'%s' cannot be listed: %s" % (self.path, msg) 106  self.send_error(ERR_NO_PERM, msg) 107 108 # Send actual content. 109 def send_content(self, content): 110 self.send_response(200) 111 self.send_header("Content-type", "text/html") 112 self.send_header("Content-Length", str(len(content))) 113  self.end_headers() 114 self.wfile.write(bytearray(content,"gbk")) 115 116 # Report internal errors. 117 def err_internal(self, msg): 118  self.send_error(self.ERR_INTERNAL, msg) 119 120 # Handle missing object errors. 121 def err_not_found(self, abs_path): 122 self.send_error(self.ERR_NOT_FOUND, "'%s' not found" % self.path) 123 124 # Handle no permission errors. 125 def err_no_perm(self, msg): 126  self.send_error(self.ERR_NO_PERM, msg) 127 128 # Write a log message if in debugging mode 129 def log(self, msg): 130 if self.Debug: 131 print(msg) 132 133 #---------------------------------------------------------------------- 134 135 if __name__ == '__main__': 136 137 # Main libraries 138 import getopt 139 140 # How to use 141 Usage = "server.py [-v] root_directory" 142 143 # Handle command-line arguments 144 options, rest = getopt.getopt(sys.argv[1:], "v") 145 #print(sys.argv[1:]) 146 #print(options,rest) 147 for (flag, arg) in options: 148 if flag == "-v": 149 RequestHandler.Debug = True 150 else: 151 print(Usage, file=sys.stderr) 152 sys.exit(1) 153 154 if not rest: 155 print(Usage, file=sys.stderr) 156 sys.exit(1) 157 root = os.path.abspath(rest[0]) 158 if not os.path.isdir(root): 159 print("No such directory '%s'" % root, file=sys.stderr) 160 sys.exit(1) 161 RequestHandler.Root_Directory = root 162 163 # Create and run server. 164 server_address = ('', 8080) 165 server = http.server.HTTPServer(server_address, RequestHandler) 166 server.serve_forever()

 

--------------------------------------------------------------------------------------------------------------------------------------------------------------------在前面的例子中我们注意到在http_header里类型我们总是填写的“text/html”.如果浏览器请求的是一个图片呢?你可以运行例子5,你会发现浏览器是无法正常显示这个图片的.

self.send_header("Content-type", "text/html")

例子6与例子5的区别只是加了一个文件类型(例如是个文本啊还是个图片啊)的判断,从而在回发content的时候告知浏览器content-type以使其知道应该如何处理这种文件.有关mime type的知识可以看这里

http://www.cnblogs.com/jsean/articles/1610265.html

  1 import sys, os, http.server, mimetypes
  2 class RequestHandler(http.server.BaseHTTPRequestHandler):
  3 
  4     # Root of files being served.
  5     Root_Directory = None
  6 
  7     # Is debugging output on?
  8     Debug = False
  9 
 10     # HTTP error codes.
 11     ERR_NO_PERM   = 403
 12     ERR_NOT_FOUND = 404
 13     ERR_INTERNAL  = 500
 14 
 15     # How to display a single item in a directory listing.
 16     Listing_Item = "<li>%s</li>"
 17 
 18     # How to display a whole page of listings.
 19     Listing_Page = """\
 20         <html>
 21         <body>
 22         <h1>Listing for %(path)s</h1>
 23         <ul>
 24         %(filler)s
 25         </ul>
 26         </body>
 27         </html>
 28         """
 29 
 30     # MIME types of files.
 31     File_Types = mimetypes.types_map
 32 
 33     # Classify and handle request.
 34     def do_GET(self): 35 36 self.log("path is '%s'" % self.path) 37 38 # Handle any errors that arise. 39 try: 40 41 # Class not yet initialized. 42 if self.Root_Directory is None: 43 self.err_internal("Root directory not set") 44 return 45 46 # Figure out what exactly is being requested. 47 abs_path = self.create_abs_path() 48 self.log("abs_path is '%s'" % abs_path) 49 50 # It isn't below the root path. 51 if not self.is_parent_dir(self.Root_Directory, abs_path): 52 self.log("abs_path not below root directory") 53 msg = "Path '%s' not below root directory '%s'" % \ 54  (abs_path, self.Root_Directory) 55  self.err_no_perm(msg) 56 57 # It doesn't exist. 58 elif not os.path.exists(abs_path): 59 self.log("abs_path doesn't exist") 60  self.err_not_found(abs_path) 61 62 # It's a file. 63 elif os.path.isfile(abs_path): 64 self.log("abs_path is a file") 65  self.handle_file(abs_path) 66 67 # It's a directory. 68 elif os.path.isdir(abs_path): 69 self.log("abs_path is a directory") 70  self.handle_dir(abs_path) 71 72 # ...we can't tell. 73 else: 74 self.log("can't tell what abs_path is") 75  self.err_not_found(abs_path) 76 77 # Handle general errors. 78 except Exception as msg: 79 self.err_internal("Unexpected exception: %s" % msg) 80 81 def create_abs_path(self): 82 head = os.path.abspath(self.Root_Directory) 83 result = os.path.normpath(head + self.path) 84 return result 85 86 def is_parent_dir(self, left, right): 87 return os.path.commonprefix([left, right]) == left 88 89 # Guess the MIME type of a file from its name. 90 def guess_file_type(self, path): 91 base, ext = os.path.splitext(path) 92 if ext in self.File_Types: 93 return self.File_Types[ext] 94 ext = ext.lower() 95 if ext in self.File_Types: 96 return self.File_Types[ext] 97 return self.File_Types[''] 98 99 # Handle files. Must read in binary mode! 100 def handle_file(self, abs_path): 101 try: 102 input = open(abs_path, "rb") 103 content = input.read() 104  input.close() 105 fileType = self.guess_file_type(abs_path) 106 print(fileType) 107  self.send_content(content, fileType) 108 except IOError as msg: 109 msg = "'%s' cannot be read: %s" % (self.path, msg) 110  self.err_no_perm(msg) 111 112 # Handle directories. 113 def handle_dir(self, abs_path): 114 try: 115 listing = os.listdir(abs_path) 116 filler = '\n'.join([(self.Listing_Item % item) for item in listing]) 117 content = self.Listing_Page % {'path' : self.path, 118 'filler' : filler} 119 print(type(content)) 120  self.send_content(content.encode()) 121 except IOError as msg: 122 msg = "'%s' cannot be listed: %s" % (self.path, msg) 123  self.err_no_perm(msg) 124 125 # Send actual content. 126 def send_content(self, content, fileType="text/html"): 127 length = str(len(content)) 128 self.log("sending content, fileType '%s', length %s" % (fileType, length)) 129 self.send_response(200) 130 self.send_header("Content-type", fileType) 131 self.send_header("Content-Length", length) 132  self.end_headers() 133 print(type(self.wfile),type(content)) 134  self.wfile.write(content) 135 136 # Report internal errors. 137 def err_internal(self, msg): 138  self.send_error(self.ERR_INTERNAL, msg) 139 140 # Handle missing object errors. 141 def err_not_found(self, abs_path): 142 self.send_error(self.ERR_NOT_FOUND, "'%s' not found" % self.path) 143 144 # Handle no permission errors. 145 def err_no_perm(self, msg): 146  self.send_error(self.ERR_NO_PERM, msg) 147 148 # Write a log message if in debugging mode 149 def log(self, msg): 150 if self.Debug: 151 print(msg) 152 153 #---------------------------------------------------------------------- 154 155 if __name__ == '__main__': 156 157 # Main libraries 158 import getopt 159 160 # How to use 161 Usage = "server.py [-v] root_directory" 162 163 # Handle command-line arguments 164 options, rest = getopt.getopt(sys.argv[1:], "v") 165 166 for (flag, arg) in options: 167 if flag == "-v": 168 RequestHandler.Debug = True 169 else: 170 print(Usage, file=sys.stderr) 171 sys.exit(1) 172 173 if not rest: 174 print(Usage, file=sys.stderr) 175 sys.exit(1) 176 root = os.path.abspath(rest[0]) 177 if not os.path.isdir(root): 178 print("No such directory '%s'" % root, file=sys.stderr) 179 sys.exit(1) 180 RequestHandler.Root_Directory = root 181 182 # Create and run server. 183 server_address = ('', 8080) 184 server = http.server.HTTPServer(server_address, RequestHandler) 185 server.serve_forever()

 

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

以上的例子中,我们返回给客户端的内容,不管是txt也好,html也好,png也好,都可以看做是静态的文件,是不能被执行的.以下这个例子通过subprocess模块的Popen()可以执行一个.py文件,然后将执行的py文件产生的stdout内容返回给浏览器.有关subprocess的内容可以看这里:https://docs.python.org/3.4/library/subprocess.html

  1 import sys, os, http.server, mimetypes, gettext,subprocess
  2 
  3 class RequestHandler(http.server.BaseHTTPRequestHandler):
  4 
  5     # Root of files being served.
  6     Root_Directory = None
  7 
  8     # Is debugging output on?
  9     Debug = False
 10 
 11     # HTTP error codes.
 12     ERR_NO_PERM   = 403
 13     ERR_NOT_FOUND = 404
 14     ERR_INTERNAL  = 500
 15 
 16     # MIME types of files.
 17     File_Types = mimetypes.types_map
 18 
 19     # Filename extensions that identify executables.
 20     Exec_Extensions = { 21 ".py" : None 22  } 23 24 # Classify and handle request. 25 def do_GET(self): 26 27 # Handle any errors that arise. 28 try: 29 30 # Class not yet initialized. 31 if self.Root_Directory is None: 32 self.err_internal("Root directory not set") 33 return 34 35 # Figure out what exactly is being requested. 36 abs_path, query_params = self.parse_path() 37 self.log("abs_path is '%s'" % abs_path) 38 self.log("query_params is '%s'" % query_params) 39 40 # It isn't below the root path. 41 if not self.is_parent_dir(self.Root_Directory, abs_path): 42 self.log("abs_path not below root directory") 43 self.err_no_perm("Path '%s' not below root directory '%s'" % \ 44  (abs_path, self.Root_Directory)) 45 46 # It doesn't exist. 47 elif not os.path.exists(abs_path): 48 self.log("abs_path doesn't exist") 49  self.err_not_found(abs_path) 50 51 # It's a file. (Ignore query parameters if the file is 52 # not being executed.) 53 elif os.path.isfile(abs_path): 54 if self.is_executable(abs_path): 55 self.log("abs_path is an executable") 56  self.handle_executable(abs_path, query_params) 57 else: 58 self.log("abs_path is a file") 59  self.handle_static_file(abs_path) 60 61 # It's a directory --- ignore query parameters. 62 elif os.path.isdir(abs_path): 63 self.log("abs_path is a directory") 64  self.handle_dir(abs_path) 65 66 # ...we can't tell. 67 else: 68 self.log("can't tell what abs_path is") 69  self.err_not_found(abs_path) 70 71 # Handle general errors. 72 except Exception as msg: 73 self.err_internal("Unexpected exception in main despatch: %s" % msg) 74 75 def parse_path(self): 76 '''Create the absolute path for a request, and extract the query 77 parameter string (if any).''' 78 parts = self.path.split("?") 79 if len(parts) == 1: 80 request_path, queryString = self.path, "" 81 elif len(parts) == 2: 82 request_path, queryString = parts 83 else: 84 pass 85 head = os.path.abspath(self.Root_Directory) 86 result = os.path.normpath(head + request_path) 87 return result, queryString 88 89 def is_parent_dir(self, left, right): 90 return os.path.commonprefix([left, right]) == left 91 92 def guess_file_type(self, path): 93 base, ext = os.path.splitext(path) 94 if ext in self.File_Types: 95 return self.File_Types[ext] 96 ext = ext.lower() 97 if ext in self.File_Types: 98 return self.File_Types[ext] 99 return self.File_Types[''] 100 101 def is_executable(self, abs_path): 102 '''Does this path map to an executable file?''' 103 root, ext = os.path.splitext(abs_path) 104 return ext in self.Exec_Extensions 105 106 def handle_static_file(self, abs_path): 107 '''Handle static files. Must read in binary mode!''' 108 try: 109 input = file(abs_path, "rb") 110 content = input.read() 111  input.close() 112 file_type = self.guess_file_type(abs_path) 113  self.send_content(content, file_type) 114 except IOError as msg: 115 self.err_no_perm("'%s' cannot be read: %s" % (self.path, msg)) 116 117 # Handle directories. 118 def handle_dir(self, abs_path): 119 120 # How to display a single item in a directory listing. 121 listing_item = "<li>%s</li>" 122 123 # How to display a whole page of listings. 124 listing_page = \ 125 "<html>" + \ 126 "<body>" + \ 127 "<h1>Listing for " + "%(path)s" + "</h1>" + \ 128 "<ul>" + \ 129 "%(filler)s" + \ 130 "</ul>" + \ 131 "</body>" + \ 132 "</html>" 133 134 try: 135 listing = os.listdir(abs_path) 136 filler = '\n'.join([(listing_item % item) for item in listing]) 137 content = listing_page % {'path' : self.path, 138 'filler' : filler} 139  self.send_content(content) 140 except IOError as msg: 141 self.err_no_perm("'%s' cannot be listed: %s" % msg) 142 143 # Handle executable file. 144 def handle_executable(self, abs_path, query_params): 145 # Passing query parameters? 146 if query_params: 147 os.environ["REQUEST_METHOD"] = "GET" 148 os.environ["QUERY_STRING"] = query_params 149 cmd = "python " + abs_path 150 #p = subprocess.Popen(cmd, shell=True, bufsize=bufsize,stdin=PIPE, stdout=PIPE, close_fds=True) 151 p = subprocess.Popen(cmd,stdin=subprocess.PIPE, stdout=subprocess.PIPE) 152 print(type(p),p) 153 (childInput, childOutput) = (p.stdin,p.stdout) 154 print(cmd,childInput,childOutput) 155 #childInput, childOutput = subprocess.popen2(cmd) 156  childInput.close() 157 response = childOutput.read() 158  childOutput.close() 159 self.log("handle_executable: response length is %d" % len(response)) 160 self.send_response(200) 161  self.wfile.write(response) 162 163 # Send actual content. 164 def send_content(self, content, fileType="text/html"): 165 length = str(len(content)) 166 self.log("sending content, fileType '%s', length %s" % (fileType, length)) 167 self.send_response(200) 168 self.send_header("Content-type", fileType) 169 self.send_header("Content-Length", length) 170  self.end_headers() 171  self.wfile.write(content) 172 173 # Report internal errors. 174 def err_internal(self, msg): 175  self.send_error(self.ERR_INTERNAL, msg) 176 177 # Handle missing object errors. 178 def err_not_found(self, abs_path): 179 self.send_error(self.ERR_NOT_FOUND, "'%s' not found" % self.path) 180 181 # Handle no permission errors. 182 def err_no_perm(self, msg): 183  self.send_error(self.ERR_NO_PERM, msg) 184 185 # Handle execution errors. 186 def errExec(self, msg): 187  self.send_error(self.ERR_NO_PERM, msg) 188 189 # Write a log message if in debugging mode 190 def log(self, msg): 191 if self.Debug: 192 print("nitinat:", msg) 193 194 #---------------------------------------------------------------------- 195 196 if __name__ == '__main__': 197 198 # Main libraries 199 import getopt 200 201 # How to handle fatal startup errors 202 def fatal(msg): 203 print("nitinat:", msg, file=sys.stderr) 204 sys.exit(1) 205 206 # Defaults 207 host = '' 208 port = 8080 209 root = None 210 211 # How to use 212 Usage = "server.py [-h host] [-p port] [-v] -r|Root_Directory" 213 214 # Handle command-line arguments 215 options, rest = getopt.getopt(sys.argv[1:], "h:p:rv") 216 217 for (flag, arg) in options: 218 if flag == "-h": 219 host = arg 220 if not arg: 221 msg = "No host given with -h" 222  fatal(msg) 223 elif flag == "-p": 224 try: 225 port = int(arg) 226 except ValueError as msg: 227 fatal("Unable to convert '%s' to integer: %s" % (arg, msg)) 228 elif flag == "-r": 229 root = os.getcwd() 230 elif flag == "-v": 231 RequestHandler.Debug = True 232 else: 233  fatal(Usage) 234 235 # Make sure root directory is set, and is a directory. 236 if (root and rest) or (not root and not rest): 237  fatal(Usage) 238 if not root: 239 root = os.path.abspath(rest[0]) 240 if not os.path.isdir(root): 241 fatal("No such directory '%s'" % root) 242 RequestHandler.Root_Directory = root 243 244 # Create and run server. 245 server_address = (host, port) 246 server = http.server.HTTPServer(server_address, RequestHandler) 247 server.serve_forever()

 

以上就是这个500行的简易小项目的全部内容了,可以看出来,虽然每一个程序都越来越复杂,其实程序的骨架并没有变,我们不断丰富的只是解析出请求后具体的处理逻辑代码而已,由于python的标准库已经帮我们做了许多诸如解析请求啊,回发内容啊等等这些内容,我们用python写起web来还是蛮容易的.虽然只是很简单的一些小程序,但是已经描述出了基本的web的写法,还是值得一看的.从git上下载该项目以后,里面的chapter.md可以好好看一看,里面简要介绍了web和HTTP协议的一些知识.你可以用markdownpad或者直接在线https://www.zybuluo.com/mdeditor来阅读这个.md文件.

 

转载于:https://www.cnblogs.com/sdu20112013/p/4142047.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码范例列表 第1章 示例描述:本章演示如何开始使用JDK进程序的开发。 HelloWorldApp.java 第一个用Java开发的应用程序。 firstApplet.java 第一个用Java开发的Applet小程序。 firstApplet.htm 用来装载Applet的网页文件 第2章 示例描述:本章介绍开发Java的基础语法知识。 accumulationByDoWhile.java 用do~while语句的累加程序 accumulationByFor.java 用for语句的累加程序 accumulationByWhile.java 用while语句的累加程序 boolExample.java 演示boolean变量的程序 charExample.java 演示char变量的程序 compare.java 演示前缀、后缀自加之间区别的程序 constCharExample.java 演示转义字符 converseNumber.java 逆向输出数字 daffodilNumber.java 求水仙花数 division.java 演示整除结果 errorCompoundVariable.java 错误使用局部变量示例 factorial.java 求阶乘 Fibonacci.java 求Fiblnacci数列 GcdAndGcm.java 求最大公约数和最小公倍数 errorInit.java 演示变量初始化错误的程序 integerExample.java 演示各种整型变量的使用 isPrime.java 判断素数 leapYearByIf.java 用if语句判断闰年 leapYearByLogical.java 用逻辑表达式判断闰年 lowToUpper.java 小字母转换成大字母 lozengeStar.java 输出一个由*组成的菱形 multiplyTable.java 求乘法口诀表 narrowingConversion_1.java 缩减转换引发错误示例1 narrowingConversion_2.java 缩减转换引发错误示例2 notMultipleOfThree.java 把100-200之间不能被3整除的数输出 outputByDoWhile.java 用while循环随机输出数据 outputByWhile.java 用do~while循环随机输出数据 outputMax.java 求两个数中的最大数 overflowExample.java 演示溢出 precedence.java 演示自加运算符的优先级 primeNumber.java 输出100-200之间的所有素数 ranking.java 评定成绩等级 rankingBySwitch.java 用switch语句评定成绩等级 realExample.java 演示浮点数的有效位数 remainder.java 取余运算示例 showBreak.java 利用标号语句跳转出所有循环嵌套 showCount.java 循环计数示例 showDoubleLoop.java 演示双重循环 showDoubleLoopSe.java 改进的双重循环 showOrder_1.java 演示操作数求值顺序示例1 showOrder_2.java 演示操作数求值顺序示例2 sign.java 用条件运算实现符号函数示例 signByIF.java 用if语句实现符号函数示例 triangleStar.java 输出一个由*组成的直角三角形 upperToLowCase.java 大转换成小 variableScopeExample.java 变量使用范围示例 第3章 示例描述:本章学习对象和类。 accessMember.java 访问成员变量示例 constructNoPara.java 无参数的构造方法 constructWithPara.java 带参数的构造方法 declareDefault.java 缺省访问权限的使用 declarePrivate.java 私有访问权限的使用 declareProtected.java 保护访问权限的使用 deriveClass.java 子类访问父类变量示例 getLinePara.java 获取命令参数示例 hasStaticMethod.java 静态成员方法示例 hasStatMember.java 静态成员变量示例 HelloNative.c 用C的一个小程序 HelloNative.dll 用C生成的DLL文件 HelloNative.exp 用VC编译生成的辅助文件 HelloNative.h 用javah生成的C语言用的头文件 HelloNative.java 准备调用C函数的java文件 HelloNative.lib 用VC编译生成的静态库文件 HelloNative.obj 用VB编译生成的目标文件 HelloNativeTest.java 测试本地化是否成功的类文件 instanceVar.java 定义一个实例成员变量 invokeByObject.java 对象实参传递示例程序 invokeByValue.java 传值调用示例程序 invokeMethod.java 同一个类中调用方法示例 invokeOther.java 类的外部调用方法示例 invokeStaticMethod.java 调用静态方法示例 localVariable.java 演示局部变量 localVSmember.java 局部变量与成员变量同名问题示例 onlyTest.java 对象传值示例 otherClass.java 从类的外部访问对象的成员 showInstVar.java 演示不同的对象拥有不同的成员变量 showMain.java 演示main方法访问本类成员 showMethod.java 演示如何定义一个方法体 showReturn_1.java return语句示例1 showReturn_2.java return语句示例2 showStaicVar.java 演示静态变量的使用 staticBlock.java 演示静态块的使用 staticVar.java 定义静态变量 supplyTest.java 对象作为静态成员使用示例 trySwap.java 试图交换两个形参的值 useOnlyTest.java 创建多个对象,演示this的作用 useStaticBolck.java 使用静态块 useStVar.java 使用静态成员变量 第4章 示例描述:本章学习继承与多态。 absClass.java 抽象类定义示例 ancestor.java 基类定义示例1 ancestor_1.java 另一个基类定义 anonymousInner.java 匿名内部类 base.java 定义一个基类 BaseColors.java 一个简单的接口 basePoint.java 一个测试用的基类 Colorable.java 一个子接口 ColoredPoint.java 一个测试用子类 common.java 一个公用类 derive.java 一个测试用子类 differ.java 测试静态方法与实例方法之间的区别 forefather.java 一个简单的基类 grandson.java 上面这个类的子类 hasConstructor.java 拥有构造器的类 hasFinalFun.java 拥有最终方法的类 hasRecall.java 可以完成回调功能的类 HasStatic.java 一个简单的拥有静态成员的类 hideMember_1.java 成员隐藏示例1 hideMember_2.java 成员隐藏示例2 hideMember_3.java 成员隐藏示例3 hideMember_4.java 成员隐藏示例4 hideMember_5.java 成员隐藏示例5 implementABS.java 继承一个抽象类 impRecall.java 实现回调函数 inheritConstruct_1.java 构造器继承示例1 inheritConstruct_2.java 构造器继承示例2 inheritConstruct_3.java 构造器继承示例3 inheritConstruct_4.java 构造器继承示例4 inheritConstruct_5.java 构造器继承示例5 inheritConstruct_6.java 构造器继承示例6 inheritor.java 子类覆盖父类示例 inPack.java 包示例 LotsOfColors.java 定义一个子接口 matching.java 重载解析示例 notInPack.java 用前缀引用包中的类 onlyShow.java 一个简单的接口 Outer_1.java 外部类示例1 Outer_2.java 外部类示例2 Outer_3.java 外部类示例3 Outer_4.java 外部类示例4 Outer_5.java 外部类示例5 Outer_6.java 外部类示例6 Outer_7.java 外部类示例7 Outer_8.java 外部类示例8 overrideMember_1.java 成员方法覆盖示例1 overrideMember_2.java 成员方法覆盖示例2 overrideMember_3.java 成员方法覆盖示例3 overrideMember_4.java 成员方法覆盖示例4 overrideMember_5.java 成员方法覆盖示例5 Paintable.java 实现了多个接口的方法 PaintedPoint.java 实现了多个接口的方法 Point.java 一个简单的类 PrintColors.java 一个子接口 RainbowColors.java 一个子接口 realPoint.java 一个子类 second.java 属于一个命名包的类 showDiff.java 演示隐藏与覆盖之间的区别 showSomething.java 测试运时多态 stupid.java 试图覆盖最终方法的类,它有错误 Sub.java 一个简单的子类 Super.java 一个基类 testOverload.java 测试方法的重载示例1 testOverload_1.java 测试方法的重载示例2 testOverload_2.java 测试方法的重载示例3 testOverload_3.java 测试方法的重载示例4 useConstructor.java 使用构造器 useHideMember_2.java 试图使用隐藏的成员变量 useInner.java 使用内部类 第5章 示例描述:本章学习数组与字符串。 ArrayString.java 字符串数组 assignTwoDime.java 为二维数组赋值 getMaxElem.java 获取数组中的最大元素 incCapicity.java 演示StingBuffer的容量增长 SortDemo.java 排序示例 travelTwoDime.java 遍历二维数组 traversing.java 遍历一维数组 useStrBuf.java 使用StringBuffer示例 useString.java 使用String示例 YanghuiTri.java 构造和显示杨辉三角 第6章 示例描述:本章学习Java的异常处理。 demoException_1.java 异常示例1 demoException_2.java 异常示例2 demoException_3.java 异常示例3 demoException_4.java 异常示例4 demoException_5.java 异常示例5 divZeroError.java 除零异常 hasCheckException.java 检查型异常 MyException.java 用户自定义异常 myInput.java 输入数据示例 nestException_1.java 异常嵌套示例1 nestException_2.java 异常嵌套示例2 nestException_3.java 异常嵌套示例3 outBoundError.java 下标越界异常 throwException.java 抛出异常示例 throwsException.java 声明抛出异常 useMyException.java 使用自定义异常 第7章 示例描述:本章学习Java的输入和输出。 CopyFile.java 文件复制实例 dir.java 显示目录下的所有文件和目录 encrypt.java 文件加密 FileList.java 自己实现的一个文件名称枚举类 MyDataIO.java 数据输入输出示例 MyFileOutput.java 将键盘读入的文字保存到文件 MyPipedIO.java 管道流示例 MySequenceIn.java 顺序输入流示例 ObjectFileTest.java 序列化对象示例 ReadAndWrite.java 读入和出数据 ReadAndWriteFile.java 读入数据出到文件 Student.java 定义一个用来序列化的类 ThreadIn.java 接收数据用的线程类 ThreadOut.java 发送数据用的线程类 TypeFile.java 显示文件内容的类 useScanner.java 用Scanner接收用户的输入 第8章 示例描述:本章学习多线程。 enhanceThread.java 一个自己定义的增强型线程类 ThreadImRunnable.java 继承Runnable接口实现多线程 mulThread.java 创建多个线程对象的类 demoJoin.java 演示使用join()以确保主线程最后结束 clicker.java 一个计数用的线程类 demoPri.java 调用上面这个类设置线程优先级示例 myThread.java 自己定义的一个Thread的子类 mutexThread.java 一个能管理临界区的线程类 demoMutex.java 使用上面这个类来演示线程的互斥 commSource.java 一个共享资源的类 demoSynchrony.java 演示线程的同步 setDataThread.java 设置数据的线程类 readDataThread.java 读取数据的线程类 demoEnhanceThread.java 使用自己定义的线程类示例 producer_consumer.java 演示生产者-消费者线程 consumer.java 消费者线程 producer.java 生产者线程 common.java 公有类 第9章 示例描述:本章学习运时类型识别。 Candy.java 一个用来测试的简单类 changeFields.java 改变属性值示例 Circle.java 一个用于测试的简单类 DumpMethods.java 使用反射机制来获取类中的方法 getClassName.java 利用反射机制获取类的名字 invokeConstructor.java 利用反射机制调用构造器 invokeMethod.java 利用反射机制调用成员方法 listConstructors.java 利用反射机制获取构造器列表 listFields.java 利用反射机制获取成员属性列表 listMethods.java 利用反射机制获取成员方法列表 loadClass.java 动态装载一个类 Shape.java 一个用于测试的简单类 useArray1.java 用反射机制使用数组示例1 useArray2.java 用反射机制使用数组示例2 第10章 示例描述:本章学习泛型。 demoBounds.java 演示有界类型 demoForceChange.java 演示强制类型转换 demoGeneric.java 泛型类的使用示例 demoGenIF.java 测试泛型类 demoGenMethods.java 泛型方法示例 demoHerit_1.java 泛型类继承示例1 demoHerit_2.java 泛型类继承示例2 demoRTTI_1.java 泛型类的类型识别示例1 demoRTTI_2.java 泛型类的类型识别示例2 demoWildcard.java 通配符使用示例 demoWipe.java 擦拭示例 derivedGen.java 泛型父类继承示例 derivedNonGen.java 非泛型父类继承示例 foo.java 一个有错误的类 Gen.java 无限界的泛型擦拭 Generic.java 一个简单的泛型类 genMethod.java 一个泛型方法 GenStr.java 有限界的泛型擦拭 MinMax.java 泛型接口示例 MyClass.java 实现一个泛型接口 nonGen.java 以非泛型类为父类 simpGen.java 使用泛型类示例 Stats.java 一个有界类泛型 superGen.java 父类是泛型 twoGen.java 有两个参数的泛型类 第11章 示例描述:本章学习集合。 CompareScore.java 实现比较器接口 demoAlgorithm.java 集合中简单算法示例 demoArrayList.java 链表使用示例 demoBinSearch.java 二分查找示例 demoEnumSet.java 枚举类型示例 demoHashMap.java 哈希映射示例 demoHashSet.java 哈希集合示例 demoSort.java 排序示例 demoTreeMap.java 树映射示例 demoTreeSet.java 树集合示例 demoVector.java 向量使用示例 job.java 模拟操作系统的进程调度 monkey.java 用链表求猴子选大王 myCompare.java 自己实现的比较器接口 reverseString.java 利用栈将字符串逆序输出 scheduling.java 模拟操作系统的作业调度过程 showClothValue.java 根据用户输入型号输出相应的价格 Size.java 一个枚举类 Student.java 用于记录学生信息的类 第12章 示例描述:本章学习类型包装器、自动装箱和元数据。 demoAnno.java 给方法做注释示例 demoAutoBox_1.java 自动装/拆箱机制示例1 demoAutoBox_2.java 自动装/拆箱机制示例2 demoAutoBox_3.java 自动装/拆箱机制示例3 demoInteger.java 整数类型包装器使用示例 demoSingle.java 单成员注释使用示例 DeprecatedClass.java Deprecated注释示例 InProgress.java Documented元注释使用示例 Marker.java 一个被注释的接口 Meta.java 利用反射机制获取方法的注释 MetaAll.java 获取所有注释示例 MyAnno.java 包含了默认值的注释 MyMarker.java 标记注释使用示例 MySingle.java 单成员注释使用示例 OverrideTester.java Override注释示例 SuppressWarningsTester.java SuppressWarnings注释示例 TODO.java Target元注释使用示例 What.java 显示全部注释 第13章 示例描述:本章学习常用工具类。 checkEmail.java 利用正则表达式检验Email的合法性 currentTime_1.java 显示时间示例程序1 currentTime_2.java 显示时间示例程序2 currentTime_3.java 显示时间示例程序3 DateAndTime.java 用Calendar显示当前的日期和时间 demoFmtTime.java 使用时间格式转换符输出日期和时间 demoFormatter.java Formatter简单输出示例 demoGroup.java 组匹配使用示例 demoMathing.java 匹配方法使用示例 demoMemory.java 内存管理示例程序 demoPattern_1.java Pattern使用示例1 demoPattern_2.java Pattern使用示例2 demoRandom.java 产生随机数序列示例 demoReplace.java 替换方法使用示例 demoRound.java 取整函数使用示例 elapsed.java 计算程序运时间 exitJVM.java 从子线程中退出虚拟机 getPI.java 利用随机数求π值 progPI.java 利用反正切函数求π的值 runNotepad.java 启动记事本 showCalendar.java 用GregorianCalendar实现一个万年历 showProperties.java 获取环境属性 textToTime.java 从文本串创建日期对象 useLog.java 利用换底公式求任意对数值 第14章 示例描述:本章学习GUI程序设计。 addNodeInJTree.java 在JTree中增加节点示例 AlarmClock.java 小闹钟程序 AWTComponents.htm 为显示AWT组件而编制的网页文件 AWTComponents.java AWT组件示例 AWTFrame.java 用AWT编的一个简单窗口 CheckAchromatopsiat.java 色盲检测程序 demoBorderLayout.java 边框布局使用示例 demoCardLayout.java 卡片布局使用示例 demoGridBagLayout.java 增强网格布局使用示例 demoGridLayout.java 网格布局使用示例 demoJApplet.htm 运JApplet的网页文件 demoJApplet.java JApplet使用示例 demoJButton.java 按钮使用示例 demoJCheckbox.java 复选框使用示例 demoJComboBox.java 组合框使用示例 demoJDialog.java 对话框使用示例 demoJFrame.java JFrame简单使用示例 demoJLabel_1.java 图像标签使用示例 demoJLabel_2.java 改变标签上鼠标形状示例 demoJList.java 列表框使用 demoJMenu.java 菜单使用示例 demoJPanel.java 面板使用简单示例 demoJRadioButton.java 单选按钮使用示例 demoJScrollPane_1.java 在JScrollPane创建时添加组件示例 demoJScrollPane_2.java 通过add()方法添加组件示例 demoJSplitPane_1.java 分隔板简单示例1 demoJSplitPane_2.java 分隔板简单示例2 demoJTabbedPane.java 选项板使用示例 demoJTable_1.java 表格使用示例1 demoJTable_2.java 表格使用示例2 demoJTable_3.java 表格使用示例3 demoJTable_4.java 表格使用示例4 demoJTable_5.java 表格使用示例5 demoJText.java 文本框和密码框使用示例 demoJTextArea.java 文本区使用示例 demoJToolBar.java 工具栏使用示例 demoJTree.java 创建JTree示例 ExampleFileFilter.java Sun公司提供的一个文件名过滤器 findDialog.java 查找对话框 fontDialog.java 字体选择对话框 MyTableModel.java 本类实现了一个表格用的模型,取代默认的模型 Notebook.java 记事本 painting_1.java 在面板上画出简单图形示例1 painting_2.java 在面板上画出图形示例2 reMulEvent.java 响应单击按钮事件 showTriDialog.java 用系统预定义的对话框 本章下面还有一些编程要用到的图片和声音文件,不一一列出。 第15章 示例描述:本章学习多媒体程序设计。 building.java 调用另外一个houseCanvas类画出一栋房子 CombinerCanvas.java 编自己的画布,所要显示的图片在此画布上显示 CombinPic.java 合成两幅图片 DrawArcs.java 画椭圆和圆弧示例 DrawLines.java 画直线示例 DrawPoly.java 画多边形示例 DrawRects.java 画矩形示例 fadeInOut.java 淡入淡出效果示例 FillArea.java 填充图形示例 FontsCanvas.java 自管理字体的画布 GetFonts.java 获取系统中安装的字体示例 GrayFilter.java 自己实现的GrayFilter类 GrayModel.java 实现一个具备灰度变换功能的Model houseCanvas.java 用直线画出一栋房子 illumination.java 光照特效示例 LightingLiteral.java 字体特效显示示例 ManageFonts.java 自管理字体示例 mixing.java 显示色彩混合效果 playAudio.java 在Application中播放声音文件 playMP3.java 增强的声音播放文件 playMusic.htm 可以播放背景音乐的一个网页 playMusic.java 利用AudioClip播放声音文件 playVideo.java 媒体播放器编示例 ResizeOval.java 缩放图形示例 ShowFonts.java 建和使用字体示例 SoundBase.java 将Java Sound API封装在一个线程中 TransparencyExample.java 为实现色彩混合效果而定义的画布 viewPic.java 用标签显示图像示例 本章下面还有一些编程要用到的图片和声音文件,不一一列出 第17章 示例描述:本章学习数据库程序设计。 AddressList.java 学生信息管理系统实例 deleteData.java 从数据库中删除记录 FirstExample.mdb 本章用到的数据库文件 insertData.java 向数据库中添加新数据 queryData.java 查询数据示例 updateData.java 修改数据示例 第18章 示例描述:本章学习C/S网络程序设计。 chatClient.java 聊天客户端程序 chatServer.java 聊天服务端程序 Client.java 一个简单的客户端程序 DownFile.java 文件下载示例 GetHostName.java 根据IP查找主机名 GetIP.java 根据域名查找IP地址 GetMyIP.java 获取本机IP地址 MultiServer.java 可以响应多个客户端的服务程序 myBrowser.java 一个简单的浏览器 Server.java 一个简单的服务端程序 ServerThread.java 一个服务端的线程类 UDPChat.java 用UDP实现的聊天程序示例 第19章 示例描述:本章学习JSP程序设计。本章所有文件均已经按照Tomcat网站部署的要求放置在各自的目录下,然后打包成ZIP文件。读者只需要解包后放置在某一分区中,然后在Tomcat中配置好入口就可以使用。 下面的文件均放置在ROOT目录下面 ArbitraryObject.java 实现一个事件监听者接口的类 calendar.jsp 用JSP实现的日历 count.txt 站点计数器保存的数据文件 counter.jsp 用JSP实现的计数器 faq.java 连接数据库用的JavaBean leaveword.htm 留言板的主页面 Model.java 自己定义的事件源类 ModelChangedListener.java 自己定义的一个事件监听者接口 MouseMovedExampleEvent.java 事件状态对象示例 MouseMovedExampleListener.java 鼠标事件监听者接口与事件监听者示例 OurButtonCustomizer.java 实现一个“按钮”Beans的定制器 query.jsp 数据库查询程序 saveword.java 用于保存记录的JavaBean saveword.jsp 后台保存数据的JSP文件 viewword.jsp 查看留言的JSP页面 WeekDayBeanInfo.java 实现BeanInfo接口示例 WeekDayEditor.java 实现属性编辑器接口 下面的文件均存放在chat目录下,是聊天室的组成文件。 chatreg.java 用户注册用到的JavaBean文件 chatreg.jsp 用户注册的前台JSP文件 chatregcof.jsp 用户注册检查JSP文件 chatroom.jsp 聊天室的主页面 confirm.jsp 检查登录是否正确的JSP文件 in.jsp 即将进入聊天室前的提示页面 listuser.jsp 显示聊天室内的所有用户名的JSP文件 logout.jsp 清除用户的相关信息 netchat.jsp 用户进入聊天室的界面文件 showmsg.jsp 显示各个用户所说的话 talk.jsp 用户聊天用的JSP文件 第21章 示例描述:本章是一个IM软件的完整代码。 ChatFrame.java 聊天用的主界面程序 ClientManageFrame.java 是好友管理窗口,也是客户端程序的主窗口 DBConnection.java 连接数据库用的JavaBean FindUserDlg.java 查找好友对话框 FindUserInfo.java 显示用户基本信息 FriendLabel.java 在list列表中显示用户的头像和字符信息 Login.java 用户登录界面 LoginUser.java 定时器的任务类,用于定时获取上线的用户的信息 MyInfo_AboutBox.java 显示作者信息 ReceiveOthersDialog.java 当用户收到陌生人的消息时,这个类向用户提示 RegisterDialog.java 用户注册面板 Server.java 提供各种服务的类 ServerFrame.java 服务器端的主界面 ServerThread.java 与客户端通讯的线程 SetCenter.java 将窗口设置在屏幕中央的类 showTimeTask.java 刷新时间的类 StartServer.java 启动服务器的主类 UpdateDialog.java 更新用户信息的对话框 UserInfo.java 获取用户信息的类 UserInfoBean.java 保存用户信息的一个JavaBean

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值