00071-套接字初探


前言

利用 Python 标准库 socket 实现多线程 echo 和 http 程序.

源教程地址: https://www.bilibili.com/video/BV1eg411G7pW/?vd_source=547d8a3d2ce70a88f0a699636396bd6f .

想要了解套接字更多的内容可以阅读 TCP/IP网络编程.

操作系统:Ubuntu 20.04.6 LTS

参考文档

  1. TCP/IP网络通信之Socket编程入门

  2. socket

echo

  1. 在服务器上编写 server.py。服务器 IP 地址为 10.4.3.155
# nc 是linux 下网络测试工具, 可以读写 TCP/UDP 的数据
# Windows 的替代版本 (nmap): https://nmap.org/
# 使用方法,在客户端运行下面命令:
#
# nc 服务器IP地址 端口号
#
# 本案例的测试命令为:
#
# nc 10.4.3.155 1234

import socket
import threading
import os

WEBROOT = os.path.dirname(__file__)

# echo 程序
def handle_client(c, addr):
    print(addr, "connected.")

    while True:
        data = c.recv(1024)
        if not data:
            break
        c.sendall(data)

# http 程序
def handle_http(c, addr):
    print(addr, "connected.")

    with c:
        request = c.recv(1024)

        # Parse HTTP headers
        headers = request.split(b"\r\n")
        file = headers[0].split()[1].decode()

        # Load file content
        if file == "/":
            file = "/index.html"

        try:
            with open(WEBROOT + file, "rb") as f:
                content = f.read()
            response = b"HTTP/1.0 200 OK\r\n\r\n" + content
        except FileNotFoundErrot:
            response = b"HTTP/1.0 404 NOT FOUND\r\n\r\nFile not found!"

        # Send HTTP response
        c.sendall(response)

# socket.AF_INET 表示 IPv4 地址家族
# socket.SOCK_STREAM 表示 TCP 协议
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    # 服务器 IP 地址, 即运行本脚本的主机地址
    s.bind(("10.4.3.155", 1234))
    s.listen()

    while True:
        c, addr = s.accept()

        t = threading.Thread(target=handle_client, args=(c, addr))
        #t = threading.Thread(target=handle_http, args=(c, addr))
        t.start()
  1. 在本地计算机上编写客户端脚本 client.py
#!/usr/bin/env python
# coding=utf-8
import socket

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect(("10.4.3.155", 1234))
    s.sendall(b"Hello, lyf!")
    data = s.recv(1024)
    print("Received: ", repr(data))
  1. 在服务器上运行 server.py

  2. 在客户端上运行 client.py


运行结果

  1. 服务器:
(base) luyanfeng@amax:~/my_code/temp$ ls
index.html  server.py
(base) luyanfeng@amax:~/my_code/temp$ python server.py 
('10.4.3.151', 47222) connected.
('10.4.3.151', 40348) connected.
('10.4.3.151', 53850) connected.
^CTraceback (most recent call last):
  File "/home/luyanfeng/my_code/temp/server.py", line 60, in <module>
    c, addr = s.accept()
  File "/home/luyanfeng/miniconda3/lib/python3.9/socket.py", line 293, in accept
    fd, addr = self._accept()
KeyboardInterrupt

(base) luyanfeng@amax:~/my_code/temp$
  1. 客户端:
(base) lyfubuntu@lyfubuntu:~/my_computer_language/temp$ ls
client.py
(base) lyfubuntu@lyfubuntu:~/my_computer_language/temp$ python client.py 
Received:  b'Hello, lyf!'
(base) lyfubuntu@lyfubuntu:~/my_computer_language/temp$ python client.py 
Received:  b'Hello, lyf!'
(base) lyfubuntu@lyfubuntu:~/my_computer_language/temp$ python client.py 
Received:  b'Hello, lyf!'
(base) lyfubuntu@lyfubuntu:~/my_computer_language/temp$

http

  1. 在服务器上编写 server.py。服务器 IP 地址为 10.4.3.155
# nc 是linux 下网络测试工具, 可以读写 TCP/UDP 的数据
# Windows 的替代版本 (nmap): https://nmap.org/
# 使用方法,在客户端运行下面命令:
#
# nc 服务器IP地址 端口号
#
# 本案例的测试命令为:
#
# nc 10.4.3.155 1234

import socket
import threading
import os

WEBROOT = os.path.dirname(__file__)

# echo 程序
def handle_client(c, addr):
    print(addr, "connected.")

    while True:
        data = c.recv(1024)
        if not data:
            break
        c.sendall(data)

# http 程序
def handle_http(c, addr):
    print(addr, "connected.")

    with c:
        request = c.recv(1024)

        # Parse HTTP headers
        headers = request.split(b"\r\n")
        file = headers[0].split()[1].decode()

        # Load file content
        if file == "/":
            file = "/index.html"

        try:
            with open(WEBROOT + file, "rb") as f:
                content = f.read()
            response = b"HTTP/1.0 200 OK\r\n\r\n" + content
        except FileNotFoundErrot:
            response = b"HTTP/1.0 404 NOT FOUND\r\n\r\nFile not found!"

        # Send HTTP response
        c.sendall(response)

# socket.AF_INET 表示 IPv4 地址家族
# socket.SOCK_STREAM 表示 TCP 协议
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    # 服务器 IP 地址, 即运行本脚本的主机地址
    s.bind(("10.4.3.155", 1234))
    s.listen()

    while True:
        c, addr = s.accept()

        #t = threading.Thread(target=handle_client, args=(c, addr))
        t = threading.Thread(target=handle_http, args=(c, addr))
        t.start()
  1. server.py 同级目录下编写 index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>My test page</title>
  </head>
  <body>
    <p>My cat is very grumpy</p>
  </body>
</html>
  1. 在服务器上运行 server.py

运行结果

  1. 打开本地浏览器,输入 http://10.4.3.155:1234/

结语

第七十一篇博文写完,开心!!!!

今天,也是充满希望的一天。


文章作者: LuYF-Lemon-love
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 LuYF-Lemon-love !
  目录