python高级-socket和web相关

目录

一、socket

1.客户端开发

2.tcp客户端

3.tcp服务端

4.连接的注意事项

5.多任务服务端

二、静态web

1.请求报文

2.响应头

3.静态web服务器

4.socket静态页面

5.多进程模拟404和200状态码

6.面向对象多任务

结语


一、socket

1.客户端开发

  1. 创建客户端套接字对象
  2. 和服务端套接字建立连接
  3. 发送数据
  4. 接收数据
  5. 关闭客户端套接字
  6. 对应状态

导入socket模块

import socket

创建客户端socket对象

socket.socket(AddressFamily,Type)

参数说明:

AddressFamily表示ip地址类型,分为ipv4和ipv6

Type表示传输协议类型

方法说明

  • connect(host,port)表示和服务端套接字建立连接,host是服务器ip地址,port是应用程序的端口号
  • send(data)表示发送数据,data是二进制数据
  • recv(buffersize)表示接收数据,buffersize是每次接收数据的长度

2.tcp客户端


import socket



if __name__ = 'main':
    #socket.AF_INET:代表ipv4     socket.SOCK_STREAM tcp传输协议
    tcp_client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    
    #服务端192.168.131.62 8000端口建立连接
    tcp_client_socket.connect(('192.168.131.62',8000))
    
    #代码执行到此,说明链接建立成功
    #准备发送的数据
    send_data = "您好服务端,我是客户端的小明".encode("gbk")
    
    #发送数据
    tcp_client_socket.send(send_data)
    
    #接收数据,这次接受的数据最大字节数是1024
    recv_data = tcp_client_socket.recv(1024)
    
    #返回的直接是服务端程序发送的二进制
    print(recv_data)
    
    #解码输出
    recv_content = recv_data.decode("gbk")
    print("接受服务端的数据为:",recv_content)
    
    #关闭套接字
    tcp_client_socket.close()
    

3.tcp服务端


import socket



if __name__ == '__main__':

    #socket.AF_INET:代表ipv4     socket.SOCK_STREAM tcp传输协议
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

    #设置端口号复用,让程序推出端口号立刻释放
    tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)

    #给程序绑定端口号
    tcp_server_socket.bind(("",8989))

    #设置最大等待建立连接的个数,目前是单任务服务端,后续会用多任务
    tcp_server_socket.listen(128)

    #解包
    service_client_socket,ip_port = tcp_server_socket.accept()

    #代码执行到此说明连接建立成功
    print("ip和port: ",ip_port)

    #接受客户端发送的数据,这次接受数据的最大字节数是(1024)
    recv_data = service_client_socket.recv(1024)

    recv_data_len = len(recv_data)
    print("接受客户端的数据的长度为:",recv_data_len)
    print("接受客户端的数据为:",recv_data)

    #解码
    rev_de_data = recv_data.decode("gbk")
    print("解码后的客户端数据: ",rev_de_data)

    #关闭套接字
    tcp_server_socket.close()


4.连接的注意事项

  • 当tcp客户端程序想和tcp服务端程序进行通信的时候必须要先建立连接
  • tcp客户端程序一般不一定需要绑定端口号,因为客户端时主动发起连接的
  • TCP服务端程序必须绑定端口号,否则客户端找不到这个tcp服务端程序
  • listen后的套接字时被动套接字,只负责接收新的客户端连接请求,不能收发消息。
  • 当TCP客户端程序和TCP服务端程序连接成功后,TCP服务端程序会产生一个新的套接字,收发客户端使用该套接字
  • 关闭accept返回的套接字意味着和这个客户端已经通信完毕。
  • 关闭listen后的套接字意味着服务端的套接字已经关闭了,会导致新的客户端不能连接服务端,但之前已经连接成功的客户端还能正常通信。
  • 当客户端的套接字调用close后,服务端的recv会解阻塞,返回的数据长度为0,服务端可以通过返回数据的长度来判断客户端是否已经下线,反之服务端关闭套接字,客户端的recv也会阻塞,返回的数据长度为0。

