python-TCP 通信与 Web 服务器

这篇具有很好参考价值的文章主要介绍了python-TCP 通信与 Web 服务器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一 . 实验目的

熟悉基于 Python 进行 TCP 套接字编程的基础知识,理解 HTTP 报文格式,能基于 Python 编写一个可以一次响应一个 HTTP 请求,并返回静态文件的简单 Web 服务器。

二 . 实验内容

利用 Python 开发一个可以一次处理一个 HTTP 请求的 Web 服务器,该服务器可以接受并解析HTTP 请求,然后从服务器的文件系统中读取被 HTTP 请求的文件,并根据该文件是否存在而向客户端发送正确的响应消息。

三 . 实验原理

基于 TCP 的面向客户端/服务器在 Python 实现中的的工作流程是:

1. 首先在服务器端通过调用 s o c k e t ( ) 创建套接字来启动一个服务器;

2. 服务器调用 b i n d ( ) 绑定指定服务器的套接字地址(IP 地址 + 端口号);

3. 服务器调用 l i s t e n ( ) 做好侦听准备,同时规定好请求队列的长度;

4. 服务器进入阻塞状态,等待客户的连接请求;

5. 服务器通过 a c c e p t ( ) 来接收连接请求,并获得客户的 socket 地址。

6. 在客户端通过调用 s o c k e t ( ) 创建套接字;

7. 客户端调用 c o n n e c t ( ) 和服务器建立连接。

8. 连接建立成功后,客户端和服务器之间通过调用 r e a d ( ) 和 w r i t e ( ) 来接收和发送数据。

9. 数据传输结束后,服务器和客户各自通过调用 c l o s e ( ) 关闭套接字。

基于 Python的 TCP 客户端/服务器具体工作流程如图1所示。

python-TCP 通信与 Web 服务器

 文章来源地址https://www.toymoban.com/news/detail-439577.html

四 . 实验条件

• 装有 python 环境的电脑一台(使用两个终端模拟两台电脑/进程);

• 局域网环境;

• 部分代码;

• Python 语言参考手册 – TCP 部分;

• HTTP 协议参考手册。

五 . 实验步骤

逐步填充代码中不完善的部分,并完成一个具有以下功能的简单 Web 服务器:

1. 服务器收到请求时能创建一个 TCP 套接字;

2. 可以通过这个 TCP 套接字接收 HTTP 请求;

3. 解析 HTTP 请求并在操作系统中确定客户端所请求的特定文件;

4. 从服务器的文件系统读取客户端请求的文件;

5. 当被请求文件存在时,创建一个由被请求的文件组成的“请求成功”HTTP 响应报文;

6. 当被请求文件不存在时,创建“请求目标不存在”HTTP 响应报文;

7. 通过 TCP 连接将响应报文发回客户端。

六 . 进阶任务

本实验中的 Web 服务器一次只能处理一个 HTTP 请求,请自行查阅线程知识,修改代码,实现一个能够同时处理多个请求的多线程服务器。

七 . 注意事项及说明

客户端发来的 HTTP 请求中,URL 都是相对根“/”的相对路径,因此需要将服务器文件系统中的某个地址映射为这个“根”。为了简化工作,建议将服务器程序存放的路径作为这个根,这样运行服务器程序时,程序会自动从当前运行的路径开始查询文件。

例如:假设将“HelloWorld.html”这个 html 文件放置在服务器程序文件存放目录中,服务器运行主机的 IP 地址为“123.234.12.34”,6789 为服务器监听的端口号。

则从 URL:http;//123.234.12.34:6789/HelloWorld.html 出发可以获取到“HelloWorld.html” 这个文件。

八 . 单一请求

代码说明在代码注释中给出,具体流程如 三、实验原理

服务器 web_server.py代码

