首页 > 编程语言 >如何用Python实现http客户端和服务器

如何用Python实现http客户端和服务器

时间:2023-01-23 15:34:45浏览次数:49  
标签:http socket Python header r1 print path 客户端 name

功能:客户端可以向服务器发送get,post等请求,而服务器端可以接收这些请求,并返回给客户端消息。

客户端:

#coding=utf-8
import http.client
from urllib import request, parse


def send_get(url,path,data):#get请求函数
    conn = http.client.HTTPConnection(url)
    conn.request("GET", path)
    r1 = conn.getresponse()
    print(r1.status, r1.reason)

    data1 = r1.read()
    print(data1)  #
    conn.close()

def send_post(url,path,data,header):#post请求函数
    conn = http.client.HTTPConnection(url)#建立连接
    conn.request("POST", path,data,header)#用request请求,将信息封装成帧
    r1 = conn.getresponse()
    print(r1.status, r1.reason)

    data1 = r1.read()
    print(data1)  #
    conn.close()
def send_head(url,path,data,header):
    conn = http.client.HTTPConnection(url)
    conn.request("HEAD", path,data,header)
    r1 = conn.getresponse()
    print(r1.status, r1.reason)
    data1 = r1.headers  #
    print(data1)  #
    conn.close()
def send_put(url,path,filedata,header):
    conn = http.client.HTTPConnection(url)
    conn.request("PUT", path,filedata,header)
    r1 = conn.getresponse()
    print(r1.status, r1.reason)

    data1 = r1.read()  #
    print(data1)
    conn.close()
def send_option(url,path,data,header):
    conn = http.client.HTTPConnection(url)
    conn.request("OPTION", path,data,header)
    r1 = conn.getresponse()
    print(r1.status, r1.reason)
    data1 = r1.headers  #
    print(data1)  #
    conn.close()
def delete_option(url,path,filename,header):
    conn = http.client.HTTPConnection(url)
    conn.request("DELETE", path, filename, header)
    r1 = conn.getresponse()
    print(r1.status, r1.reason)

    data1 = r1.read()  #
    print(data1)
    conn.close()
if __name__ == '__main__':

    url="localhost:8100"
    data = {
        'my post data': 'I am client , hello world',
    }
    datas = parse.urlencode(data).encode('utf-8')

    headers = {"Content-type": "application/x-www-form-urlencoded","Accept": "text/plain"}
    while True:
        command = input("输入请求的命令:")
        if command =='get':
            print("----------发送get请求:-----------")
            send_get(url,path="",data="None")
        elif command=='post':
            print("----------发送post请求-----------")
            send_post(url, path="",data=datas,header=headers)

        elif command =='put':
            print("----------发送put请求-----------")
            file = input("输入要发送的文件名:")
            tfile=open(file,encoding="UTF-8",mode='r')
            filedatas=tfile.read()
            fileheaders = {"Content-type": "text/plain", "Accept": "text/plain",\
                           "content-length":str(len(filedatas))}
            send_put(url, path="E:/pythonProject2/httpweb/", filedata=filedatas, header=fileheaders)
        elif command=='head':
            print("----------发送head请求:-----------")
            send_head(url, path="", data=datas, header=headers)
        elif command=='option':
            print("----------发送option请求:-----------")
            send_option(url,path="",data=datas,header=headers)
        elif command=='delete':
            print("----------发送delete请求-----------")
            file = input("输入要删除的文件名:")
            fileheaders = {"Content-type": "text/plain", "Accept": "text/plain"}
            delete_option(url, path="E:/pythonProject2/httpweb/", filename = file, header=fileheaders)
        elif command == 'exit':
            break

服务器:

# -*- coding: utf-8 -*-

import socket
import re
import os
import threading
import urllib.parse


