精华内容
下载资源
问答
  • 从零开始写一个RTSP服务器(一)RTSP协议讲解

    万次阅读 多人点赞 2019-08-09 20:17:55
    从零开始写一个RTSP服务器系列 从零开始写一个RTSP服务器(一)不一样的RTSP协议讲解 从零开始写一个RTSP服务器(二)RTP传输H.264(待) 从零开始写一个RTSP服务器(三)一个传输H.264的RTSP服务器(待) 从零开始...

    从零开始写一个RTSP服务器系列

    ★我的开源项目-RtspServer

    从零开始写一个RTSP服务器(一)RTSP协议讲解

    从零开始写一个RTSP服务器(二)RTSP协议的实现

    从零开始写一个RTSP服务器(三)RTP传输H.264

    从零开始写一个RTSP服务器(四)一个传输H.264的RTSP服务器

    从零开始写一个RTSP服务器(五)RTP传输AAC

    从零开始写一个RTSP服务器(六)一个传输AAC的RTSP服务器

    从零开始写一个RTSP服务器(七)多播传输RTP包

    从零开始写一个RTSP服务器(八)一个多播的RTSP服务器

    从零开始写一个RTSP服务器(九)一个RTP OVER RTSP/TCP的RTSP服务器

    从零开始写一个RTSP服务器(一)不一样的RTSP协议讲解

    前言

    • 为什么要写这个系列?

      因为我自己在学习rtsp协议想自己从零写一个rtsp服务器的时候,由于rtsp比较复杂,所以觉得这个过程非常的困难,网上许多相关文章或模棱两可,或是复制粘贴。所以想写这样一个系列,来帮助想要学习rtsp协议或者想要从零写一个rtsp服务器的初学者

    • 本系列的文章特点

      并系列文章实现追求精简,能够让人明白rtsp协议的实现过程,不追求复杂和完美

      如果想要实现一个比较完善的rtsp服务器,可以参考我的开源项目-RtspServer

    言归正传,下面开始本系列的文章

    一、什么是RTSP协议?

    RTSP是一个实时传输流协议,是一个应用层的协议

    通常说的RTSP包括RTSP协议RTP协议RTCP协议

    对于这些协议的作用简单的理解如下

    RTSP协议:负责服务器与客户端之间的请求与响应

    RTP协议:负责传输媒体数据

    RTCP协议:在RTP传输过程中提供传输信息

    rtsp承载与rtp和rtcp之上,rtsp并不会发送媒体数据,而是使用rtp协议传输

    rtp并没有规定发送方式,可以选择udp发送或者tcp发送

    二、RTSP协议详解

    rtsp的交互过程就是客户端请求,服务器响应,下面看一看请求和响应的数据格式

    2.1 RTSP数据格式

    RTSP协议格式与HTTP协议格式类似

    • RTSP客户端的请求格式

      method url vesion\r\n
      CSeq: x\r\n
      xxx\r\n
      ...
      \r\n
      

      method:方法,表明这次请求的方法,rtsp定义了很多方法,稍后介绍

      url:格式一般为rtsp://ip:port/session,ip表主机ip,port表端口好,如果不写那么就是默认端口,rtsp的默认端口为554,session表明请求哪一个会话

      version:表示rtsp的版本,现在为RTSP/1.0

      CSeq:序列号,每个RTSP请求和响应都对应一个序列号,序列号是递增的

    • RTSP服务端的响应格式

      vesion 200 OK\r\n
      CSeq: x\r\n
      xxx\r\n
      ...
      \r\n
      

      version:表示rtsp的版本,现在为RTSP/1.0

      CSeq:序列号,这个必须与对应请求的序列号相同

    2.2 RTSP请求的常用方法

    方法描述
    OPTIONS获取服务端提供的可用方法
    DESCRIBE向服务端获取对应会话的媒体描述信息
    SETUP向服务端发起建立请求,建立连接会话
    PLAY向服务端发起播放请求
    TEARDOWN向服务端发起关闭连接会话请求

    2.3 RTSP交互过程

    有了上述的知识,我们下面来讲解一个RTSP的交互过程

    OPTIONS

    • C–>S

      OPTIONS rtsp://192.168.31.115:8554/live RTSP/1.0\r\n
      CSeq: 2\r\n
      \r\n
      

      客户端向服务器请求可用方法

    • S–>C

      RTSP/1.0 200 OK\r\n
      CSeq: 2\r\n
      Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY\r\n
      \r\n
      

      服务端回复客户端,当前可用方法OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY

    DESCRIBE

    • C–>S

      DESCRIBE rtsp://192.168.31.115:8554/live RTSP/1.0\r\n
      CSeq: 3\r\n
      Accept: application/sdp\r\n
      \r\n
      

      客户端向服务器请求媒体描述文件,格式为sdp

    • S–>C

      RTSP/1.0 200 OK\r\n
      CSeq: 3\r\n
      Content-length: 146\r\n
      Content-type: application/sdp\r\n
      \r\n
      
      v=0\r\n
      o=- 91565340853 1 in IP4 192.168.31.115\r\n
      t=0 0\r\n
      a=contol:*\r\n
      m=video 0 RTP/AVP 96\r\n
      a=rtpmap:96 H264/90000\r\n
      a=framerate:25\r\n
      a=control:track0\r\n
      

      服务器回复了sdp文件,这个文件告诉客户端当前服务器有哪些音视频流,有什么属性,具体稍后再讲解

      这里只需要直到客户端可以根据这些信息得知有哪些音视频流可以发送

    SETUP

    • C–>S

      SETUP rtsp://192.168.31.115:8554/live/track0 RTSP/1.0\r\n
      CSeq: 4\r\n
      Transport: RTP/AVP;unicast;client_port=54492-54493\r\n
      \r\n
      

      客户端发送建立请求,请求建立连接会话,准备接收音视频数据

      解析一下Transport: RTP/AVP;unicast;client_port=54492-54493\r\n

      RTP/AVP:表示RTP通过UDP发送,如果是RTP/AVP/TCP则表示RTP通过TCP发送

      unicast:表示单播,如果是multicast则表示多播

      client_port=54492-54493:由于这里希望采用的是RTP OVER UDP,所以客户端发送了两个用于传输数据的端口,客户端已经将这两个端口绑定到两个udp套接字上,54492表示是RTP端口,54493表示RTCP端口(RTP端口为某个偶数,RTCP端口为RTP端口+1)

    • S–>C

      RTSP/1.0 200 OK\r\n
      CSeq: 4\r\n
      Transport: RTP/AVP;unicast;client_port=54492-54493;server_port=56400-56401\r\n
      Session: 66334873\r\n
      \r\n
      

      服务端接收到请求之后,得知客户端要求采用RTP OVER UDP发送数据,单播客户端用于传输RTP数据的端口为54492,RTCP的端口为54493

      服务器也有两个udp套接字,绑定好两个端口,一个用于传输RTP,一个用于传输RTCP,这里的端口号为56400-56401

      之后客户端会使用54492-54493这两端口和服务器通过udp传输数据,服务器会使用56400-56401这两端口和这个客户端传输数据

    PLAY

    • C–>S

      PLAY rtsp://192.168.31.115:8554/live RTSP/1.0\r\n
      CSeq: 5\r\n
      Session: 66334873\r\n
      Range: npt=0.000-\r\n
      \r\n
      

      客户端请求播放媒体

    • S–>C

      RTSP/1.0 200 OK\r\n
      CSeq: 5\r\n
      Range: npt=0.000-\r\n
      Session: 66334873; timeout=60\r\n
      \r\n
      

      服务器回复之后,会开始使用RTP通过udp向客户端的54492端口发送数据

    TEARDOWN

    • C–>S

      TEARDOWN rtsp://192.168.31.115:8554/live RTSP/1.0\r\n
      CSeq: 6\r\n
      Session: 66334873\r\n
      \r\n
      
    • S–>C

      RTSP/1.0 200 OK\r\n
      CSeq: 6\r\n
      \r\n
      

    2.4 sdp格式

    我们上面避开没有讲sdp文件,这里来好好补一补

    sdp格式由多行的type=value组成

    sdp会话描述由一个会话级描述和多个媒体级描述组成。会话级描述的作用域是整个会话,媒体级描述描述的是一个视频流或者音频流

    会话级描述v=开始到第一个媒体级描述结束

    媒体级描述m=开始到下一个媒体级描述结束

    下面是上面示例的sdp文件,我们就来好好分析一下这个sdp文件

    v=0\r\n
    o=- 91565340853 1 in IP4 192.168.31.115\r\n
    t=0 0\r\n
    a=contol:*\r\n
    m=video 0 RTP/AVP 96\r\n
    a=rtpmap:96 H264/90000\r\n
    a=framerate:25\r\n
    a=control:track0\r\n
    

    这个示例的sdp文件包含一个会话级描述一个媒体级描述,分别如下

    • 会话级描述

      v=0\r\n
      o=- 91565340853 1 IN IP4 192.168.31.115\r\n
      t=0 0\r\n
      a=contol:*\r\n
      

      v=0

      表示sdp的版本
      o=- 91565340853 1 IN IP4 192.168.31.115
      格式为 o=<用户名> <会话id> <会话版本> <网络类型><地址类型> <地址>
      用户名:-
      会话id:91565340853,表示rtsp://192.168.31.115:8554/live请求中的live这个会话
      会话版本:1
      网络类型:IN,表示internet
      地址类型:IP4,表示ipv4
      地址:192.168.31.115,表示服务器的地址

    • 媒体级描述

      m=video 0 RTP/AVP 96\r\n
      a=rtpmap:96 H264/90000\r\n
      a=framerate:25\r\n
      a=control:track0\r\n
      

      m=video 0 RTP/AVP 96\r\n

      格式为 m=<媒体类型> <端口号> <传输协议> <媒体格式 >
      媒体类型:video

      端口号:0,为什么是0?因为上面在SETUP过程会告知端口号,所以这里就不需要了

      传输协议:RTP/AVP,表示RTP OVER UDP,如果是RTP/AVP/TCP,表示RTP OVER TCP

      媒体格式:表示负载类型(payload type),一般使用96表示H.264

      a=rtpmap:96 H264/90000

      格式为a=rtpmap:<媒体格式><编码格式>/<时钟频率>

      a=framerate:25

      表示帧率

      a=control:track0

      表示这路视频流在这个会话中的编号

    三、RTP协议

    3.1 RTP包格式

    rtp包由rtp头部和rtp荷载构成

    • RTP头部

    在这里插入图片描述

    版本号(V):2Bit,用来标志使用RTP版本

    填充位§:1Bit,如果该位置位,则该RTP包的尾部就包含填充的附加字节

    扩展位(X):1Bit,如果该位置位,则该RTP包的固定头部后面就跟着一个扩展头部

    CSRC技术器(CC):4Bit,含有固定头部后面跟着的CSRC的数据

    标记位(M):1Bit,该位的解释由配置文档来承担

    载荷类型(PT):7Bit,标识了RTP载荷的类型

    序列号(SN):16Bit,发送方在每发送完一个RTP包后就将该域的值增加1,可以由该域检测包的丢失及恢复

    ​ 包的序列。序列号的初始值是随机的

    时间戳:32比特,记录了该包中数据的第一个字节的采样时刻

    同步源标识符(SSRC):32比特,同步源就是RTP包源的来源。在同一个RTP会话中不能有两个相同的SSRC值

    贡献源列表(CSRC List):0-15项,每项32比特,这个不常用

    • rtp荷载

      rtp载荷为音频或者视频数据

    3.2 RTP OVER TCP

    RTP默认是采用UDP发送的,格式为RTP头+RTP载荷,如果是使用TCP,那么需要在RTP头之前再加上四个字节

    第一个字节:$,辨识符

    第二个字节:通道,在SETUP的过程中获取

    第三第四个字节: RTP包的大小,最多只能12位,第三个字节保存高4位,第四个字节保存低8位

    四、RTCP

    RTCP用于在RTP传输过程中提供传输信息,可以报道RTP传输情况,还可以用来音视频同步,这里就不详细讲解了

    展开全文
  • 自己写一个Web服务器(1)

    千次阅读 2017-02-08 15:56:23
    自己写一个Web服务器(1) 2016-04-13 分类:操作系统、编程开发、首页精华1人评论 分享到:更多15 本文由码农网 – 王坚原创翻译,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划! 自己...

    自己写一个Web服务器(1)

    本文由码农网 – 王坚原创翻译,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划

    自己写一个Web服务器(1)

    自己写一个Web服务器(2)

    自己写一个Web服务器(3)

    有天一个女人出去散步,她经过建筑工地时看到三个人正在干活。她上去问第一个人,你在干什么呢?第一个人觉得这问题很恼人,厉声道,你看不到我在砌砖头吗?不甚满意的女人又问第二个人他在做什么。第二个人答道,我在砌一道砖墙。然后他看了下第一个人,喊道,嘿,你超过墙的长度了,把最后一块砖拿下来。女人还是不满意这个答案,他问第三个人。这个人呢,他一边看着天一边跟她说,我在建这世上从未有过的大教堂。在他抬头望天的时候,另两个人在为砖头的对错争吵不休。这人转向那两人说,伙计们,别为那一块砖当心了。这是个内墙,它会被粉刷没人能看到砖头的。把它放到另一层去吧。

    这个故事的寓意是,当你知道整个系统,了解不同组件如何相互配合(砖,墙壁,教堂),你能快速找到和快速解决问题(砖)。

    它对你从头开始建web服务器有什么启示呢?

    我相信要成为好的开发者,你必须对日常使用的软件底层系统有更好的理解,这包括编程语言,编译器和解释器,数据库和操作系统,web服务器和web框架。而为了能更好更深的理解这些系统,你必须从头开始重建他们,从一砖一瓦开始。

    老夫子有言曰:

    我听见了,我就忘了;

    我看见了,我就记得了;

    我做过了,我就理解了。

    我希望你同意这点,我们重新建构软件系统是学习他们怎样运作的好方法。

    在这个分为三部分的系列中,我将展示给你怎样搭建你自己的web服务器。我们开始吧。

    简而言之,这是一个运行在物理服务器上的网络服务器,它等待客户端发送的请求。当它收到一个请求,它会生成一个回复并传回到客户端。一个客户端和服务器的通信时通过HTTP协议实现。客户端可以是你的浏览器或任何其他应用HTTP的软件。

    一个简单的web服务器是什么样呢?这是我给出的答案。这个例子是用Python的,但即使你不懂Python也能通过下面的代码和解释理解这些概念。

    import socket
    
    HOST, PORT = '', 8888
    
    listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    listen_socket.bind((HOST, PORT))
    listen_socket.listen(1)
    print 'Serving HTTP on port %s ...' % PORT
    while True:
        client_connection, client_address = listen_socket.accept()
        request = client_connection.recv(1024)
        print request
    
        http_response = """\
    HTTP/1.1 200 OK
    
    Hello, World!
    """
        client_connection.sendall(http_response)
        client_connection.close()

    将上面代码保存为’websever1.py’,或者直接在GitHub上下载,然后想下面那样在命令行中运行

    $ python webserver1.py
    Serving HTTP on port 8888

    现在在浏览器地址栏输入http://localhost:8888/hello,按Enter键,奇迹就发生率。你应该能在浏览器看到“Hello,World”,如图所示:

    看到了吧。让我们来看看它到底是怎么做到的。

    从你键入的网址开始。它是一个URL下面是他的基本结构:

    这是你告诉浏览器找寻web服务器和连接的地址,也是你要获取的服务器上的页面(路径)。在你的浏览器发送HTTP请求前,它需要和web服务器建立一个TCP连接。然后它通过TCP连接发出HTTP请求,接着等待服务器返回一个HTTP响应。当浏览器收到响应后显示出来,在这个例子中它显示为“Hello World!”

    再来详细看看客户端和服务器怎样在HTTP请求响应之前建立TCP连接的。要做到这个,他们都用到了socket。不要直接用浏览器,你用telnet命令行来手动模拟浏览器。

    在同一台电脑上通过telnet会话运行web服务器,指定localhost和8888端口,按下Enter:

    $ telnet localhost 8888
    Trying 127.0.0.1 …
    Connected to localhost.

    这样你就已经跟服务器建立了TCP连接,它运行在本地主机准备好发送和接收HTTP消息。下面的图片中你可以看到服务器必须经过一个标准的程序才可能接受一个新的TCP连接。

    在同一telnet会话中键入GET /hello HTTP/1.1,按下Enter:

    $ telnet localhost 8888
    Trying 127.0.0.1 …
    Connected to localhost.
    GET /hello HTTP/1.1
    
    HTTP/1.1 200 OK
    Hello, World!

    你刚才手动模拟了浏览器!你发送了一个HTTP请求然后收到了一个HTTP响应。这就是HTTP请求的基本结构:

    HTTP请求由HTTP方法(GET,因为我们要求服务器返回给我们写东西),路径/hello指向服务器的一个“页面”和协议版本。

    为了简单的找到我们的web服务器,这个例子完全无视上面的命令行。你可以用任何没意义的东西替换“GET /hello HTTP/1.1”,还是会得到“Hello, World!”

    一旦你输入了请求而且按下了Enter,客户端就像服务器发出了请求,服务器读取请求,打印它然后做出适当的响应。
    这是HTTP响应,服务器传送到你的客户端的过程(这里是telnet):

    我们来剖析它。响应由一个状态行 HTTP/1.1 200 OK, 接着一个空白行,然后是HTTP响应主体。

    状态行 HTTP/1.1 200 OK, 由HTTP版本,HTTP状态代码和HTTP状态代码指示短语 OK 组成。当浏览器收到响应,它显示出响应主体,这就是为什么你在浏览器中看到“Hello, World!”

    这就是一个web服务器运行的基本模型。总结起来:web服务器创建一个监听socket持续地接受新的连接。客户端发起一个TCP连接,然后成功建立连接,客户端发出一个HTTP请求给服务器,服务器用HTTP响应来做回复,最后呈现给用户。建立TCP连接的过程中客户端和服务器都使用了 socket。

    现在你有了一个基本的服务器,可以在浏览器和其他HTTP客户端去测试。如你所见,你也可以做个人肉HTTP客户端,用telnet同时手动键入hTTP请求就行。

    那么问题来了:你怎么在你刚建立的web服务器上运行一个Django应用,Flask应用和Pyramid应用,如何不做任何改变而适应不同的web架构呢?

    我会在这个系列的第二篇告诉你。敬请关注!

    译文链接:http://www.codeceo.com/article/make-web-server-1.html
    英文原文:Let’s Build A Web Server. Part 1.
    翻译作者:码农网 – 王坚
    转载必须在正文中标注并保留原文链接、译文链接和译者等信息。]

    展开全文
  • //写一个登录的接口 //通过http模块创建一个服务器 const http=require('http') const url=require('url') const querystring = require('querystring'); const server = http.createServer((req, res) =&amp;gt...
    //搭建一个node api服务器
    //写一个登录的接口
    //通过http模块创建一个服务器
    const http=require('http')
    const url=require('url')
    const querystring = require('querystring');
    const server = http.createServer((req, res) => {
        //req 请求信息
        //res 回复信息
        // console.log(req)
      
        let string=req.url
        // 过滤浏览器请求图标文件
        if(string!=='/favicon.ico'){
            console.log(string)
            let urlobj=url.parse(string)
            let pathname=urlobj.pathname  //用户截取的地址信息
            let query=querystring.parse(urlobj.query) // 用户get传递的参数
            if(pathname==='/login'){
                console.log(query)
                res.writeHead(200, { 'Content-Type': 'text/plain' }); //回复的格式设置
                if(query.us==='网易'&&query.ps==='123'){
                    res.end('login ok');
                }else{
                    res.end('login nook');
                }
                
                
            }else if(pathname==='/reg'){
                res.writeHead(200, { 'Content-Type': 'text/plain' }); //回复的格式设置
                res.end('reg ok');
            }
        
            
        }
     
      });
    
      
      // 监听端口号
      server.listen(3000,()=>{
          console.log('服务器启动')
      })
    
    展开全文
  • Java写一个简单的Web服务器Socket实现

    万次阅读 多人点赞 2018-06-06 14:55:53
    Java写一个简单的Web服务器Socket实现   一、实现思路 1、使用 ServerSocket 监听某一端口,然后等待连接获取 Socket对象。 2、创建一个HttpServer 继承 java.lang.Thread 类,重写 run()方法,执行浏览器...

                        Java写一个简单的Web服务器Socket实现

     

    一、实现思路

    1、使用 ServerSocket 监听某一端口,然后等待连接获取 Socket对象。

    2、创建一个类 HttpServer 继承 java.lang.Thread 类,重写 run()方法,执行浏览器请求。

    3、获得浏览器请求,解析资源文件路径。

    4、读取资源文件,响应给浏览器。

     

    二、代码实现

    1、ServerSocket 监听端口,获取 Socket对象

    package com.httpserver.two;
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    /**
     * @description: 使用socket 自己写一个web服务器 ---监听端口,获取socket 对象。
     * @version:v1.0
     * @author:w
     * @date:2018年6月6日上午11:03:36
     *
     */
    public class WebServer {
    	public void startServer(int port){
    		try {
    			@SuppressWarnings("resource")
    			ServerSocket serverSocket = new ServerSocket(port);
    			while(true){
    				Socket socket = serverSocket.accept();
    				new HttpServer(socket).start();
    			}
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    }

     

     

    2、HttpServer.java类 --- 具体作用看方法注释。

    package com.httpserver.two;
    
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.net.Socket;
    
    /**
     * @description: 使用socket 实现 web服务器 --- 具体执行读写操作的。
     * @version:v1.0
     * @author:w
     * @date:2018年6月6日上午11:06:20
     *
     */
    public class HttpServer extends Thread {
    	/**
    	 * web资源根路径
    	 */
    	public static final String ROOT = "c:/";
    	
    	/**
    	 * 输入流对象,读取浏览器请求
    	 */
    	private InputStream input;
    	
    	/**
    	 * 输出流对象,响应内容给浏览器
    	 */
    	private OutputStream out;
    
    	/**
    	 * @description:初始化socket对象,获取对应 输入,输出流
    	 * @param socket
    	 */
    	public HttpServer(Socket socket) {
    		try {
    			input = socket.getInputStream();
    			out = socket.getOutputStream();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    
    	/**
    	 * 多线程方法调用
    	 */
    	@Override
    	public void run() {
    		String filePath = read();
    		response(filePath);
    	}
    
    	/**
    	 * @description: 读取资源文件,响应给浏览器。
    	 * @param:@param filePath
    	 *                   资源文件路径
    	 * @return:void
    	 * @version:v1.0
    	 * @author:w
    	 * @date:2018年6月6日 上午11:42:37
    	 *
    	 */
    	private void response(String filePath) {
    		File file = new File(ROOT + filePath);
    		if (file.exists()) {
    			// 1、资源存在,读取资源
    			try {
    				BufferedReader reader = new BufferedReader(new FileReader(file));
    				StringBuffer sb = new StringBuffer();
    				String line = null;
    				while ((line = reader.readLine()) != null) {
    					sb.append(line).append("\r\n");
    				}
    				StringBuffer result = new StringBuffer();
    				result.append("HTTP /1.1 200 ok /r/n");
    				result.append("Content-Type:text/html /r/n");
    				result.append("Content-Length:" + file.length() + "/r/n");
    				result.append("\r\n:" + sb.toString());
    				out.write(result.toString().getBytes());
    				out.flush();
    				out.close();
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    
    		} else {
    			// 2、资源不存在,提示 file not found
    			StringBuffer error = new StringBuffer();
    			error.append("HTTP /1.1 400 file not found /r/n");
    			error.append("Content-Type:text/html \r\n");
    			error.append("Content-Length:20 \r\n").append("\r\n");
    			error.append("<h1 >File Not Found..</h1>");
    			try {
    				out.write(error.toString().getBytes());
    				out.flush();
    				out.close();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    
    	}
    
    	/**
    	 * 
    	 * @description:解析资源文件路径
    	 * @example: GET /index.html HTTP/1.1
    	 * @param:@return
    	 * @return:String
    	 * @version:v1.0
    	 * @author:w
    	 * @date:2018年6月6日 上午11:39:42
    	 *
    	 */
    	private String read() {
    		BufferedReader reader = new BufferedReader(new InputStreamReader(input));
    		try {
    			// 读取请求头, 如:GET /index.html HTTP/1.1
    			String readLine = reader.readLine();
    			String[] split = readLine.split(" ");
    			if (split.length != 3) {
    				return null;
    			}
    			System.out.println(readLine);
    			return split[1];
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    		return null;
    	}
    
    }

    三、代码测试

    1、启动服务器

    public static void main(String[] args) {
        new WebServer().startServer(8000);
    }

     

    2、浏览器地址栏输入: http://localhost:8000/index.html

     

    3、效果如下:

     

        

     

    四、总结

    1、该示例代码可直接粘贴IDE中运行,无需任何第三方jar包。 简单简洁,便于理解。

    2、c盘中,必须有一个 index.html的文件,若存放在其他位置,请修改 HttpServer.ROOT字段,路径位置即可。

    3、若出现请求成功,响应页面为空白,请去掉 index.html 页面的 <html>标签试试。--- 至于什么问题导致的,目前还不清楚。 -_-!

    4、 index.html 代码参考

                

    <!DOCTYPE html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    	<h1>Hello World! this is my webserver!</h1>
    </body>
    

     

    五、遗留问题解决

    1、若出现请求成功,响应页面为空白,请去掉 index.html 页面的 <html>标签试试。原因是:换行符"\r\n"写错了,写成了"/r/n" 。

    2、Firefox无法解析。原因是:"HTTP /1.1 200 ok" 中,"HTTP"和"/1.1" 直接不能有空格,否则 Firefox无法解析 。正确的是: "HTTP/1.1 200 ok"。

    3、关于换行符问题补充: 

    a. windows 换行符: "\r\n

    b. linux 换行符: "\n

    c. mac 换行符:"\r"

               4、可能引发问题: 假设在 linux 中,使用 windows的换行符会有效果吗?会引发上述的问题吗?

    5、造成上述问题的发生,主要是 response header 不对导致的,chrome 浏览器可查看 response header 如下图:

     

    六、补上修改后的代码 

    package com.httpserver.two.fix;
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.net.Socket;
    /**
     * @description: 使用socket 实现 web服务器 --- 具体执行读写操作的。<br>
     * 	fix: 1、换行符写错误:"/r/n" 调整为正确: "\r\n"。 <br>
     * 		 2、"HTTP /1.1 200 ok" 中,"HTTP"和"/1.1" 直接不能有空格,否则 Firefox无法解析。<br>
     * @version:v1.1
     * @author:w
     * @date:2018年12月18日 16:50:28
     */
    public class HttpServerFix extends Thread {
    	/**
    	 * web资源根路径
    	 */
    	public static final String ROOT = "c:/";
    	
    	/**
    	 * 输入流对象,读取浏览器请求
    	 */
    	private InputStream input;
    	
    	/**
    	 * 输出流对象,响应内容给浏览器
    	 */
    	private OutputStream out;
    
    	/**
    	 * @description:初始化socket对象,获取对应 输入,输出流
    	 * @param socket
    	 */
    	public HttpServerFix(Socket socket) {
    		try {
    			input = socket.getInputStream();
    			out = socket.getOutputStream();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    
    	/**
    	 * 多线程方法调用
    	 */
    	@Override
    	public void run() {
    		String filePath = read();
    		response(filePath);
    	}
    
    	/**
    	 * @description: 读取资源文件,响应给浏览器。
    	 * @param:@param filePath
    	 *                   资源文件路径
    	 * @return:void
    	 * @version:v1.0
    	 * @author:w
    	 * @date:2018年6月6日 上午11:42:37
    	 *
    	 */
    	private void response(String filePath) {
    		File file = new File(ROOT + filePath);
    		if (file.exists()) {
    			// 1、资源存在,读取资源
    			try {
    				BufferedReader reader = new BufferedReader(new FileReader(file));
    				StringBuffer sb = new StringBuffer();
    				String line = null;
    				while ((line = reader.readLine()) != null) {
    					System.out.println("line:"+ line);
    					sb.append(line).append("\r\n");
    				}
    				StringBuffer result = new StringBuffer();
    				/**
    				 * 1、 换行符"/r/n"写错了,正确的是: "\r\n"
    				 * 2、"HTTP /1.1 ..."之间不能有空格,否则Firfox不能解析
    				 * 3、 关于换行符的补充:
    				 * 	  a.windows:"\r\n"
    				 *    b.linux:"\n"
    				 *    c.mac:"\r" 
    				 */
    			//	result.append("HTTP /1.1 200 ok /r/n");
    				result.append("HTTP/1.1 200 ok \r\n");
    				result.append("Content-Language:zh-CN \r\n");
    				// charset=UTF-8 解决中文乱码问题
    				result.append("Content-Type:text/html;charset=UTF-8 \r\n");
    				result.append("Content-Length:" + file.length() + "\r\n");
    				result.append("\r\n" + sb.toString());
    				out.write(result.toString().getBytes());
    				out.flush();
    				out.close();
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    
    		} else {
    			// 2、资源不存在,提示 file not found
    			StringBuffer error = new StringBuffer();
    			error.append("HTTP/1.1 400 file not found \r\n");
    			error.append("Content-Type:text/html \r\n");
    			error.append("Content-Length:20 \r\n").append("\r\n");
    			error.append("<h1 >File Not Found..</h1>");
    			try {
    				out.write(error.toString().getBytes());
    				out.flush();
    				out.close();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    
    	}
    
    	/**
    	 * 
    	 * @description:解析资源文件路径
    	 * @example: GET /index.html HTTP/1.1
    	 * @param:@return
    	 * @return:String
    	 * @version:v1.0
    	 * @author:w
    	 * @date:2018年6月6日 上午11:39:42
    	 *
    	 */
    	private String read() {
    		BufferedReader reader = new BufferedReader(new InputStreamReader(input));
    		try {
    			// 读取请求头, 如:GET /index.html HTTP/1.1
    			String readLine = reader.readLine();
    			String[] split = readLine.split(" ");
    			if (split.length != 3) {
    				return null;
    			}
    			System.out.println(readLine);
    			return split[1];
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    		return null;
    	}
    
    }
    

     

    最后,感谢 Vito_w7 的指点迷津!

     

    展开全文
  • 自己用java写一个http和https代理服务器

    千次阅读 热门讨论 2019-05-13 16:21:37
    如果这实现的代理器只是你自己用的话或者少数几个人用的话,我觉得完全没问题,自己也试了,看视频啥的也没啥问题(如果你看的视频需要全部下载到本地后才能播放,那就只能把socket的过期时间设置长点了,不过现在...
  • 用C++写一个简单的服务器(Linux)

    千次阅读 2018-11-07 19:16:18
    用C++写一个简单的服务器(Linux) 下面是创建一个简单服务器的基本流程,所用的端口是8099。后面贴了代码。 一、基本流程: 创建套接字 配置服务器地址相关参数 将两者绑定 监听套接字上的端口 在上面创建的套接字...
  • 1. 前言 如今一提到服务器首先就...俗话说自己动手丰衣足食,今天我们就来实现一个简单的静态web服务器。 2. http协议 谈到浏览器,服务器时,作为计算机行业从业者,首先想到的就是www、http、https、html等等,...
  • 从零开始学写HTTP服务器) http协议简介
  • 用python写一个简单的web服务器

    万次阅读 2018-04-02 08:44:47
    人生苦短,我用python简洁高效,这才是理想的语言啊分享一点python的学习经验-----如何用python写一个简单的web服务器首先,我们需要简单地了解一下网络通信协议,这里用白话介绍一下TCP和UDP这两种传输层的协议TCP...
  • 女朋友说:“看你最近挺辛苦的,我送你一个礼物吧。...于是,我认真了起来,拿起手机,上淘宝逛了几分钟,但还是没能想出来缺点什么,最后实在没办法了:“这样吧,如果你实在想送东西,那你就写一个代理服务器吧”...
  • Python写一个简易的web服务器

    千次阅读 2019-01-17 16:00:49
    现在,我们准备我们的第一个简单的Web服务器。基本思想非常简单: 1.等待有人来连接我们的服务器,发送HTTP请求; 2.解析请求; 3.找出它的要求; 4.获取数据(或动态生成它); 5.把数据格式化为HTML;...
  • 自己写一个简单的Web服务器(附Demo)

    千次阅读 2015-03-22 22:52:47
    下面的示例代码演示了如何通过 java.net.Socket 与 java.net.ServerSocket这两个重要的类创建一个简单基于 Java 的 Web 服务器 。这个服务器通过8784号端口提供访问,向浏览器返回一个固定的静态网页。在这个示例中,...
  • JAVA写HTTP代理服务器()-socket实现

    万次阅读 2017-09-04 16:12:40
    HTTP代理服务器是一种特殊的网络服务,允许一个网络终端(一般为客户端)通过这个服务与另一个网络终端(一般为服务器)进行非直接的连接。一些网关、路由器等网络设备具备网络代理功能。一般认为代理服务有利于保障...
  • 用c一个简单web服务器实现

    千次阅读 2013-10-11 08:58:16
    本程序的目的是实现一个web服务器,在服务器启动时读取配置文件config.txt,然后浏览器向服务器发送请求,服务器向浏览器发送index.html,文件发送完毕后服务器关闭与浏览器的链接,告知浏览器文件已发送完毕,...
  • Python 实现一个简单的http服务器

    万次阅读 2014-03-29 14:17:26
    写一个python脚本,实现简单的http服务器功能: 1.浏览器中输入网站地址:172.20.52.163:20014 2.server接到浏览器的请求后,读取本地的index.html文件的内容,回发给浏览器  代码实现 server.py #!/usr/bin/python...
  • Linux实现一个简单的HTTP服务器

    千次阅读 2018-06-24 10:51:09
    代码实现 : Makefile : .PHONY:all clean ...http_server:http_server.c ...
  • Anroid搭建一个局域网Web服务器

    万次阅读 多人点赞 2016-06-14 00:31:19
    其实我想到的是Socket和Http,我们知道Http是基于Socket的,所以它是一个非常成熟的Socket,所以我选择了用Http来实现,今天的博客内容也是主要讲Android端如何搭建一个Http服务器
  • c++编写一个简单的Http服务器

    千次阅读 2019-06-28 19:40:21
    5.实现简单http服务器 github头文件: tcp_pthread_server.hpp与tcp_socket.hpp # include "tcp_pthread_server.hpp" # include using namespace std ; void HttpProcess ( string & req , ...
  • 然而,远程服务器是无法直接调用本地摄像头的数据的,要实现这一功能,只好在远程搭建一个http服务端,与本地的客户端通过curl进行通信。 在实现这一功能之前,首先来实现一个相对简单的功能:在客户端以1s为间隔向...
  • 网友的JAVA版HTTP服务器程序

    千次阅读 2013-10-09 14:23:22
    平时都是直接使用第三方软件作为WEB的HTTP服务器,比如IIS,Apache 的Tomcat等,了解一下HTTP服务器程序是怎么编写的很有必要,这样增加了解HTTP服务器的处理过程,下面是网友的JAVA版HTTP服务器程序,很有参考...
  • 用node.js写一个简单的服务器,只使用了20行左右的代码,支持根据视频名字点播,视频文件和node.js文件放在同一目录下; 服务器代码如下: var express = require('express'); var pg = require('pg'); var app = ...
  • 快速搭建一个自己的服务器详解(java环境)

    万次阅读 多人点赞 2018-07-19 22:12:51
    1. 我选择的是阿里云的服务器,学生价9.5元一个月,百度直接搜索阿里云,然后点击右上角登录,推荐大家用支付宝扫码登录,方便快捷。阿里云官网的东西比较多,登录后我找了很久也没有找到学生服务器在哪里卖,最后在...
  • 终于有人把域名和DNS服务器明白了

    万次阅读 多人点赞 2020-05-10 16:39:17
    终于有人把域名和DNS服务器明白了
  • 自己动手写http服务器---java版

    万次阅读 2013-10-05 17:52:41
    最简单的http服务器,可下载源码:...1.通过socket向服务器发送一个符合一定格式的请求字符串(里面包含了用户输入的网址),比如: Accept text/html,application/xhtml+xml,
  • Go搭建一个Web服务器

    万次阅读 2016-07-31 03:14:07
    前面小节已经介绍了Web是基于http协议的一个服务,Go语言里面提供了一个完善的net/http包,通过http包可以很方便的就搭建起来一个可以运行的Web服务。同时使用这个包能很简单地对Web的路由,静态文件,模版,cookie...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,164,938
精华内容 465,975
关键字:

写一个http服务器