from socket import *
import sys
def web_server(ip, port):
    # 服务器端通过调用socket()创建套接字来启动一个服务器
    serverSocket = socket(AF_INET,SOCK_STREAM)
    server_address = (ip, port)#接收传入的ip地址与端口号
    #服务器调用bind()绑定指定服务器的套接字地址(IP 地址 + 端口号)
    serverSocket.bind(server_address) 
    # 服务器调用listen()做好侦听准备,同时规定好请求队列的长度
    Length=1024
    try:
        serverSocket.listen(1)
    except socket.error:
        print("fail to listen on port %s" % error)
        sys.exit(1)
    while True:
        print("Ready to server...")
        #服务器进入阻塞状态,等待客户的连接请求
        #服务器通过accept来接收连接请求,并获得客户的 socket 地址
        connectionSocket, addr = serverSocket.accept()
        break
    while True:
        try:
            #通过TCP 套接字接收 HTTP 请求
            message = connectionSocket.recv(Length)
            msg_de = message.decode('utf-8')
            print('file msg from client: '+msg_de)
            #收到客户端断开连接消息
            if msg_de == 'disconnect':break
            #从服务器的文件系统读取客户端请求的文件
            filename=message
            f=open(filename[0:])
            #被请求文件存在,创建一个由被请求的文件组成的“请求成功”HTTP 响应报文
            output=(msg_de+' has been successfully received.').encode('utf-8')
            #通过 TCP 连接将响应报文发回客户端
            connectionSocket.send(output)
        except IOError:
            #被请求文件不存在,创建“请求目标不存在”HTTP 响应报文
            output=('The request has failed.').encode('utf-8')
            #通过 TCP 连接将响应报文发回客户端
            connectionSocket.send(output)
    print("finish test, close connect")
    #通过close()关闭套接字
    connectionSocket.close()
    serverSocket.close()
if __name__=='__main__':
    web_server('127.0.0.1',6000)

客户端 web_client.py代码

from socket import * 
def web_client(ip,port):
    #在客户端通过调用socket()创建套接字
    clientSocket = socket(AF_INET,SOCK_STREAM)
    failed_count = 0
    while True:
        try:
            print("start connect to server ")
            #客户端调用connect()和服务器建立连接
            clientSocket.connect((ip,port))
            break
        except socket.error:
            failed_count += 1
            print("fail to connect to server %d times" % failed_count)
            if failed_count == 100: return 
    #连接成功后发送消息
    while True:
        print("connect success")
        receive_count = 0
        while True:
            if receive_count%2==0:
                msg = 'iloveu.txt'#存在的文档消息请求
            else:
                msg='1.txt'#不存在的文档消息请求
            #使用send()发送消息
            clientSocket.send(msg.encode('utf-8'))                        
            msg = clientSocket.recv(1024)
            print('msg from server :'+msg.decode('utf-8'))
            receive_count+= 1
            #一共发送14次消息,随后告知服务器将要断开连接
            if receive_count==14:
                msg = 'disconnect'
                clientSocket.send(msg.encode('utf-8'))
                break
        break
    #通过close关闭套接字
    clientSocket.close()      
if __name__=='__main__':
web_client('127.0.0.1',6000)

九 . 多请求

在单一HTTP请求的代码基础上,创建多线程服务器,可以同一时间处理多个HTTP请求,并在客户端使用多线程同时向服务器发送HTTP请求。

客户端在请求时将自己的线程号与请求文件一同发出,服务器在收到客户端的请求后,若请求成功,将自身的线程号一并返回给客户端。

多线程服务器 web_mul_server.py代码

