1 返回一个特定的网页

  1. from socket import *
  2. from threading import Thread
  3. def serve_client(client_socket):
  4. recv_data = client_socket.recv(1024)
  5. print("客户端发送的请求:", recv_data) # 5
  6. print("回复客户端...") # 6
  7. reply = "HTTP/1.1 200 OK\n\n"\
  8. "<h1>MacBookPro</h1>"
  9. client_socket.send(reply.encode("utf-8"))
  10. print("关闭套接字...") # 7
  11. client_socket.close()
  12. print("创建套接字...") # 1
  13. tcp_socket = socket(AF_INET, SOCK_STREAM)
  14. # 程序退出端口号自动释放
  15. tcp_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, True)
  16. print("绑定端口...") # 2
  17. tcp_socket.bind(("", 16055))
  18. print("变为监听套接字,只能被动接收...") # 3
  19. tcp_socket.listen(128)
  20. while True:
  21. print("接受客户端请求,分配一个客服套接字...") # 4
  22. client_socket, client_addr = tcp_socket.accept()
  23. print("客户端信息:", client_addr)
  24. sub_thread = Thread(target=serve_client, args=(client_socket,), daemon=True)
  25. sub_thread.start()
  26. tcp_socket.close()

image.png

2 返回浏览器请求的html

  1. from socket import *
  2. import re
  3. def serve_client(client_socket):
  4. request = client_socket.recv(1024).decode("utf-8")
  5. print("客户端发送的请求:", request) # 5
  6. # 读取请示中的文件名
  7. request_lines = request.splitlines()
  8. ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
  9. file_name = ""
  10. if ret:
  11. file_name = ret.group(1)
  12. print("-------------", file_name)
  13. # 设置默认界面
  14. if file_name == "/" or file_name == "":
  15. file_name = "/index.html"
  16. # header是字符串,body是二进制,不能+=连在一起
  17. print("回复客户端...") # 6
  18. try:
  19. f = open("./html" + file_name, "rb")
  20. except: # 未找到文件
  21. response = "HTTP/1.1 404 NOT FOUND\n\n"
  22. response += "-----file not found-----"
  23. client_socket.send(response.encode("utf-8"))
  24. else: # 成功
  25. html_content = f.read()
  26. f.close()
  27. header = "HTTP/1.1 200 OK\n\n"
  28. client_socket.send(header.encode("utf-8"))
  29. client_socket.send(html_content)
  30. print("关闭套接字...") # 7
  31. client_socket.close()
  32. print("创建套接字...") # 1
  33. tcp_socket = socket(AF_INET, SOCK_STREAM)
  34. print("绑定端口...") # 2
  35. tcp_socket.bind(("", 16055))
  36. print("变为监听套接字,只能被动接收...") # 3
  37. tcp_socket.listen(128)
  38. while True:
  39. print("接受客户端请求,分配一个客服套接字...") # 4
  40. client_socket, client_addr = tcp_socket.accept()
  41. print("客户端信息:", client_addr)
  42. serve_client(client_socket)
  43. tcp_socket.close()

3 多进程实现

  1. from socket import *
  2. import re
  3. from multiprocessing import Process
  4. def serve_client(client_socket):
  5. request = client_socket.recv(1024).decode("utf-8")
  6. print("客户端发送的请求:", request) # 5
  7. # 读取请示中的文件名
  8. request_lines = request.splitlines()
  9. ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
  10. file_name = ""
  11. if ret:
  12. file_name = ret.group(1)
  13. print("-------------", file_name)
  14. # 设置默认界面
  15. if file_name == "/":
  16. file_name = "/index.html"
  17. # header是字符串,body是二进制,不能+=连在一起
  18. print("回复客户端...") # 6
  19. try:
  20. f = open("./html" + file_name, "rb")
  21. except: # 未找到文件
  22. response = "HTTP/1.1 404 NOT FOUND\n\n"
  23. response += "-----file not found-----"
  24. client_socket.send(response.encode("utf-8"))
  25. else: # 成功
  26. html_content = f.read()
  27. f.close()
  28. header = "HTTP/1.1 200 OK\n\n"
  29. client_socket.send(header.encode("utf-8"))
  30. client_socket.send(html_content)
  31. print("关闭套接字...") # 7
  32. client_socket.close()
  33. if __name__ == "__main__":
  34. print("创建套接字...") # 1
  35. tcp_socket = socket(AF_INET, SOCK_STREAM)
  36. print("绑定端口...") # 2
  37. tcp_socket.bind(("", 16054))
  38. print("变为监听套接字,只能被动接收...") # 3
  39. tcp_socket.listen(128)
  40. while True:
  41. print("接受客户端请求,分配一个客服套接字...") # 4
  42. client_socket, client_addr = tcp_socket.accept()
  43. print("客户端信息:", client_addr)
  44. p = Process(target=serve_client, args=(client_socket,))
  45. p.start()
  46. client_socket.close()
  47. tcp_socket.close()