def service_client(new_socket):
    # 为这个客户端返回数据
    # 1.接收浏览器发过来的请求,即http请求
    # GET / HTTP/1.1
    request = new_socket.recv(1024).decode('utf-8')
    request_header_lines = request.splitlines()
    print(request_header_lines)
    data = request_header_lines[-1]
    # ret = re.match(r'[^/]+(/[^ ]*)', request_header_lines[0])
    ret =  list(request_header_lines[0].split(' '))[1]
    method = list(request_header_lines[0].split(' '))[0]
    path_name = "/"

    if method == 'GET':
        if ret:
            path = ret
            path_name = urllib.parse.unquote(path)  # 浏览器请求的路径中带有中文,会被自动编码,需要先解码成中文,才能找到后台中对应的html文件
            print("请求路径:{}".format(path_name))

        if path_name == "/":  # 用户请求/时,返回咖啡.html页面
            path_name = "/咖啡.html"

        # 2.返回http格式的数据给浏览器
        file_name = 'E:/pythonProject2/httpweb/HTML/' + path_name
        try:
            f = open(file_name, 'rb')
        except:
            response = "HTTP/1.1 404 NOT FOUND\r\n"
            response += "\r\n"
            response += "------file not found------"
            new_socket.send(response.encode("utf-8"))
        else:
            html_content = f.read()
            f.close()
            # 准备发给浏览器的数据 -- header
            response = "HTTP/1.1 200 OK\r\n"
            response += "\r\n"
            new_socket.send(response.encode("utf-8"))
            new_socket.send(html_content)
            # 关闭套接字
    if method == 'POST':
        if ret:
            path = ret
            path_name = urllib.parse.unquote(path)  # 浏览器请求的路径中带有中文,会被自动编码,需要先解码成中文,才能找到后台中对应的html文件
            print("请求路径:{}".format(path_name))
        if path_name == "/":  # 用户请求/时,返回咖啡.html页面
            path_name = "/咖啡.html"

        # 2.返回http格式的数据给浏览器
        file_name = 'E:/pythonProject2/httpweb/HTML/' + path_name
        response = "HTTP/1.1 200 OK\r\n"
        response += "\r\n"
        new_socket.send(response.encode("utf-8"))
        new_socket.send(file_name.encode("utf-8")+'    data:'.encode("utf-8")+data.encode("utf-8"))
    if method == 'PUT':
        if ret:
            path = ret
            path_name = urllib.parse.unquote(path)  # 浏览器请求的路径中带有中文,会被自动编码,需要先解码成中文,才能找到后台中对应的html文件
            print("请求路径:{}".format(path_name))
        if path_name == "/":  # 用户请求/时,返回咖啡.html页面
            path_name = "/咖啡.html"

        # 2.返回http格式的数据给浏览器
        file_name = list(request_header_lines[0].split(' '))[1] +'test.txt'
        content = data.encode('utf-8')
        response = "HTTP/1.1 200 OK\r\n"
        response += "\r\n"
        with open(file_name, 'ab') as f:
            f.write(content)
        new_socket.send(response.encode("utf-8"))
        new_socket.send("finish".encode("utf-8"))
    if method=='HEAD':
        if ret:
            path =ret
            path_name = urllib.parse.unquote(path)
            print("请求路径:{}".format(path_name))
        if path_name =="/":
            path_name = "/咖啡.html"
        response = "HTTP/1.1 200 ok\r\n"
        new_socket.send(response.encode("utf-8"))
        new_socket.send(str(request_header_lines[1:]).encode("utf-8"))
    if method=='OPTION':
        if ret:
            path = ret
            path_name = urllib.parse.unquote(path)
            print("请求路径:{}".format(path_name))
        if path_name == "/":
            path_name = "/咖啡.html"
        response = "HTTP/1.1 200 ok\r\n"
        new_socket.send(response.encode("utf-8"))
        new_socket.send("OPTIONS GET,HEAD,POST,PUT,DELETE".encode("utf-8"))
    if method =='DELETE':
        if ret:
            path = ret
            path_name = urllib.parse.unquote(path)  # 浏览器请求的路径中带有中文,会被自动编码,需要先解码成中文,才能找到后台中对应的html文件
            print("请求路径:{}".format(path_name))
        if path_name == "/":  # 用户请求/时,返回咖啡.html页面
            path_name = "/咖啡.html"

        deletename = request_header_lines[-1]
        # print(path_name+deletename)
        os.remove(path_name+deletename)
        # 2.返回http格式的数据给浏览器
        content = data.encode('utf-8')
        response = "HTTP/1.1 200 OK\r\n"
        response += "\r\n"
        # with open(file_name, 'ab') as f:
        #     f.write(content)
        new_socket.send(response.encode("utf-8"))
        new_socket.send("finish".encode("utf-8"))
    # 关闭套接字
    new_socket.close()