from socket import *
import sys,threading
def web_mul_server(ip, port,num):
    # 服务器端通过调用socket()创建套接字来启动一个服务器
    serverSocket = socket(AF_INET,SOCK_STREAM)
    server_address = (ip, port)#接收传入的ip地址与端口号
    #服务器调用bind()绑定指定服务器的套接字地址(IP 地址 + 端口号)
    serverSocket.bind(server_address)
    # 服务器调用listen()做好侦听准备,同时规定好请求队列的长度
    Length=1024
    try:
        serverSocket.listen(1)
    except socket.error:
        print("fail to listen on port %s" % error)
        sys.exit(1)
    while True:
        print("server "+str(num)+" ready to server...")
        #服务器进入阻塞状态,等待客户的连接请求
        #服务器通过accept来接收连接请求,并获得客户的 socket 地址
        connectionSocket, addr = serverSocket.accept()
        break
    while True:
        try:
            #通过TCP 套接字接收 HTTP 请求
            message = connectionSocket.recv(Length)
            msg_de = message.decode('utf-8')
            print('file msg from '+msg_de)
            #收到客户端断开连接消息
            if msg_de == 'disconnect':break
            #从服务器的文件系统读取客户端请求的文件
            client_num=message.split()[0]
            client_num=client_num.decode('utf-8')
            filename=message.split()[1]
            f=open(filename[0:])
            #被请求文件存在,创建一个由被请求的文件组成的“请求成功”HTTP 响应报文
            output=(msg_de+' from '+client_num+' has been successfully received.--server '+str(num)).encode('utf-8')
            #通过 TCP 连接将响应报文发回客户端
            connectionSocket.send(output)
        except IOError:
            #被请求文件不存在,创建“请求目标不存在”HTTP 响应报文
            output=('The request has failed.').encode('utf-8')
            #通过 TCP 连接将响应报文发回客户端
            connectionSocket.send(output)
    print("finish test, close connect")
    #通过close()关闭套接字
    connectionSocket.close()
    serverSocket.close()
if __name__=='__main__':
    t1=threading.Thread(target=web_mul_server,args=('127.0.0.1',6000,1))
    t2=threading.Thread(target=web_mul_server,args=('127.0.0.1',7000,2))
    t3=threading.Thread(target=web_mul_server,args=('127.0.0.1',8000,3))
    t1.start()
    t2.start()
    t3.start()

多线程客户端 web_mul_client.py代码

from socket import *
import threading
def web_mul_client(ip,port,num):
    #在客户端通过调用socket()创建套接字
    clientSocket = socket(AF_INET,SOCK_STREAM)
    failed_count = 0
    while True:
        try:
            print('client '+str(num)+" start connect to server ")
            #客户端调用connect()和服务器建立连接
            clientSocket.connect((ip,port))
            break
        except socket.error:
            failed_count += 1
            print('client '+str(num)+" fail to connect to server %d times" % failed_count)
            if failed_count == 100: return
    #连接成功后发送消息
    while True:
        print('client '+str(num)+" connect success")
        receive_count = 0
        while True:
            if receive_count%2==0:
                msg ='client'+str(num)+' iloveu.txt'#存在的文档消息请求
            else:
                msg='client'+str(num)+' 1.txt'#不存在的文档消息请求
            #使用send()发送消息
            clientSocket.send(msg.encode('utf-8'))                      
            msg = clientSocket.recv(1024)
            print('msg from server :'+msg.decode('utf-8'))
 
            receive_count+= 1
            #一共发送14次消息,随后告知服务器将要断开连接
            if receive_count==14:
                msg = 'disconnect'
                clientSocket.send(msg.encode('utf-8'))
                break
        break
    #通过close关闭套接字
    clientSocket.close()    
if __name__=='__main__':
    t1=threading.Thread(target=web_mul_client,args=('127.0.0.1',6000,1))
    t2=threading.Thread(target=web_mul_client,args=('127.0.0.1',7000,2))
    t3=threading.Thread(target=web_mul_client,args=('127.0.0.1',8000,3))
    t1.start()
    t2.start()
    t3.start()

 

十 . HTTP请求

在设计好tcp的基础上,在报文中加上相应的http头部即可从url发送文件需求消息。需要注意的是由于tcp的http请求报文存在一定的格式,在server进行接收时需要截取其中有用的消息片段访问文件,在发送消息时也要按照固定的格式进行发送,否则将会出错。

通过url向web发送报文,发送方式为127.0.0.1:4900/iiii.html 即ip:port/文件名。

若从url输入内容127.0.0.1:4040/iloveu.html,在server中收到的信息如

python-TCP 通信与 Web 服务器

 

需要用split()函数截取出有用的文件名信息进行下一步操作。

在向url返回信息时,需要在发送前发送http头信息

python-TCP 通信与 Web 服务器

单一http请求web.py代码

 

