精华内容
下载资源
问答
  • ServerSocket实现一个简单的Web服务器demo
  • 说到 web 服务器想必大多数人首先想到的协议是 http,那么 http 之下则是 tcp,本篇文章将通过 tcp 来实现一个简单的 web 服务器。本篇文章将着重讲解如何实现,对于 http 与 tcp 的概念本篇将不过多讲解。一、了解 ...

    说到 web 服务器想必大多数人首先想到的协议是 http,那么 http 之下则是 tcp,本篇文章将通过 tcp 来实现一个简单的 web 服务器。

    本篇文章将着重讲解如何实现,对于 http 与 tcp 的概念本篇将不过多讲解。

    一、了解 Socket 及 web 服务工作原理

    既然是基于 tcp 实现 web 服务器,很多学习 C 语言的小伙伴可能会很快的想到套接字 socket。socket 是一个较为抽象的通信进程,或者说是主机与主机进行信息交互的一种抽象。socket 可以将数据流送入网络中,也可以接收数据流。

    socket 的信息交互与本地文件信息的读取从表面特征上看类似,但其中所存在的编写复杂度是本地 IO 不能比拟的,但却有相似点。在 win 下 socket 的交互交互步骤为:WSAStartup 进行初始化--> socket 创建套接字--> bind 绑定--> listen 监听--> connect 连接--> accept 接收请求--> send/recv 发送或接收数据--> closesocket 关闭 socket--> WSACleanup 最终关闭。

    f6356160b1c047a1acc602c34b463100.png

    了解完了一个 socket 的基本步骤后我们了解一下一个基本 web 请求的用户常规操作,操作分为:打开浏览器-->输入资源地址 ip 地址-->得到资源。当目标服务器接收到该操作产生掉请求后,我们可以把服务器的响应流程步骤看为:获得 request 请求-->得到请求关键数据-->获取关键数据-->发送关键数据。服务器的这一步流程是在启动socket 进行监听后才能响应。通过监听得知接收到请求,使用 recv 接收请求数据,从而根据该参数得到进行资源获取,最后通过 send 将数据进行返回。

    二、创建sokect完成监听

    2.1 WSAStartup初始化

    首先在c语言头文件中引入依赖 WinSock2.h:

    #include <WinSock2.h>
    

    在第一点中对 socket 的创建步骤已有说明,首先需要完成 socket 的初始化操作,使用函数 WSAStartup,该函数的原型为:

    int WSAStartup(
      WORD      wVersionRequired,
      LPWSADATA lpWSAData
    );
    

    该函数的参数 wVersionRequired 表示 WinSock2 的版本号;lpWSAData 参数为指向 WSADATA 的指针,WSADATA 结构用于 WSAStartup 初始化后返回的信息。

    wVersionRequired 可以使用 MAKEWORD 生成,在这里可以使用版本 1.1 或版本2.2,1.1 只支持 TCP/IP,版本 2.1 则会有更多的支持,在此我们选择版本 1.1。

    首先声明一个 WSADATA 结构体 :

    WSADATA wsaData;
    

    随后传参至初始化函数 WSAStartup 完成初始化:

    WSAStartup(MAKEWORD(1, 1), &wsaData)
    

    WSAStartup 若初始化失败则会返回非0值:

    if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) 
    {
     exit(1);
    }
    

    2.2 创建socket 套接字

    初始化完毕后开始创建套接字,套接字创建使用函数,函数原型为:

    SOCKET WSAAPI socket(
      int af,
      int type,
      int protocol
    );
    

    在函数原型中,af 表示 IP 地址类型,使用 PF_INET 表示 IPV4,type 表示使用哪种通信类型,例如 SOCK_STREAM 表示 TCP,protocol 表示传输协议,使用 0 会根据前 2 个参数使用默认值。

    int skt = socket(PF_INET, SOCK_STREAM, 0);
    

    创建完 socket 后,若为 -1 表示创建失败,进行判断如下:

    if (skt == -1) 
    {         
     return -1;
    }
    

    2.3 绑定服务器

    创建完 socket 后需要对服务器进行绑定,配置端口信息、IP 地址等。 首先查看 bind 函数需要哪一些参数,函数原型如下:

    int bind(
      SOCKET         socket,
      const sockaddr *addr,
      int            addrlen
    );
    

    参数 socket 表示绑定的 socket,传入 socket 即可;addr 为 sockaddr_in 的结构体变量的指针,在 sockaddr_in 结构体变量中配置一些服务器信息;addrlen 为 addr 的大小值。

    通过 bind 函数原型得知了我们所需要的数据,接下来创建一个 sockaddr_in 结构体变量用于配置服务器信息:

    struct sockaddr_in server_addr;
    

    随后配置地址家族为AF_INET对应TCP/IP:

    server_addr.sin_family = AF_INET;
    

    接着配置端口信息:

    server_addr.sin_port = htons(8080);
    

    再指定 ip 地址:

    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    

    ip 地址若不确定可以手动输入,最后使用神器 memset 初始化内存,完整代码如下:

    //配置服务器 
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8080);
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    memset(&(server_addr.sin_zero), '0', 8);
    

    随后使用 bind 函数进行绑定且进行判断是否绑定成功:

    //绑定
    if (bind(skt, (struct sockaddr *)&server_addr,sizeof(server_addr)) == -1) {       
     return -1; 
    } 
    

    2.4 listen进行监听

    绑定成功后开始对端口进行监听。查看 listen 函数原型:

    int listen(
     int sockfd, 
     int backlog
    )
    

    函数原型中,参数 sockfd 表示监听的套接字,backlog 为设置内核中的某一些处理(此处不进行深入讲解),直接设置成 10 即可,最大上限为 128。使用监听并且判断是否成功代码为:

    if (listen(skt, 10) == -1 ) {    
     return -1;
    }
    

    此阶段完整代码如下:

    #include <WinSock2.h>
    #include<stdio.h> 
    int main(){
     //初始化 
     WSADATA wsaData;
     if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) {
      exit(1);
     }
     //socket创建 
     int skt = socket(PF_INET, SOCK_STREAM, 0);
     if (skt == -1) {         
      return -1;
     }
     //配置服务器 
     struct sockaddr_in server_addr;
     server_addr.sin_family = AF_INET;
     server_addr.sin_port = htons(8080);
     server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
     memset(&(server_addr.sin_zero), '0', 8);
     //绑定
     if (bind(skt, (struct sockaddr *)&server_addr,sizeof(server_addr)) == -1){       
      return -1; 
     } 
     //监听 
     if (listen(skt, 10) == -1 ) {    
      return -1;
     }
     
     printf("Listening ... ...n");
    }
    

    运行代码可得知代码无错误,并且输出 listening:

    7080e8ada2e4913bf2a1e6eae414084c.png

    2.5 获取请求

    监听完成后开始获取请求。受限需要使用 accept 对套接字进行连接,accept 函数原型如下:

    int accept(
     int sockfd,
     struct sockaddr *addr,
     socklen_t *addrlen
     );
    

    参数 sockfd 为指定的套接字;addr 为指向 struct sockaddr 的指针,一般为客户端地址;addrlen 一般设置为设置为 sizeof(struct sockaddr_in) 即可。代码为:

    struct sockaddr_in c_skt; 
    int s_size=sizeof(struct   sockaddr_in);
    int access_skt = accept(skt, (struct sockaddr *)&c_skt, &s_size);
    

    接下来开始接受客户端的请求,使用recv函数,函数原型为:

    ssize_t recv(
     int sockfd, 
     void *buf, 
     size_t len, 
     int flags
    )
    

    参数 sockfd 为 accept 建立的通信;buf 为缓存,数据存放的位置;len 为缓存大小;flags 一般设置为0即可:

    //获取数据 
    char buf[1024];
    if (recv(access_skt, buf, 1024, 0) == -1) {
     exit(1);
    }
    

    此时我们再到 accpt 和 recv 外层添加一个循环,使之流程可重复:

    while(1){
      //建立连接 
      printf("Listening ... ...n");
      struct sockaddr_in c_skt; 
      int s_size=sizeof(struct   sockaddr_in);
      int access_skt = accept(skt, (struct sockaddr *)&c_skt, &s_size);
      
      //获取数据 
      char buf[1024];
      if (recv(access_skt, buf, 1024, 0) == -1) {
       exit(1);
      }
     } 
    

    并且可以在浏览器输入 127.0.0.1:8080 将会看到客户端打印了 listening 新建了链接:

    5d171e1b9bd205d70d56c1151a88e00c.png

    ba72c224a9125ab1faee7280de98f741.png

    我们添加printf语句可查看客户端请求:

    while(1){
      //建立连接 
      printf("Listening ... ...n");
      struct sockaddr_in c_skt; 
      int s_size=sizeof(struct   sockaddr_in);
      int access_skt = accept(skt, (struct sockaddr *)&c_skt, &s_size);
      
      //获取数据 
      char buf[1024];
      if (recv(access_skt, buf, 1024, 0) == -1) {
       exit(1);
      }
      
      printf("%s",buf);
     } 
    

    97b6727041616d134abae75488703d23.png

    接下来我们对请求头进行对应的操作。

    2.6 请求处理层编写

    得到请求后开始编写处理层。继续接着代码往下写没有层级,编写一个函数名为 req,该函数接收请求信息与一个建立好的连接为参数:

    void req(char* buf, int access_socket) 
    {
    }
    

    然后先在 while 循环中传递需要的值:

    req(buf, access_skt);
    

    接着开始编写 req 函数,首先在 req 函数中标记当前目录下:

    char arguments[BUFSIZ];  
    strcpy(arguments, "./");
    

    随后分离出请求与参数:

    char command[BUFSIZ];     
    sscanf(request, "%s%s", command, arguments+2);
    

    接着我们标记一些头元素:

    char* extension = "text/html";   
    char* content_type = "text/plain";     
    char* body_length = "Content-Length: ";
    

    接着获取请求参数,若获取 index.html,就获取当前路径下的该文件:

    FILE* rfile= fopen(arguments, "rb");
    

    获取文件后表示请求 ok,我们先返回一个 200 状态:

    char* head = "HTTP/1.1 200 OKrn";    
    int len; 
    char ctype[30] = "Content-type:text/htmlrn";   
    len = strlen(head);
    

    接着编写一个发送函数 send_:

    int send_(int s, char *buf, int *len) 
    {
     int total;          
     int bytesleft;                                
     int n;
     total=0;
     bytesleft=*len;
     while(total < *len) 
     {
      n = send(s, buf+total, bytesleft, 0);
      if (n == -1) 
      {
       break;
      }
      total += n;
      bytesleft -= n;
     }
     *len = total;          
     return n==-1?-1:0;         
    }
    

    send 函数功能并不难在此不再赘述,就是一个遍历发送的逻辑。随后发送 http 响应与文件类型:

    send_(send_to, head, &len);
    len = strlen(ctype);
    send_(send_to, ctype, &len);
    

    随后获得请求文件的描述,需要添加头文件#include <sys/stat.h>使用fstat,且向已连接的通信发生必要的信息 :

    //获取文件描述
    struct stat statbuf;
    char read_buf[1024];       
    char length_buf[20];
    fstat(fileno(rfile), &statbuf);
    itoa( statbuf.st_size, length_buf, 10 );
    send(client_sock, body_length, strlen(body_length), 0);
    send(client_sock, length_buf, strlen(length_buf), 0);
    
    send(client_sock, "n", 1, 0);
    send(client_sock, "rn", 2, 0);
    

    最后发送数据:

    //·数据发送
    char read_buf[1024]; 
    len = fread(read_buf ,1 , statbuf.st_size, rfile);
    if (send_(client_sock, read_buf, &len) == -1) { 
     printf("error!");   
    }
    

    最后访问地址 http://127.0.0.1:8080/index.html,得到当前目录下 index.html 文件数据,并且在浏览器渲染:

    fe19c140128e89877dcaddd42817cd8c.png

    所有代码如下:

    #include <WinSock2.h>
    #include<stdio.h> 
    #include <sys/stat.h> 
    
    int send_(int s, char *buf, int *len) {
     int total;          
     int bytesleft;                                
     int n;
     total=0;
     bytesleft=*len;
     while(total < *len) 
     {
      n = send(s, buf+total, bytesleft, 0);
      if (n == -1) 
      {
       break;
      }
      total += n;
      bytesleft -= n;
     }
     *len = total;          
     return n==-1?-1:0;         
    }
    
    void req(char* request, int client_sock) {   
     char arguments[BUFSIZ];  
     strcpy(arguments, "./");
     
     char command[BUFSIZ];     
     sscanf(request, "%s%s", command, arguments+2);
     
     char* extension = "text/html";   
     char* content_type = "text/plain";     
     char* body_length = "Content-Length: ";
     
     FILE* rfile= fopen(arguments, "rb");
     
    
     char* head = "HTTP/1.1 200 OKrn";    
     int len; 
     char ctype[30] = "Content-type:text/htmlrn";   
     len = strlen(head);
      
     send_(client_sock, head, &len);
     len = strlen(ctype);
     send_(client_sock, ctype, &len);
     
    
     struct stat statbuf;
           
     char length_buf[20];
     fstat(fileno(rfile), &statbuf);
     itoa( statbuf.st_size, length_buf, 10 );
     send(client_sock, body_length, strlen(body_length), 0);
     send(client_sock, length_buf, strlen(length_buf), 0);
    
     send(client_sock, "n", 1, 0);
     send(client_sock, "rn", 2, 0);
     
    
     char read_buf[1024]; 
     len = fread(read_buf ,1 , statbuf.st_size, rfile);
     if (send_(client_sock, read_buf, &len) == -1) { 
      printf("error!");   
     }
     
     return;
    }
    
    
    int main(){
     WSADATA wsaData;
     if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) {
      exit(1);
     }
    
     int skt = socket(PF_INET, SOCK_STREAM, 0);
     if (skt == -1) {         
      return -1;
     }
    
     struct sockaddr_in server_addr;
     server_addr.sin_family = AF_INET;
     server_addr.sin_port = htons(8080);
     server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
     memset(&(server_addr.sin_zero), '0', 8);
    
     if (bind(skt, (struct sockaddr *)&server_addr,sizeof(server_addr)) == -1) {       
      return -1; 
     } 
    
     if (listen(skt, 10) == -1 ) {    
      return -1;
     }
     
     while(1){
    
      printf("Listening ... ...n");
      struct sockaddr_in c_skt; 
      int s_size=sizeof(struct   sockaddr_in);
      int access_skt = accept(skt, (struct sockaddr *)&c_skt, &s_size);
    
      char buf[1024];
      if (recv(access_skt, buf, 1024, 0) == -1) {
       exit(1);
      }
      
      req(buf, access_skt);
     } 
     
    }
    

    小伙伴们可以编写更加灵活的指定资源类型、错误处理等完善这个 demo。

    展开全文
  • 主要介绍了java实现一个简单的Web服务器实例解析,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
  • 现在我们自己实现一个简单的web服务器,基本的功能就是用户点击要访问的资源,服务器将资源发送到客户端的浏览器。web服务基于的是HTTP协议,用户在浏览器的地址栏输入要访问的地址,服务器如何得到该地址是个关键。...

    在日常的开发中,我们用过很多开源的web服务器,例如tomcat、apache等等。现在我们自己实现一个简单的web服务器,基本的功能就是用户点击要访问的资源,服务器将资源发送到客户端的浏览器。web服务基于的是HTTP协议,用户在浏览器的地址栏输入要访问的地址,服务器如何得到该地址是个关键。先看下一般的HTTP请求和响应报文的一般格式:

    HTTP 请求报文

    0818b9ca8b590ca3270a3433284dd417.png

    HTTP 响应报文

    0818b9ca8b590ca3270a3433284dd417.png

    二 socket类 套接字是网络连接的断点。套接字使得应用程序可以从网络中读取数据,可以向网络中写入数据。不同计算机上的应用程序可以通过套接字发送或接受字节流。java中提供了Socket类来实现这个功能,通过getInputStream和getOutputStream可以获取网络中的输入输出流。 但是,光靠Socket类还是不能够实现我们构建一个服务器应用程序的功能的,因为服务器必须时刻待命,因此java里面提供了ServerSocket类来处理等待来自客户端的请求,当ServerSocket接受到了来自客户端的请求之后,它就会创建一个实例来处理与客户端的通信。 三 服务器应用程序的实现 首先,我们要构建一个封装请求信息的类requst,一个响应请求的类response,还要有一个主程序httpServer来处理客户端来的请求。

    下面是代码:

    Request类:

    package server;

    import java.io.IOException;

    import java.io.InputStream;

    /**

    * 将浏览器发来的请求信息转化成字符和截取url

    */

    public class Request {

    //输入流

    private InputStream input;

    //截取url,如http://localhost:8080/index.html ,截取部分为 /index.html

    private String uri;

    public Request(InputStream inputStream){

    this.input = inputStream;

    }

    public InputStream getInput() {

    return input;

    }

    public void setInput(InputStream input) {

    this.input = input;

    }

    public String getUri() {

    return uri;

    }

    public void setUri(String uri) {

    this.uri = uri;

    }

    //从套接字中读取字符信息

    public void parse(){

    StringBuffer request = new StringBuffer(2048);

    int i = 0;

    byte[] buffer = new byte[2048];

    try {

    i = input.read(buffer);

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    i = -1;

    }

    for(int j = 0;j

    request.append((char)(buffer[j]));

    }

    System.out.println(request.toString());

    uri = parseUri(request.toString());

    }

    //截取请求的url 截取index.html

    private String parseUri(String requestString){

    int index1 = 0;

    int index2 = 0;

    index1 = requestString.indexOf(' ');

    if(index1!=-1){

    index2 = requestString.indexOf(' ',index1+1);

    if(index2>index1){

    return requestString.substring(index1+1,index2);

    }

    }

    return null;

    }

    }

    Responselei

    package server;

    import java.io.File;

    import java.io.FileInputStream;

    import java.io.FileNotFoundException;

    import java.io.IOException;

    import java.io.OutputStream;

    /**

    * 类说明 根据相应信息返回结果

    */

    public class Response {

    private static final int BUFFER_SIZE = 1024;

    Request request;

    OutputStream output;

    public Response(OutputStream output){

    this.output = output;

    }

    public void sendStaticResource() throws IOException{

    byte[] bytes = new byte[BUFFER_SIZE];

    FileInputStream fis = null;

    File file = new File(HttpServer.WEB_ROOT,request.getUri());

    if(file.exists()){

    try {

    fis = new FileInputStream(file);

    int ch = fis.read(bytes,0,BUFFER_SIZE);

    while(ch != -1){

    output.write(bytes,0,ch);

    ch = fis.read(bytes,0,BUFFER_SIZE);

    }

    } catch (FileNotFoundException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }catch(IOException e){

    e.printStackTrace();

    }finally{

    if(fis !=null){

    fis.close();

    }

    }

    }else{

    //找不到文件

    String errorMessage = "HTTP/1.1 404 File Not Found\r\n" +

    "Content-Type: text/html\r\n" +

    "Content-Length: 23\r\n" +

    "\r\n" +

    "

    File Not Found

    ";

    try {

    output.write(errorMessage.getBytes());

    output.flush();

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    }

    public Request getRequest() {

    return request;

    }

    public void setRequest(Request request) {

    this.request = request;

    }

    public OutputStream getOutput() {

    return output;

    }

    public void setOutput(OutputStream output) {

    this.output = output;

    }

    public static int getBUFFER_SIZE() {

    return BUFFER_SIZE;

    }

    }

    HttpServer类

    package server;

    import java.io.File;

    import java.io.InputStream;

    import java.io.OutputStream;

    import java.net.InetAddress;

    import java.net.ServerSocket;

    import java.net.Socket;

    /**

    * 类说明

    * 时刻等待前端请求

    */

    public class HttpServer {

    /**

    * @param args

    */

    //WEB_ROOT是服务器的根目录

    public static final String WEB_ROOT = System.getProperty("user.dir")+File.separator+"webroot";

    //关闭的命令

    // private static final String SHUTDOWN_COMMAND= "/SHUTDOWN";

    public static void main(String[] args) {

    // TODO Auto-generated method stub

    HttpServer server = new HttpServer();

    server.await();

    }

    public void await(){

    ServerSocket serverSocket = null;

    int port = 8080;

    try {

    serverSocket = new ServerSocket(port,1,InetAddress.getByName("127.0.0.1"));

    while(true)

    {

    try {

    Socket socket = null;

    InputStream input = null;

    OutputStream output = null;

    socket = serverSocket.accept();

    input = socket.getInputStream();

    output = socket.getOutputStream();

    //封装request请求

    Request request = new Request(input);

    request.parse();

    //封装response对象

    Response response = new Response(output);

    response.setRequest(request);

    response.sendStaticResource();

    socket.close();

    } catch (Exception e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    continue;

    }

    }

    } catch (Exception e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    }

    DEMO目录结构:

    0818b9ca8b590ca3270a3433284dd417.png

    运行HttpServer,在浏览器上输入以下地址即可看到效果

    http://localhost:8080/index.html

    0818b9ca8b590ca3270a3433284dd417.png

    展开全文
  • 实现一个简单的web服务器

    千次阅读 2018-06-06 11:04:31
    实现一个简单的Web服务器myhttpd。服务器程序启动时要读取配置文件/etc/myhttpd.conf,其中需要指定服务器监听的端口号和服务目录,例如:Port=80 Directory=/var/www注意,1024以下的端口号需要超级用户才能开启...

    实现一个简单的Web服务器myhttpd。服务器程序启动时要读取配置文件/etc/myhttpd.conf,其中需要指定服务器监听的端口号和服务目录,例如:

    Port=80
    Directory=/var/www

    注意,1024以下的端口号需要超级用户才能开启服务。如果你的系统中已经安装了某种Web服务器(例如Apache),应该为myhttpd选择一个不同的端口号。当浏览器向服务器请求文件时,服务器就从服务目录(例如/var/www)中找出这个文件,加上HTTP协议头一起发给浏览器。但是,如果浏览器请求的文件是可执行的则称为CGI程序,服务器并不是将这个文件发给浏览器,而是在服务器端执行这个程序,将它的标准输出发给浏览器,服务器不发送完整的HTTP协议头,CGI程序自己负责输出一部分HTTP协议头。

    5.1. 基本HTTP协议

    打开浏览器,输入服务器IP,例如 http://192.168.0.3 ,如果端口号不是80,例如是8000,则输入 http://192.168.0.3:8000 。这时浏览器向服务器发送的HTTP协议头如下:

    GET / HTTP/1.1
    Host: 192.168.0.3:8000
    User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.6) Gecko/20061201 Firefox/2.0.0.6 (Ubuntu-feisty)
    Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 300
    Connection: keep-alive
    
    

    注意,其中每一行的末尾都是回车加换行(C语言的"\r\n"),第一行是GET请求和协议版本,其余几行选项字段我们不讨论,HTTP协议头的最后有一个空行,也是回车加换行

    我们实现的Web服务器只要能正确解析第一行就行了,这是一个GET请求,请求的是服务目录的根目录/(在本例中实际上是/var/www),Web服务器应该把该目录下的索引页(默认是index.html)发给浏览器,也就是把/var/www/index.html发给浏览器。假如该文件的内容如下(HTML文件没必要以"\r\n"换行,以"\n"换行就可以了):

    <html>
    <head><title>Test Page</title></head>
    <body>
    	<p>Test OK</p>
    	<img src='mypic.jpg'>
    </body>
    </html>

    显示一行字和一幅图片,图片的相对路径(相对当前的index.html文件的路径)是mypic.jpg,也就是/var/www/mypic.jpg,如果用绝对路径表示应该是:

    <img src='/mypic.jpg'>

    服务器应按如下格式应答浏览器:

    HTTP/1.1 200 OK
    Content-Type: text/html
    
    <html>
    <head><title>Test Page</title></head>
    <body>
    	<p>Test OK</p>
    	<img src='mypic.jpg'>
    </body>
    </html>

    服务器应答的HTTP头也是每行末尾以回车加换行结束,最后跟一个空行的回车加换行。

    HTTP头的第一行是协议版本和应答码,200表示成功,后面的消息OK其实可以随意写,浏览器是不关心的,主要是为了调试时给开发人员看的。虽然网络协议最终是程序与程序之间的对话,但是在开发过程中却是人与程序之间的对话,一个设计透明的网络协议可以提供很多直观的信息给开发人员,因此,很多应用层网络协议,如HTTP、FTP、SMTP、POP3等都是基于文本的协议,为的是透明性(transparency)。

    HTTP头的第二行表示即将发送的文件的类型(称为MIME类型),这里是text/html,纯文本文件是text/plain,图片则是image/jpg、image/png等。

    然后就发送文件的内容,发送完毕之后主动关闭连接,这样浏览器就知道文件发送完了。这一点比较特殊:通常网络通信都是客户端主动发起连接,主动发起请求,主动关闭连接,服务器只是被动地处理各种情况,而HTTP协议规定服务器主动关闭连接(有些Web服务器可以配置成Keep-Alive的,我们不讨论这种情况)。

    浏览器收到index.html之后,发现其中有一个图片文件,就会再发一个GET请求(HTTP协议头其余部分略):

    GET /mypic.jpg HTTP/1.1

    一个较大的网页中可能有很多图片,浏览器可能在下载网页的同时就开很多线程下载图片,因此,'''服务器即使对同一个客户端也需要提供并行服务的能力'''。服务器收到这个请求应该把图片发过去然后关闭连接:

    HTTP/1.1 200 OK
    Content-Type: image/jpg
    
    (这里是mypic.jpg的二进制数据)

    这时浏览器就应该显示出完整的网页了。

    如果浏览器请求的文件在服务器上找不到,要应答一个404错误页面,例如:

    HTTP/1.1 404 Not Found
    Content-Type: text/html
    
    <html><body>request file not found</body></html>

    5.2. 执行CGI程序 

    如果浏览器请求的是一个可执行文件(不管是什么样的可执行文件,即使是shell脚本也一样),那么服务器并不把这个文件本身发给浏览器,而是把它的执行结果标准输出发给浏览器。例如一个shell脚本/var/www/myscript.sh(注意一定要加可执行权限):

    #!/bin/sh
    echo "Content-Type: text/html"
    echo
    echo "<html><body>Hello world!</body></html>"

    这样浏览器收到的是:

    HTTP/1.1 200 OK
    Content-Type: text/html
    
    <html><body>Hello world!</body></html>

    总结一下服务器的处理步骤:

    1. 解析浏览器的请求,在服务目录中查找相应的文件,如果找不到该文件就返回404错误页面

    2. 如果找到了浏览器请求的文件,用stat(2)检查它是否可执行

    3. 如果该文件可执行:

      1. 发送HTTP/1.1 200 OK给客户端

      2. fork(2),然后用dup2(2)重定向子进程的标准输出到客户端socket

      3. 在子进程中exec(3)该CGI程序

      4. 关闭连接

    4. 如果该文件不可执行:

      1. 发送HTTP/1.1 200 OK给客户端

      2. 如果是一个图片文件,根据图片的扩展名发送相应的Content-Type给客户端

      3. 如果不是图片文件,这里我们简化处理,都当作Content-Type: text/html

      4. 简单的HTTP协议头有这两行就足够了,再发一个空行表示结束

      5. 读取文件的内容发送到客户端

      6. 关闭连接

    实现简单的Web服务器 请点评

    实现一个简单的Web服务器myhttpd。服务器程序启动时要读取配置文件/etc/myhttpd.conf,其中需要指定服务器监听的端口号和服务目录,例如:

    Port=80
    Directory=/var/www

    注意,1024以下的端口号需要超级用户才能开启服务。如果你的系统中已经安装了某种Web服务器(例如Apache),应该为myhttpd选择一个不同的端口号。当浏览器向服务器请求文件时,服务器就从服务目录(例如/var/www)中找出这个文件,加上HTTP协议头一起发给浏览器。但是,如果浏览器请求的文件是可执行的则称为CGI程序,服务器并不是将这个文件发给浏览器,而是在服务器端执行这个程序,将它的标准输出发给浏览器,服务器不发送完整的HTTP协议头,CGI程序自己负责输出一部分HTTP协议头。

    5.1. 基本HTTP协议 请点评

    打开浏览器,输入服务器IP,例如 http://192.168.0.3 ,如果端口号不是80,例如是8000,则输入 http://192.168.0.3:8000 。这时浏览器向服务器发送的HTTP协议头如下:

    GET / HTTP/1.1
    Host: 192.168.0.3:8000
    User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.6) Gecko/20061201 Firefox/2.0.0.6 (Ubuntu-feisty)
    Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 300
    Connection: keep-alive
    
    

    注意,其中每一行的末尾都是回车加换行(C语言的"\r\n"),第一行是GET请求和协议版本,其余几行选项字段我们不讨论,HTTP协议头的最后有一个空行,也是回车加换行

    我们实现的Web服务器只要能正确解析第一行就行了,这是一个GET请求,请求的是服务目录的根目录/(在本例中实际上是/var/www),Web服务器应该把该目录下的索引页(默认是index.html)发给浏览器,也就是把/var/www/index.html发给浏览器。假如该文件的内容如下(HTML文件没必要以"\r\n"换行,以"\n"换行就可以了):

    <html>
    <head><title>Test Page</title></head>
    <body>
    	<p>Test OK</p>
    	<img src='mypic.jpg'>
    </body>
    </html>

    显示一行字和一幅图片,图片的相对路径(相对当前的index.html文件的路径)是mypic.jpg,也就是/var/www/mypic.jpg,如果用绝对路径表示应该是:

    <img src='/mypic.jpg'>

    服务器应按如下格式应答浏览器:

    HTTP/1.1 200 OK
    Content-Type: text/html
    
    <html>
    <head><title>Test Page</title></head>
    <body>
    	<p>Test OK</p>
    	<img src='mypic.jpg'>
    </body>
    </html>

    服务器应答的HTTP头也是每行末尾以回车加换行结束,最后跟一个空行的回车加换行。

    HTTP头的第一行是协议版本和应答码,200表示成功,后面的消息OK其实可以随意写,浏览器是不关心的,主要是为了调试时给开发人员看的。虽然网络协议最终是程序与程序之间的对话,但是在开发过程中却是人与程序之间的对话,一个设计透明的网络协议可以提供很多直观的信息给开发人员,因此,很多应用层网络协议,如HTTP、FTP、SMTP、POP3等都是基于文本的协议,为的是透明性(transparency)。

    HTTP头的第二行表示即将发送的文件的类型(称为MIME类型),这里是text/html,纯文本文件是text/plain,图片则是image/jpg、image/png等。

    然后就发送文件的内容,发送完毕之后主动关闭连接,这样浏览器就知道文件发送完了。这一点比较特殊:通常网络通信都是客户端主动发起连接,主动发起请求,主动关闭连接,服务器只是被动地处理各种情况,而HTTP协议规定服务器主动关闭连接(有些Web服务器可以配置成Keep-Alive的,我们不讨论这种情况)。

    浏览器收到index.html之后,发现其中有一个图片文件,就会再发一个GET请求(HTTP协议头其余部分略):

    GET /mypic.jpg HTTP/1.1

    一个较大的网页中可能有很多图片,浏览器可能在下载网页的同时就开很多线程下载图片,因此,'''服务器即使对同一个客户端也需要提供并行服务的能力'''。服务器收到这个请求应该把图片发过去然后关闭连接:

    HTTP/1.1 200 OK
    Content-Type: image/jpg
    
    (这里是mypic.jpg的二进制数据)

    这时浏览器就应该显示出完整的网页了。

    如果浏览器请求的文件在服务器上找不到,要应答一个404错误页面,例如:

    HTTP/1.1 404 Not Found
    Content-Type: text/html
    
    <html><body>request file not found</body></html>

    5.2. 执行CGI程序 请点评

    如果浏览器请求的是一个可执行文件(不管是什么样的可执行文件,即使是shell脚本也一样),那么服务器并不把这个文件本身发给浏览器,而是把它的执行结果标准输出发给浏览器。例如一个shell脚本/var/www/myscript.sh(注意一定要加可执行权限):

    #!/bin/sh
    echo "Content-Type: text/html"
    echo
    echo "<html><body>Hello world!</body></html>"

    这样浏览器收到的是:

    HTTP/1.1 200 OK
    Content-Type: text/html
    
    <html><body>Hello world!</body></html>

    总结一下服务器的处理步骤:

    1. 解析浏览器的请求,在服务目录中查找相应的文件,如果找不到该文件就返回404错误页面

    2. 如果找到了浏览器请求的文件,用stat(2)检查它是否可执行

    3. 如果该文件可执行:

      1. 发送HTTP/1.1 200 OK给客户端

      2. fork(2),然后用dup2(2)重定向子进程的标准输出到客户端socket

      3. 在子进程中exec(3)该CGI程序

      4. 关闭连接

    4. 如果该文件不可执行:

      1. 发送HTTP/1.1 200 OK给客户端

      2. 如果是一个图片文件,根据图片的扩展名发送相应的Content-Type给客户端

      3. 如果不是图片文件,这里我们简化处理,都当作Content-Type: text/html

      4. 简单的HTTP协议头有这两行就足够了,再发一个空行表示结束

      5. 读取文件的内容发送到客户端

      6. 关闭连接

    展开全文
  • 说到 web 服务器想必大多数人首先想到的协议是 http,那么 http 之下则是 tcp,本篇文章将通过 tcp 来实现一个简单的 web 服务器。 本篇文章将着重讲解如何实现,对于 http 与 tcp 的概念本篇将不过多讲解。 一、...
  • 实现一个简单的Web服务器

    千次阅读 2017-06-19 16:56:22
    实现一个简单的Web服务器myhttpd。服务器程序启动时要读取配置文件/etc/myhttpd.conf,其中需要指定服务器监听的端口号和服务目录,例如: Port=80 Directory=/var/www 注意,1024以下的端口号需要超级用户才能...

    实现一个简单的Web服务器myhttpd。服务器程序启动时要读取配置文件/etc/myhttpd.conf,其中需要指定服务器监听的端口号和服务目录,例如:

    Port=80
    Directory=/var/www

    注意,1024以下的端口号需要超级用户才能开启服务。如果你的系统中已经安装了某种Web服务器(例如Apache),应该为myhttpd选择一个不同的端口号。当浏览器向服务器请求文件时,服务器就从服务目录(例如/var/www)中找出这个文件,加上HTTP协议头一起发给浏览器。但是,如果浏览器请求的文件是可执行的则称为CGI程序,服务器并不是将这个文件发给浏览器,而是在服务器端执行这个程序,将它的标准输出发给浏览器,服务器不发送完整的HTTP协议头,CGI程序自己负责输出一部分HTTP协议头。

    5.1. 基本HTTP协议

    打开浏览器,输入服务器IP,例如 http://192.168.0.3 ,如果端口号不是80,例如是8000,则输入 http://192.168.0.3:8000 。这时浏览器向服务器发送的HTTP协议头如下:

    GET / HTTP/1.1
    Host: 192.168.0.3:8000
    User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.6) Gecko/20061201 Firefox/2.0.0.6 (Ubuntu-feisty)
    Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 300
    Connection: keep-alive
    
    

    注意,其中每一行的末尾都是回车加换行(C语言的"\r\n"),第一行是GET请求和协议版本,其余几行选项字段我们不讨论,HTTP协议头的最后有一个空行,也是回车加换行

    我们实现的Web服务器只要能正确解析第一行就行了,这是一个GET请求,请求的是服务目录的根目录/(在本例中实际上是/var/www),Web服务器应该把该目录下的索引页(默认是index.html)发给浏览器,也就是把/var/www/index.html发给浏览器。假如该文件的内容如下(HTML文件没必要以"\r\n"换行,以"\n"换行就可以了):

    <html>
    <head><title>Test Page</title></head>
    <body>
    	<p>Test OK</p>
    	<img src='mypic.jpg'>
    </body>
    </html>

    显示一行字和一幅图片,图片的相对路径(相对当前的index.html文件的路径)是mypic.jpg,也就是/var/www/mypic.jpg,如果用绝对路径表示应该是:

    <img src='/mypic.jpg'>

    服务器应按如下格式应答浏览器:

    HTTP/1.1 200 OK
    Content-Type: text/html
    
    <html>
    <head><title>Test Page</title></head>
    <body>
    	<p>Test OK</p>
    	<img src='mypic.jpg'>
    </body>
    </html>

    服务器应答的HTTP头也是每行末尾以回车加换行结束,最后跟一个空行的回车加换行。

    HTTP头的第一行是协议版本和应答码,200表示成功,后面的消息OK其实可以随意写,浏览器是不关心的,主要是为了调试时给开发人员看的。虽然网络协议最终是程序与程序之间的对话,但是在开发过程中却是人与程序之间的对话,一个设计透明的网络协议可以提供很多直观的信息给开发人员,因此,很多应用层网络协议,如HTTP、FTP、SMTP、POP3等都是基于文本的协议,为的是透明性(transparency)。

    HTTP头的第二行表示即将发送的文件的类型(称为MIME类型),这里是text/html,纯文本文件是text/plain,图片则是image/jpg、image/png等。

    然后就发送文件的内容,发送完毕之后主动关闭连接,这样浏览器就知道文件发送完了。这一点比较特殊:通常网络通信都是客户端主动发起连接,主动发起请求,主动关闭连接,服务器只是被动地处理各种情况,而HTTP协议规定服务器主动关闭连接(有些Web服务器可以配置成Keep-Alive的,我们不讨论这种情况)。

    浏览器收到index.html之后,发现其中有一个图片文件,就会再发一个GET请求(HTTP协议头其余部分略):

    GET /mypic.jpg HTTP/1.1

    一个较大的网页中可能有很多图片,浏览器可能在下载网页的同时就开很多线程下载图片,因此,'''服务器即使对同一个客户端也需要提供并行服务的能力'''。服务器收到这个请求应该把图片发过去然后关闭连接:

    HTTP/1.1 200 OK
    Content-Type: image/jpg
    
    (这里是mypic.jpg的二进制数据)

    这时浏览器就应该显示出完整的网页了。

    如果浏览器请求的文件在服务器上找不到,要应答一个404错误页面,例如:

    HTTP/1.1 404 Not Found
    Content-Type: text/html
    
    <html><body>request file not found</body></html>

    5.2. 执行CGI程序 

    如果浏览器请求的是一个可执行文件(不管是什么样的可执行文件,即使是shell脚本也一样),那么服务器并不把这个文件本身发给浏览器,而是把它的执行结果标准输出发给浏览器。例如一个shell脚本/var/www/myscript.sh(注意一定要加可执行权限):

    #!/bin/sh
    echo "Content-Type: text/html"
    echo
    echo "<html><body>Hello world!</body></html>"

    这样浏览器收到的是:

    HTTP/1.1 200 OK
    Content-Type: text/html
    
    <html><body>Hello world!</body></html>

    总结一下服务器的处理步骤:

    1. 解析浏览器的请求,在服务目录中查找相应的文件,如果找不到该文件就返回404错误页面

    2. 如果找到了浏览器请求的文件,用stat(2)检查它是否可执行

    3. 如果该文件可执行:

      1. 发送HTTP/1.1 200 OK给客户端

      2. fork(2),然后用dup2(2)重定向子进程的标准输出到客户端socket

      3. 在子进程中exec(3)该CGI程序

      4. 关闭连接

    4. 如果该文件不可执行:

      1. 发送HTTP/1.1 200 OK给客户端

      2. 如果是一个图片文件,根据图片的扩展名发送相应的Content-Type给客户端

      3. 如果不是图片文件,这里我们简化处理,都当作Content-Type: text/html

      4. 简单的HTTP协议头有这两行就足够了,再发一个空行表示结束

      5. 读取文件的内容发送到客户端

      6. 关闭连接

    实现简单的Web服务器 请点评

    实现一个简单的Web服务器myhttpd。服务器程序启动时要读取配置文件/etc/myhttpd.conf,其中需要指定服务器监听的端口号和服务目录,例如:

    Port=80
    Directory=/var/www

    注意,1024以下的端口号需要超级用户才能开启服务。如果你的系统中已经安装了某种Web服务器(例如Apache),应该为myhttpd选择一个不同的端口号。当浏览器向服务器请求文件时,服务器就从服务目录(例如/var/www)中找出这个文件,加上HTTP协议头一起发给浏览器。但是,如果浏览器请求的文件是可执行的则称为CGI程序,服务器并不是将这个文件发给浏览器,而是在服务器端执行这个程序,将它的标准输出发给浏览器,服务器不发送完整的HTTP协议头,CGI程序自己负责输出一部分HTTP协议头。

    5.1. 基本HTTP协议 请点评

    打开浏览器,输入服务器IP,例如 http://192.168.0.3 ,如果端口号不是80,例如是8000,则输入 http://192.168.0.3:8000 。这时浏览器向服务器发送的HTTP协议头如下:

    GET / HTTP/1.1
    Host: 192.168.0.3:8000
    User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.6) Gecko/20061201 Firefox/2.0.0.6 (Ubuntu-feisty)
    Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 300
    Connection: keep-alive
    
    

    注意,其中每一行的末尾都是回车加换行(C语言的"\r\n"),第一行是GET请求和协议版本,其余几行选项字段我们不讨论,HTTP协议头的最后有一个空行,也是回车加换行

    我们实现的Web服务器只要能正确解析第一行就行了,这是一个GET请求,请求的是服务目录的根目录/(在本例中实际上是/var/www),Web服务器应该把该目录下的索引页(默认是index.html)发给浏览器,也就是把/var/www/index.html发给浏览器。假如该文件的内容如下(HTML文件没必要以"\r\n"换行,以"\n"换行就可以了):

    <html>
    <head><title>Test Page</title></head>
    <body>
    	<p>Test OK</p>
    	<img src='mypic.jpg'>
    </body>
    </html>

    显示一行字和一幅图片,图片的相对路径(相对当前的index.html文件的路径)是mypic.jpg,也就是/var/www/mypic.jpg,如果用绝对路径表示应该是:

    <img src='/mypic.jpg'>

    服务器应按如下格式应答浏览器:

    HTTP/1.1 200 OK
    Content-Type: text/html
    
    <html>
    <head><title>Test Page</title></head>
    <body>
    	<p>Test OK</p>
    	<img src='mypic.jpg'>
    </body>
    </html>

    服务器应答的HTTP头也是每行末尾以回车加换行结束,最后跟一个空行的回车加换行。

    HTTP头的第一行是协议版本和应答码,200表示成功,后面的消息OK其实可以随意写,浏览器是不关心的,主要是为了调试时给开发人员看的。虽然网络协议最终是程序与程序之间的对话,但是在开发过程中却是人与程序之间的对话,一个设计透明的网络协议可以提供很多直观的信息给开发人员,因此,很多应用层网络协议,如HTTP、FTP、SMTP、POP3等都是基于文本的协议,为的是透明性(transparency)。

    HTTP头的第二行表示即将发送的文件的类型(称为MIME类型),这里是text/html,纯文本文件是text/plain,图片则是image/jpg、image/png等。

    然后就发送文件的内容,发送完毕之后主动关闭连接,这样浏览器就知道文件发送完了。这一点比较特殊:通常网络通信都是客户端主动发起连接,主动发起请求,主动关闭连接,服务器只是被动地处理各种情况,而HTTP协议规定服务器主动关闭连接(有些Web服务器可以配置成Keep-Alive的,我们不讨论这种情况)。

    浏览器收到index.html之后,发现其中有一个图片文件,就会再发一个GET请求(HTTP协议头其余部分略):

    GET /mypic.jpg HTTP/1.1

    一个较大的网页中可能有很多图片,浏览器可能在下载网页的同时就开很多线程下载图片,因此,'''服务器即使对同一个客户端也需要提供并行服务的能力'''。服务器收到这个请求应该把图片发过去然后关闭连接:

    HTTP/1.1 200 OK
    Content-Type: image/jpg
    
    (这里是mypic.jpg的二进制数据)

    这时浏览器就应该显示出完整的网页了。

    如果浏览器请求的文件在服务器上找不到,要应答一个404错误页面,例如:

    HTTP/1.1 404 Not Found
    Content-Type: text/html
    
    <html><body>request file not found</body></html>

    5.2. 执行CGI程序 请点评

    如果浏览器请求的是一个可执行文件(不管是什么样的可执行文件,即使是shell脚本也一样),那么服务器并不把这个文件本身发给浏览器,而是把它的执行结果标准输出发给浏览器。例如一个shell脚本/var/www/myscript.sh(注意一定要加可执行权限):

    #!/bin/sh
    echo "Content-Type: text/html"
    echo
    echo "<html><body>Hello world!</body></html>"

    这样浏览器收到的是:

    HTTP/1.1 200 OK
    Content-Type: text/html
    
    <html><body>Hello world!</body></html>

    总结一下服务器的处理步骤:

    1. 解析浏览器的请求,在服务目录中查找相应的文件,如果找不到该文件就返回404错误页面

    2. 如果找到了浏览器请求的文件,用stat(2)检查它是否可执行

    3. 如果该文件可执行:

      1. 发送HTTP/1.1 200 OK给客户端

      2. fork(2),然后用dup2(2)重定向子进程的标准输出到客户端socket

      3. 在子进程中exec(3)该CGI程序

      4. 关闭连接

    4. 如果该文件不可执行:

      1. 发送HTTP/1.1 200 OK给客户端

      2. 如果是一个图片文件,根据图片的扩展名发送相应的Content-Type给客户端

      3. 如果不是图片文件,这里我们简化处理,都当作Content-Type: text/html

      4. 简单的HTTP协议头有这两行就足够了,再发一个空行表示结束

      5. 读取文件的内容发送到客户端

      6. 关闭连接

    展开全文
  • C 语言实现一个简单的 web 服务器

    千次阅读 2020-10-30 09:04:53
    说到 web 服务器想必大多数人首先想到的协议是 http,那么 http 之下则是 tcp,本篇文章将通过 tcp 来实现一个简单的 web 服务器。 本篇文章将着重讲解如何实现,对于 http 与 tcp 的概念本篇将不过多讲解。 一、...
  • JAVA使用Scoket实现一个简单的Web服务器一、项目介绍二、整体思路三、代码实现1. WebServer.java2. Httpserver.java3.Index.html4.资源路径四、项目测试 一、项目介绍 该项目是用JAVA使用Scoket实现一个简单的Web...
  • java实现一个简单的Web服务器

    万次阅读 多人点赞 2015-04-01 07:31:34
    Web服务器也称为超文本传输协议服务器,使用http与其客户端进行通信,基于java的web服务器会使用两...这个简单的Web服务器会有以下三个类: *HttpServer *Request *Response 应用程序的入口在HttpServer类中,main
  • Web服务器也称为超文本传输协议服务器,使用http与其客户端进行通信,基于java的web...这个简单的Web服务器会有以下三个类:*HttpServer*Request*Response应用程序的入口在HttpServer类中,main()方法创建一个HttpS...
  • 现在我们自己实现一个简单的web服务器,基本的功能就是用户点击要访问的资源,服务器将资源发送到客户端的浏览器。web服务基于的是HTTP协议,用户在浏览器的地址栏输入要访问的地址,服务器如何得到该地址是个关键。...
  • Java实现一个简单的Web服务器

    千次阅读 2017-08-11 21:37:13
    import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.net.ServerSocket;...import java.net.Socket;... * 一个简单的Web服务器 * 浏览器在访问一个web
  • 在Ubuntu下实现一个简单的Web服务器

    千次阅读 2013-10-08 19:36:45
    Ubuntu下实现一个简单的Web服务器
  • Web服务器Web服务器也称为超文本传输协议服务器,使用http与其客户端进行通信,基于java的web服务器会使用两重要的类,.首先java.net.Socket类和java.net.ServerSocket类,并基于发送http消息进行通信。步骤1;...
  • import reimport socketdef service_cilent(new_socket):request = new_socket.recv(1024).decode("utf-8")# Python splitlines() 按照行('\r', '\r\n', \n')分隔,返回一个包含各行作为元素列表,如果参数 ...
  • 分享:基于epoll实现一个简单的web服务器 基于epoll实现一个简单的web服务器 http://my.oschina.net/rentiansheng/blog/115302 ...
  • Web是基于http协议的一个服务,Go语言里面提供了一个完善的net/http包,通过http包可以很方便的就搭建起来一个可以运行的Web服务。同时使用这个包能很简单地对Web的路由,静态文件,模版,cookie等数据进行设置和...
  • 实现一个简单的Web服务器(C语言)

    千次阅读 2018-11-10 10:26:13
    该项目第二部分是在第部分基础上继续完善Web服务器。 第二部分主要是完成两功能:记录日志和HTTP响应。 记录日志 该部分比较简单,只要简单地将一些服务器信息添加到指定日志文件即可, 也不需要完成很...
  • Shinatra - 只用55行bash脚本实现一个简单的web服务器
  • Web服务器也称为超文本传输协议服务器,使用http与其客户端进行通信,基于java的web...这个简单的Web服务器会有以下三个类:*HttpServer*Request*Response应用程序的入口在HttpServer类中,main()方法创建一个HttpS...
  • VSWSInC 用C实现一个非常简单的Web服务器
  • 本程序实现一个简单的连接方式为短链接的web服务器,其中html文件存储在/var/www/html下,也可自行设置其他路径 #include <stdio.h> #include <string.h> #include <assert.h> #include <...
  • Web服务器Web服务器也称为超文本传输协议服务器,使用http与其客户端进行通信,基于java的web服务器会使用两重要的类,.首先java.net.Socket类和java.net.ServerSocket类,并基于发送http消息进行通信。步骤1;...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,463
精华内容 2,585
关键字:

实现一个简单的web服务器