4 多线程实现

  1. from socket import *
  2. import re
  3. from threading import Thread
  4. def serve_client(client_socket):
  5. request = client_socket.recv(1024).decode("utf-8")
  6. print("客户端发送的请求:", request) # 5
  7. # 读取请示中的文件名
  8. request_lines = request.splitlines()
  9. ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
  10. file_name = ""
  11. if ret:
  12. file_name = ret.group(1)
  13. print("-------------", file_name)
  14. # 设置默认界面
  15. if file_name == "/":
  16. file_name = "/index.html"
  17. # header是字符串,body是二进制,不能+=连在一起
  18. print("回复客户端...") # 6
  19. try:
  20. f = open("./html" + file_name, "rb")
  21. except: # 未找到文件
  22. response = "HTTP/1.1 404 NOT FOUND\n\n"
  23. response += "-----file not found-----"
  24. client_socket.send(response.encode("utf-8"))
  25. else: # 成功
  26. html_content = f.read()
  27. f.close()
  28. header = "HTTP/1.1 200 OK\n\n"
  29. client_socket.send(header.encode("utf-8"))
  30. client_socket.send(html_content)
  31. print("关闭套接字...") # 7
  32. client_socket.close()
  33. if __name__ == "__main__":
  34. print("创建套接字...") # 1
  35. tcp_socket = socket(AF_INET, SOCK_STREAM)
  36. print("绑定端口...") # 2
  37. tcp_socket.bind(("", 16054))
  38. print("变为监听套接字,只能被动接收...") # 3
  39. tcp_socket.listen(128)
  40. while True:
  41. print("接受客户端请求,分配一个客服套接字...") # 4
  42. client_socket, client_addr = tcp_socket.accept()
  43. print("客户端信息:", client_addr)
  44. p = Thread(target=serve_client, args=(client_socket,))
  45. p.start()
  46. tcp_socket.close()

5 gevent实现

  1. from socket import *
  2. import re
  3. import gevent
  4. from gevent import monkey
  5. import time
  6. monkey.patch_all()
  7. def serve_client(client_socket):
  8. request = client_socket.recv(1024).decode("utf-8")
  9. print("客户端发送的请求:", request) # 5
  10. # 读取请示中的文件名
  11. request_lines = request.splitlines()
  12. ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
  13. file_name = ""
  14. if ret:
  15. file_name = ret.group(1)
  16. print("-------------", file_name)
  17. # 设置默认界面
  18. if file_name == "/":
  19. file_name = "/index.html"
  20. # header是字符串,body是二进制,不能+=连在一起
  21. print("回复客户端...") # 6
  22. try:
  23. f = open("./html" + file_name, "rb")
  24. except: # 未找到文件
  25. response = "HTTP/1.1 404 NOT FOUND\n\n"
  26. response += "-----file not found-----"
  27. client_socket.send(response.encode("utf-8"))
  28. else: # 成功
  29. html_content = f.read()
  30. f.close()
  31. header = "HTTP/1.1 200 OK\n\n"
  32. client_socket.send(header.encode("utf-8"))
  33. client_socket.send(html_content)
  34. print("关闭套接字...") # 7
  35. client_socket.close()
  36. if __name__ == "__main__":
  37. print("创建套接字...") # 1
  38. tcp_socket = socket(AF_INET, SOCK_STREAM)
  39. tcp_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
  40. print("绑定端口...") # 2
  41. tcp_socket.bind(("", 7890))
  42. print("变为监听套接字,只能被动接收...") # 3
  43. tcp_socket.listen(128)
  44. while True:
  45. print("接受客户端请求,分配一个客服套接字...") # 4
  46. client_socket, client_addr = tcp_socket.accept()
  47. print("客户端信息:", client_addr)
  48. gevent.spawn(serve_client, client_socket)
  49. time.sleep(0.01)
  50. tcp_socket.close()