from socket import *
import sys

def web_server(ip, port):
    # 服务器端通过调用socket()创建套接字来启动一个服务器
    serverSocket = socket(AF_INET,SOCK_STREAM)
    serverSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
    server_address = ('', port)#接收传入的ip地址与端口号
    #服务器调用bind()绑定指定服务器的套接字地址(IP 地址 + 端口号)
    serverSocket.bind(server_address)
 
    # 服务器调用listen()做好侦听准备,同时规定好请求队列的长度
    Length=1024
    try:
        serverSocket.listen(5)
    except socket.error:
        print("fail to listen on port %s" % error)
        sys.exit(1)
    while True:
        print("Ready to server...")
        connectionSocket, addr = serverSocket.accept()
        print('accepted!'+str(addr))
        try:
            #通过TCP 套接字接收 HTTP 请求
            message = connectionSocket.recv(Length)
            message=message.split()[1]
            msg_de = message.decode('utf-8')
            print('file msg from client: '+msg_de)
            #收到客户端断开连接消息
            if msg_de == '\disconnect':break
            #从服务器的文件系统读取客户端请求的文件
            filename=message
            f=open(filename[1:])
            text=f.read()
            #被请求文件存在,创建一个由被请求的文件组成的“请求成功”HTTP 响应报文
            output= "HTTP/1.1 200 OK\r\n"
            output+= "\r\n"
            output+='\r\n'
            output+=msg_de+' has been successfully received.\n'
            output=output.encode('utf-8')
            print('output: '+str(output))
            #通过 TCP 连接将响应报文发回客户端
            connectionSocket.send(output)
            for i in range(0,len(text)):
                connectionSocket.send(text[i].encode('utf-8'))
            print('send!')
        except IOError:
            #被请求文件不存在,创建“请求目标不存在”HTTP 响应报文
            output= "HTTP/1.1 200 OK\r\n"
            output+= "\r\n"
            output+='\r\n'
            output+='The request has failed.\n'
            output=output.encode('utf-8')
            print('output: '+str(output))
            #通过 TCP 连接将响应报文发回客户端
            connectionSocket.send(output)
 
    print("finish test, close connect")
    #通过close()关闭套接字
    connectionSocket.close()
    serverSocket.close()
 
if __name__=='__main__':
    web_server('127.0.0.1',8888)

 单一http请求实验结果

python-TCP 通信与 Web 服务器

 多http请求web_mul.py代码

from socket import *
import sys,threading

def web_mul(ip, port):
    # 服务器端通过调用socket()创建套接字来启动一个服务器
    serverSocket = socket(AF_INET,SOCK_STREAM)
    serverSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
    server_address = ('', port)#接收传入的ip地址与端口号
    #服务器调用bind()绑定指定服务器的套接字地址(IP 地址 + 端口号)
    serverSocket.bind(server_address)
 
    # 服务器调用listen()做好侦听准备,同时规定好请求队列的长度
    Length=1024
    try:
        serverSocket.listen(5)
    except socket.error:
        print("fail to listen on port %s" % error)
        sys.exit(1)
    while True:
        print("Ready to server...")
        connectionSocket, addr = serverSocket.accept()
        print('accepted!'+str(addr))
        try:
            #通过TCP 套接字接收 HTTP 请求
            message = connectionSocket.recv(Length)
            message=message.split()[1]
            msg_de = message.decode('utf-8')
            print('file msg from client: '+msg_de)
            #收到客户端断开连接消息
            if msg_de == '\disconnect':break
            #从服务器的文件系统读取客户端请求的文件
            filename=message
            f=open(filename[1:])
            text=f.read()
            #被请求文件存在,创建一个由被请求的文件组成的“请求成功”HTTP 响应报文
            output= "HTTP/1.1 200 OK\r\n"
            output+= "\r\n"
            output+='\r\n'
            output+=msg_de+' has been successfully received.\n'
            output=output.encode('utf-8')
            print('output: '+str(output))
            #通过 TCP 连接将响应报文发回客户端
            connectionSocket.send(output)
            for i in range(0,len(text)):
                connectionSocket.send(text[i].encode('utf-8'))
            print('send!')
        except IOError:
            #被请求文件不存在,创建“请求目标不存在”HTTP 响应报文
            output= "HTTP/1.1 200 OK\r\n"
            output+= "\r\n"
            output+='\r\n'
            output+='The request has failed.\n'
            output=output.encode('utf-8')
            print('output: '+str(output))
            #通过 TCP 连接将响应报文发回客户端
            connectionSocket.send(output)
 
    print("finish test, close connect")
    #通过close()关闭套接字
    connectionSocket.close()
    serverSocket.close()