5.多任务服务端

  • 编写一个tcp服务端程序,循环等待接受客户端的连接请求
  • 当客户端和服务端建立连接成功,创捷子线程,使用子线程专门处理客户端的请求,防止主线程阻塞
  • 把创建的子线程设置为守护主线程,防止主线程无法退出
import socket
import threading

def handle_client_r(service_client_socket,ip_port):
    #单客户端内部循环检测
    while True:
        #循环接受客户端发送的数据
        #接受客户端发送的数据
        recv_d = service_client_socket.recv(1024)

        #容器类型判断是否有数据可以直接使用if语句进行判断,如果容器类型里面有数据表示条件成立
        #容器类型:列表、字典、元组、字符串、set、range、二进制数组
        if recv_d:
            print(recv_d.decode("gbk"),ip_port)

            #回复
            service_client_socket.send("你好我是服务端。。。。".encode("gbk"))
        else:
            print("客户端下线了: ",ip_port)
            break

    service_client_socket.close()
if __name__ == '__main__':
    #创建tcp服务端套接字
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

    #设置端口号复用,让程序推出端口号立即释放
    tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)

    #绑定端口号
    tcp_server_socket.bind(("",9090))

    #设置监听,listen后的套接字是被动套接字,只负责接收客户端的连接请求
    tcp_server_socket.listen(128)
    
    #多客户端socket
    while True:
        #等待接收客户端的连接请求
        service_client_s,ip_port = tcp_server_socket.accept()
        print("客户端连接成功: ",ip_port)

        #当客户端和服务端建立连接成功后,需要创建一个子线程,不同子线程负责接受不同客户端的消息
        sub_t = threading.Thread(target=handle_client_r,args=(service_client_s,ip_port))

        #设置守护主线程
        sub_t.setDaemon(True)

        #启动子线程
        sub_t.start()

import socket
import threading

class SocketServer(object):
    def __init__(self):
        # 创建tcp服务端套接字
        self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        # 设置端口号复用,让程序推出端口号立即释放
        self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)

        # 绑定端口号
        self.tcp_server_socket.bind(("",6666))

        # 设置监听,listen后的套接字是被动套接字,只负责接收客户端的连接请求
        self.tcp_server_socket.listen(128)

    def start(self):
        #多客户端socket
        while True:
            #等待接收客户端的连接请求
            service_client_s,ip_port = self.tcp_server_socket.accept()
            print("客户端连接成功: ",ip_port)

            #当客户端和服务端建立连接成功后,需要创建一个子线程,不同子线程负责接受不同客户端的消息
            sub_t = threading.Thread(target=self.client_t,args=(service_client_s,ip_port))

            #设置守护主线程
            sub_t.setDaemon(True)

            #启动子线程
            sub_t.start()

        self.tcp_server_socket.close()

    def client_t(self,service_client_socket,ip_port):
        print(ip_port,"  连接上来了")
        #单客户端内部循环检测
        while True:
            #循环接受客户端发送的数据
            #接受客户端发送的数据
            recv_d = service_client_socket.recv(1024).decode('gbk')

            #容器类型判断是否有数据可以直接使用if语句进行判断,如果容器类型里面有数据表示条件成立
            #容器类型:列表、字典、元组、字符串、set、range、二进制数组
            if len(recv_d) != 0:
                print(f'客户端{ip_port[0]} 发来的消息是{recv_d}')
            else:
                print(f'客户端{ip_port[0]} 已断开连接,下次再见。。。。')
                break
            send_data = ('Hello 我是服务端 --'+recv_d).encode('gbk')
            service_client_socket.send(send_data)

if __name__ == '__main__':
    server = SocketServer()
    server.start()


二、静态web

1.请求报文

2.响应头

响应码

3.静态web服务器

python3 -m http.server

http://127.0.0.1:8000/index1.html

http://0.0.0.0:8000/

4.socket静态页面


import socket