6 面向对象实现

  1. #!/usr/bin/env python
  2. from socket import *
  3. from threading import Thread
  4. import sys
  5. class HttpServer():
  6. def __init__(self, port):
  7. self.server = socket()
  8. self.server.setsockopt(SOL_SOCKET, SO_REUSEADDR, True)
  9. self.server.bind(('', port))
  10. self.server.listen()
  11. def handle_request(self, conn: socket):
  12. try:
  13. data = conn.recv(4096)
  14. except:
  15. print('接收数据发生异常')
  16. return
  17. if len(data) == 0:
  18. return
  19. content = data.decode()
  20. request_lines = content.split(' ', 2)
  21. path = request_lines[1]
  22. if path == '/':
  23. path = '/index.html'
  24. try:
  25. with open('static'+path, 'rb') as f:
  26. response_body = f.read()
  27. response_line = 'HTTP/1.1 200 OK\n'
  28. response_header = 'Server: CPALyth/1.1\n'
  29. except:
  30. with open('static/404.html', 'rb') as f:
  31. response_body = f.read()
  32. response_line = 'HTTP/1.1 404 Not Found\n'
  33. response_header = 'Server: CPALyth/1.1\n'
  34. response = (response_line + response_header + '\n').encode() + response_body
  35. conn.send(response)
  36. def start(self):
  37. while True:
  38. print('等待客户端...')
  39. conn, addr = self.server.accept()
  40. Thread(target=self.handle_request, args=(conn,), daemon=True).start()
  41. if __name__ == '__main__':
  42. web_server = HttpServer(8000)
  43. web_server.start()

7 实现上传图片

(1) 服务端

  1. #!/usr/bin/env python
  2. from socket import *
  3. from threading import Thread
  4. import re
  5. import base64
  6. class HttpServer():
  7. def __init__(self, port):
  8. self.server = socket()
  9. self.server.setsockopt(SOL_SOCKET, SO_REUSEADDR, True)
  10. self.server.bind(('', port))
  11. self.server.listen()
  12. def handle_request(self, conn: socket):
  13. while True:
  14. print('正在等待客户端发送消息...')
  15. try:
  16. data = conn.recv(4096)
  17. except:
  18. data = ''
  19. if len(data) == 0:
  20. conn.close()
  21. return
  22. content = data.decode()
  23. request_line = content.split(' ', 2)
  24. method = request_line[0]
  25. if method == 'GET': # 获取服务器资源
  26. path = request_line[1]
  27. self.get(conn, path)
  28. elif method == 'POST': # 上传文件到服务器
  29. ret = re.search(r'Content-type: (.+)\n', content)
  30. content_type = ret.group(1) if ret else None
  31. ret = re.search(r'\n\n(.+)', content)
  32. body = ret.group(1) if ret else None
  33. self.post(conn, content_type, body)
  34. def get(self, conn, path):
  35. if path == '/':
  36. path = '/index.html'
  37. try:
  38. with open('static' + path, 'r', encoding='utf8') as f:
  39. response_body = f.read()
  40. response_line = 'HTTP/1.1 200 OK\n'
  41. response_header = 'Server: CPALyth/1.1\n'
  42. except:
  43. with open('static/404.html', 'r', encoding='utf8') as f:
  44. response_body = f.read()
  45. response_line = 'HTTP/1.1 404 Not Found\n'
  46. response_header = 'Server: CPALyth/1.1\n'
  47. response = (response_line + response_header + '\n' + response_body).encode()
  48. conn.send(response)
  49. def post(self, conn, content_type, body):
  50. if content_type == 'images/png':
  51. body_b64 = body.encode()
  52. img_data = base64.b64decode(body_b64)
  53. with open('out.png', 'wb') as f:
  54. f.write(img_data)
  55. response = ('HTTP/1.1 200 OK\n' + 'Server: CPALyth/1.1\n' + '\n' + '上传成功').encode()
  56. conn.send(response)
  57. def start(self):
  58. while True:
  59. print('等待客户端...')
  60. conn, addr = self.server.accept()
  61. Thread(target=self.handle_request, args=(conn,), daemon=True).start()
  62. if __name__ == '__main__':
  63. web_server = HttpServer(8000)
  64. web_server.start()

(2) 客户端

  1. from socket import *
  2. import base64
  3. class HttpClient():
  4. def __init__(self):
  5. self.conn = socket()
  6. self.conn.connect(('192.168.3.67', 8000))
  7. def get_index(self):
  8. request_line = 'GET / HTTP/1.1\n'
  9. request_header = 'User-Agent: Python\n'
  10. request_body = ''
  11. request = (request_line + request_header + '\n' + request_body).encode()
  12. self.conn.send(request)
  13. response = self.conn.recv(4096).decode()
  14. print(response)
  15. def upload_pic(self):
  16. request_line = 'POST / HTTP/1.1\n'
  17. request_header = 'Content-type: images/png\n'
  18. # 图片先读取bytes, 再编码为base64, 再解码为utf8
  19. with open('1.png', 'rb') as f:
  20. request_body = base64.b64encode(f.read()).decode()
  21. request = (request_line + request_header + '\n' + request_body).encode()
  22. self.conn.send(request)
  23. response = self.conn.recv(4096).decode()
  24. print(response)
  25. cli = HttpClient()
  26. # cli.get_index()
  27. cli.upload_pic()