这部分回顾Socket Programming Assignment 1: WebServer。

参考资料:

简介

此次作业的目的是是熟悉TCP套接字编程,主要任务如下:

  • 实现基本的服务器
  • 实现多线程服务器
  • 实现客户端

文件路径结构如下:

Socket1_WebServer/
|-- HelloWorld.html
|-- client.py
|-- web_server.py
`-- web_server_multi.py

文件解释如下:

  • HelloWorld.html:服务器中文件;
  • web_server.py:基本服务器;
  • web_server_multi.py:多线程服务器;
  • client.py:客户端

网页内容

HelloWorld.html:

<!DOCTYPE html>
<html>
    <head>
        <title>Test web server</title>
    </head>
    <body>
        <p>Hello, world!</p>
    </body>
</html>

基本服务器

代码比较简单,注意点有如下:

  • header中每个部分需要后跟\r\n表示结束,整个header部分需要后跟\r\n表示header结束;
  • serverName为表示ip地址为localhost

web_server.py代码如下:

#import socket module
from socket import *

serverSocket = socket(AF_INET, SOCK_STREAM) 
#Prepare a sever socket 
#Fill in start
serverPort = 12000
serverSocket.bind(("", serverPort))
serverSocket.listen(1)

#Fill in end 
while True:     
    #Establish the connection    
    print('Ready to serve...')
    connectionSocket, addr = serverSocket.accept() #Fill in start  #Fill in end
    try:         
        message = connectionSocket.recv(1024).decode()#Fill in start  #Fill in end
        print(message)
        filename = message.split()[1]  
        print(filename)                        
        f = open(filename[1:])
        outputdata = f.readlines()#Fill in start  #Fill in end
        print(outputdata)
        #Send one HTTP header line into socket
        #Fill in start
        # 每个header需要后跟\r\n表示结束, header部分需要后跟\r\n表示header结束       
        connectionSocket.send('HTTP/1.1 200 OK\r\n\r\n'.encode())
        #Fill in end    
        #Send the content of the requested file to the client
        for i in range(0, len(outputdata)):
            connectionSocket.send(outputdata[i].encode())
        f.close()
        connectionSocket.close()
    except IOError:
        #Send response message for file not found
        #Fill in start
        connectionSocket.send('HTTP/1.1 404 Not Found\r\n\r\n'.encode())
        #Fill in end
        #Close client socket
        #Fill in start
        connectionSocket.close()
        #Fill in end             
serverSocket.close()

启动服务器:

python web_server.py

测试:

多线程服务器

每次碰到一个请求,多开一个进程即可,web_server_multi.py代码如下:

#import socket module
from socket import *
import threading

serverSocket = socket(AF_INET, SOCK_STREAM) 
#Prepare a sever socket 
#Fill in start
serverPort = 12000
serverSocket.bind(('', serverPort))
serverSocket.listen(1)

def response(connectionSocket):
    try:         
        message = connectionSocket.recv(1024).decode()#Fill in start  #Fill in end
        print(message)
        filename = message.split()[1]  
        print(filename)                        
        f = open(filename[1:])
        outputdata = f.readlines()#Fill in start  #Fill in end
        print(outputdata)
        #Send one HTTP header line into socket
        #Fill in start         
        connectionSocket.send('HTTP/1.1 200 OK\r\n\r\n'.encode())
        #Fill in end    
        #Send the content of the requested file to the client
        for i in range(0, len(outputdata)):
            connectionSocket.send(outputdata[i].encode())
        f.close()
        connectionSocket.close()
    except IOError:
        #Send response message for file not found
        #Fill in start
        connectionSocket.send('HTTP/1.1 404 Not Found\r\n\r\n'.encode())
        #Fill in end
        #Close client socket
        #Fill in start
        connectionSocket.close()
        #Fill in end        

#Fill in end 
while True:     
    #Establish the connection    
    print('Ready to serve...')
    connectionSocket, addr = serverSocket.accept() #Fill in start  #Fill in end
    thread = threading.Thread(target=response, args=(connectionSocket,))
    thread.start()
     
serverSocket.close()

启动服务器:

python web_server_multi.py

测试:

客户端

参考课本2.7.2的客户端编写即可,这里输入有三个参数,分别是server_host,server_port,filename,client.py代码如下:

import sys
from socket import *

def main():
    server_host = sys.argv[1]
    server_port = sys.argv[2]
    filename = sys.argv[3]
    clientSocket = socket(AF_INET, SOCK_STREAM)
    clientSocket.connect((server_host, int(server_port)))
    clientSocket.send(f"GET /{filename} HTTP/1.1\r\n\r\n".encode())
    while True:
        rawdata = clientSocket.recv(1024)
        data = rawdata.decode()
        if len(data) == 0:
            break
        print(data)
    
    clientSocket.close()

if __name__ == '__main__':
    main()

启动服务器以及客户端:

python web_server.py

python client.py localhost 12000 HelloWorld.html

实验结果:

HTTP/1.1 200 OK


<!DOCTYPE html>
<html>
    <head>
        <title>Test web server</title>
    </head>
    <body>
        <p>Hello, world!</p>
    </body>
</html>