if __name__ == '__main__':
    #创建tcp服务端套接字
    tcp_serv_s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

    #设置端口号复用
    tcp_serv_s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)

    #端口绑定
    tcp_serv_s.bind(("",9000))

    #设置监听
    tcp_serv_s.listen(128)

    while True:
        #等待接受客户端的连接请求
        new_socket,ip_port = tcp_serv_s.accept()

        #代码执行到此,说明连接建立成功
        recv_c_d = new_socket.recv(4096)

        #对接收的客户端的请求包头进行二进制解码
        recv_c_con = recv_c_d.decode("utf-8")
        print(recv_c_con)

        with open("./index1.html",'rb') as f:
            f_d = f.read()

        #相应行
        response_l = "HTTP/1.1 200 OK\r\n"

        #响应头
        response_h = "Server: PWS1.0\r\n"

        #响应体
        response_b = f_d

        #拼接响应报文
        res_d = (response_l+response_h+"\r\n").encode("utf-8") + response_b

        #发送数据
        new_socket.send(res_d)

new_socket.close()

5.多进程模拟404和200状态码

import multiprocessing
import socket


def serv_start(port):
    server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
    server.bind(("",port))
    server.listen(128)

    while True:
        client,ip_port = server.accept()
        print(f"客户端{ip_port[0]} 使用{ip_port[1]} 端口连接成功")

        p = multiprocessing.Process(target=task,args=(client,))
        p.start()
    server.close()

def task(client):
    request_data = client.recv(1024).decode('utf-8')
    if len(request_data) == 0:
        client.close()
    else:
        request_path = request_data.split(' ')[1]
        print("请求地址是: ",request_path)

        print("request:  ",request_path)

        if request_path == '/':
            request_path = 'index1.html'

        try:
            with open('./'+request_path,'rb') as f:
                file_con = f.read()
        except Exception as e:
            response_line = "HTTP/1.1 404 NOT FOUND\r\n"
            response_head = "Server: PSWS1.1\r\n"
            with open('./err.html','rb') as f:
                error_data = f.read()

            response_data = (response_line+response_head+'\r\n').encode('utf-8') + error_data

            client.send(response_data)

        else:
            response_line = "HTTP/1.1 200 OK\r\n"
            response_head = "Server: PSWS1.1\r\n"
            with open('./'+request_path,'rb') as f:
                response_body = f.read()

            response_data = (response_line+response_head+'\r\n').encode() + response_body

            client.send(response_data)
        finally:
            client.close()


if __name__ == '__main__':
    serv_start(7777)




 

6.面向对象多任务

import multiprocessing
import socket


class server_start(object):
    def __init__(self,port):
        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
        self.server.bind(("", port))
        self.server.listen(128)



    def start(self):
        while True:
            client,ip_port = self.server.accept()
            print(f"客户端{ip_port[0]} 使用{ip_port[1]} 端口连接成功")

            p = multiprocessing.Process(target=self.task,args=(client,))
            p.start()
        self.server.close()

    def task(self,client):
        request_data = client.recv(1024).decode('utf-8')
        if len(request_data) == 0:
            client.close()
        else:
            request_path = request_data.split(' ')[1]
            print("请求地址是: ",request_path)

            print("request:  ",request_path)

            if request_path == '/':
                request_path = 'index1.html'

            try:
                with open('./'+request_path,'rb') as f:
                    file_con = f.read()
            except Exception as e:
                response_line = "HTTP/1.1 404 NOT FOUND\r\n"
                response_head = "Server: PSWS1.1\r\n"
                with open('./err.html','rb') as f:
                    error_data = f.read()

                response_data = (response_line+response_head+'\r\n').encode('utf-8') + error_data

                client.send(response_data)

            else:
                response_line = "HTTP/1.1 200 OK\r\n"
                response_head = "Server: PSWS1.1\r\n"
                with open('./'+request_path,'rb') as f:
                    response_body = f.read()

                response_data = (response_line+response_head+'\r\n').encode() + response_body

                client.send(response_data)
            finally:
                client.close()


if __name__ == '__main__':
    server_start(7777).start()


结语

点赞👍

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白帽小丑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值