def main():
    # 用来完成整体的控制
    # 1.创建套接字
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 2.绑定
    tcp_server_socket.bind(("0.0.0.0", 8100))
    # 3.变为监听套接字
    tcp_server_socket.listen(128)
    while True:
        # 4.等待新客户端的链接
        new_socket, client_addr = tcp_server_socket.accept()
        # 5.为这个客户端服务
        print("为",client_addr,"服务")
        t = threading.Thread(target=service_client, args=(new_socket,))
        t.start()

    # 关闭监听套接字
    tcp_server_socket.close()


if __name__ == '__main__':
    main()

标签:http,socket,Python,header,r1,print,path,客户端,name
From: https://www.cnblogs.com/xiaohai123/p/17065221.html

相关文章

  • python3 获取request 302跳转后最终的URL
    python3获取request302跳转后最终的URL代码:importrequestsresp=requests.get(rtsp_url,timeout=(3,7))iflen(resp.history)>0:location_url=......
  • nginx http2 导致safari浏览器XMLHttpRequest cannot load错误
    环境说明nginx:1.22.0safari:13+curl:7.68.0ubuntu:20.04问题说明[Error]Thenetworkconnectionwaslost.[Error]XMLHttpRequestcannotloadxxxduetoaccesscon......
  • python 控制鼠标操作
    importtimeimportpyautogui##必须以管理员身份运行此程序,不然鼠标点击会没有效果!!!defmoveAndClick():print("startapp")x,y=976,748#鼠标需要移动到的位......
  • Python语言基础—集合的常见操作方法
    希望本阶段内容可以帮助大家学好Python基础,详情可以关注上方Python专栏!文章目录​​系列文章目录​​​​一、创建集合​​​​二、集合常见操作方法​​​​2.1增加数据​......
  • Python语言基础—列表的常用操作
    希望本阶段内容可以帮助大家学好Python基础,详情可以关注上方Python专栏!文章目录​​系列文章目录​​​​一、列表的应用场景​​​​二、列表的格式​​​​三、列表的常用......
  • http和https到底啥关系?
    对应测试人员都会听过http请求和响应.在这里给大家介绍http相关的知识一.http和https基本概念HTTP:是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答......
  • 【Python基础学习】4.程序的控制结构
    主要参考来源:慕课嵩天老师的“Python语言程序设计”[https://www.icourse163.org/course/BIT-268001?tid=1468130447]4.1程序的分支结构:顺序结构、分支结构、循环结构单......
  • python 批量修改文件文件名,文件类型
    相关文章使用python批量修改文件名https://blog.csdn.net/m0_45447650/article/details/126859424Python批量修改文件名https://www.cnblogs.com/gooutlook/p/1637127......
  • Python 内置界面开发框架 Tkinter入门篇
    本文大概4158个字,阅读需花10分钟内容不多,但也花了一些精力如要交流,欢迎关注我然后评论区留言谢谢你的点赞收藏分享首先,今天先给大家拜个好年!新年快乐,恭喜发财!为了......
  • python pil 图片缩放
    #安装pil#cmd-->pipinstallpillowfromPILimportImagedefPicture_zoom():#加载图片im=Image.open("./pic/spring/b0.png")#获得图片的长宽......