if __name__=='__main__':
    t1=threading.Thread(target=web_mul,args=('127.0.0.1',4700))
    t2=threading.Thread(target=web_mul,args=('127.0.0.1',4800))
    t3=threading.Thread(target=web_mul,args=('127.0.0.1',4900))
    t1.start()
    t2.start()
    t3.start()

多http请求实验结果

python-TCP 通信与 Web 服务器

python-TCP 通信与 Web 服务器

 python-TCP 通信与 Web 服务器

 

十一 . 实验分析

实验过程

在单一HTTP请求中打开两个终端分别运行服务器端web_wever.py与客户端web_client.py。其中需要先打开服务器端再运行客户端。

在单一HTTP请求的基础上进行多HTTP请求的编写。其中对于client向server请求的方式可以有多种,可以开多个进程对server发送请求,此处使用较为方便同时也是server端使用的多线程的方法发送请求。

由于TCP是可靠的连接,在一方连接断开时需要通知另一方自己将断开连接,在实验中在client发送了一定次数请求后将关闭连接并通知server使其也关闭的功能。若client关闭了连接却没有通知server导致server在循环中继续通过tcp发送消息将导致程序报错,同理若server断开连接并进行下一次的等待操作,若没有通知client,client将无法通过tcp传输而导致报错,也因为没有断开连接将无法正常进行下一次的连接操作。

还有一种较为常见可行的方法是client接收用户键盘输入的文件请求,关闭操作也可以由接收的键盘输入控制,而后将文件请求通过tcp发送给服务器端,之后的方法大致相同。

在使用url向server发送请求时要注意端口号,以及在处理报文和发送报文时需要按照固定的格式,接收时需要截取特定的报文内容,发送时需要添加固定的格式。

需要注意传输的内容格式需要是byte,发送时需要使用encode()转码,接收时需要使用decode()转成str。

结果分析

在单一HTTP请求与多HTTP请求中都做到了client向server发送文件请求,server在本地目录下查询文件后返回的操作。在执行完后正常而言不应该进行close操作,但为了代码与执行的整洁性与逻辑性,我们仍然选择在完成特定功能后关闭连接。

tcp是可靠的连接,我们在多HTTP请求中可以观察到,当连接确立后,对应的server线程会接收来自对应client发送的消息,随后将消息准确地发回对应的client。

可以通过url向web发送报文,发送方式为127.0.0.1:4900/iiii.html 即ip:port/文件名。

遇到问题

在server进行accept操作时若不使用循环,当没有client时会报错,所以使用循环进行等待。

在server和client断开连接时若操作不当,server或client单方面断开连接很容易导致报错,在这里client断开连接时会向server发送断开连接消息告知server,server随机断开不再进行传输操作。

当连接异常时,较多为server或client单方面中断,另一方若继续通过tcp发送消息,电脑将中断该操作。

在使用url向server发送请求时,在直接使用之前的方式会出现应答出错,需要将单独的while循环的accpet放进整体中才能正常运行。

 

到了这里,关于python-TCP 通信与 Web 服务器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 如何搭建服务器调试2G/3G/4G模块通信/公网TCP服务器调试

            在调试2G/3G/4G模块网络通信时,个人电脑无法直接进行调试,因为个人电脑连接网络属于局域网,而2G/3G/4G等GSM网络属于广域网,也就是公网,所以如何调试2G/3G/4G网络需要进行内网穿透。         方案一:使用安信可透传云         安信可透传云解决方案是指

    2024年01月21日
    浏览(50)
  • TCP实现服务器和客户端通信

    目录 TCP介绍 代码实现 server(服务器端) 代码分析 client(客户端) 代码分析 结果展示 TCP (Transmission Control Protocol) 是一种面向连接的协议,用于在计算机网络中传输数据。TCP 可以确保数据的可靠传输,即使在网络环境不稳定的情况下也能够保证数据的完整性和顺序。以下是

    2024年02月15日
    浏览(53)
  • 简易TCP客户端和服务器端通信

    #includeiostream #include winsock2.h   #include ws2tcpip.h   #includestdlib.h using namespace std; #define  BUF_SIZE  1024 int main() {     cout \\\"客户端\\\" endl;     //设置Winsock版本,     WSADATA   wsaData;     if (WSAStartup(MAKEWORD(2, 2), wsaData) != 0)     {         cout \\\"error\\\" endl;         exit(1);     }     //创建通

    2024年04月29日
    浏览(40)
  • TCP通信实现客户端向服务器发送图片

    TCP通信: 1. TCP 协议通信交互流程: 具体的流程如下: (1)服务器根据地址类型(ipv4、ipv6)、socket 类型、协议创建 socket. (2)服务器为 socket 绑定 ip 地址和端口号。 (3)服务器 socket 监听端口号的请求,随时准备接受来自客户端的连接,此时服务器的 socket 处于关闭状态

    2024年02月13日
    浏览(53)
  • QT实现TCP通信(服务器与客户端搭建)

    创建一个QTcpServer类对象,该类对象就是一个服务器 调用listen函数将该对象设置为被动监听状态,监听时,可以监听指定的ip地址,也可以监听所有主机地址,可以通过指定端口号,也可以让服务器自动选择 当有客户端发来连接请求时,该服务器会自动发射一个newConnection信号

    2024年02月09日
    浏览(49)
  • Java实现TCP客户端和服务器端相互通信

    解决TCP客户端和服务器端通信读不到数据的问题  解决: 服务器端和客户端读完后加上client.shutdownInput(); 服务器端和客户端写完后加上client.shutdownOutput(); 服务器端代码: 客户端代码: 运行服务器端再运行客户端,在客户端中输入要发送的信息,回车 服务器收到信息,over

    2024年02月08日
    浏览(54)
  • TCP/IP客户端和服务器端建立通信过程

    使用Qt提供的类进行基于 TCP 的套接字通信需要用到两个类: QTcpServer 类用于监听客户端连接以及和客户端建立连接,在使用之前先介绍一下这个类提供的一些常用API函数: 构造函数 给监听的套接字设置监听 listen() 函数 在代码中 通过启动监听按钮 设置监听 参数: address :

    2024年02月07日
    浏览(57)
  • 【云服务器】关于UDP/TCP跨平台网络通信服务器无响应的情况及解决办法

    本篇文章仅为了记录我在跨平台进行udp通信的时候遇到的问题及解决办法 进行udp网络通信的时候,我用腾讯云服务器作服务端,windows本机作客户端,在进行连接的时候,当我在客户端向服务端发送消息的时候,服务器端接收不到消息(安全组已经配置) 当执行上述命令出现

    2024年02月10日
    浏览(39)
  • Linux下TCP网络服务器与客户端通信程序入门

    实现客户端连接服务器,通过终端窗口发送信息给服务器端,服务器接收到信息后对信息数据进行回传,客户端读取回传信息并返回。 服务器当前IP地址要知道 建立socket 绑定本地IP地址并设置端口号 知道服务器的IP地址和端口号 然后进行连接

    2024年02月14日
    浏览(54)
  • 实验六 WEB FTP服务器配置

    实验六 WEB FTP服务器配置    一、实验目的 理解IIS服务的基本概念; 掌握在Windows 2003 server 上安装WEB服务器的方法; 掌握WEB服务器的配置方法; 掌握在客户端访问WEB服务器的方法。 理解FTP的基本概念与工作原理; 安装FTP服务器方法; 配置与管理FTP服务器的方法; 客户端访

    2024年02月09日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包