文档章节

简单的Socket实现的http Server

SuShine
 SuShine
发布于 2015/09/07 17:35
字数 913
阅读 93
收藏 4

代码下载地址  http://note.youdao.com/share/?id=1d28ee946720332255efc72c3e12a0da&type=note

参考 http://blog.csdn.net/u010687392/article/details/44649589

/**
 * 
 * @className: MainActivity
 * @description: 手机红外客户端:处理TV请求发射的红外码
 * @author: Administrator
 * @date: 2015年9月6日 上午9:40:13
 */
public class MainActivity extends Activity
{
    private TextView mInputText;
    ServerSocket server = null;
    Socket socket = null;
    private TextView mTitleText;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTitleText = (TextView) findViewById(R.id.title);
        mInputText = (TextView) findViewById(R.id.msg);
        initServiceData();
        mTitleText.setText("IP:" + getIp());
        
    }
    
    private String getIp() {
        WifiManager wifimanger = (WifiManager) getSystemService(WIFI_SERVICE);
        WifiInfo wifiinfo = wifimanger.getConnectionInfo();
        int i = wifiinfo.getIpAddress();
        return (i & 0xFF) + "." + ((i >> 8) & 0xFF) + "." + ((i >> 16) & 0xFF) + "." + (i >> 24 & 0xFF);
    }
    
    private void initServiceData() {
        
        new Thread()
        {
            @Override
            public void run() {
                
                try {
                    server = new ServerSocket(8888);//创建一个ServerSocket,并让Socket监听8888的端口
                    
                    // 调用ServerSocket的accept()方法,接受客户端所发送的请求,同时创建一个Socket对象
                    // 如果客户端没有发送数据,那么该线程就停滞不继续,也就是阻塞
                    while (true) {
                        socket = server.accept();
                        System.out.println("主机:" + socket.getInetAddress().getHostName() + ",IP:" + socket.getInetAddress().getHostAddress());//得到当前发送数据Socket对象的主机名和ip地址
                        
                        //读取客户端的消息
                        InputStream inputStream = socket.getInputStream();
                        BufferedInputStream bis = new BufferedInputStream(inputStream);
                        //byte[] b = new byte[inputStream.available()];
                        byte[] b = new byte[1024 * 2];
                        int len = -1;
                        final StringBuilder stringBuilder = new StringBuilder();
                        while ((len = bis.read(b)) != -1) {
                            String msg = new String(b, 0, len, "UTF-8");
                            System.out.println(msg);
                            stringBuilder.append(msg);
                            break;//一次只能读取2048个自己的请求数据, 当然也可以更加content lenght计算, 然后跳出循环. 注意.这里 read(b) 永远不会是-1 因为读取到输入流末尾之后, socket还是会尝试读取client的数据
                        }
                        
                        runOnUiThread(new Runnable()
                        {
                            @Override
                            public void run() {
                                HttpRequestParser httpRequestParser = new HttpRequestParser();
                                try {
                                    httpRequestParser.parseRequest(stringBuilder.toString());
                                    mInputText.append(stringBuilder.toString() + "\n=================\n\n");
                                    //mInputText.append(URLDecoder.decode(httpRequestParser.getMessageBody(), "UTF-8"));
                                    Log.d("TAG", "params is " + URLDecoder.decode(httpRequestParser.getMessageBody(), "UTF-8"));
                                    
                                }
                                catch (IOException e) {
                                    e.printStackTrace();
                                }
                                catch (HttpFormatException e) {
                                    e.printStackTrace();
                                }
                                
                            }
                        });
                        socket.shutdownInput();//结束读取
                        
                        //--------向客户端的返回信息-------------
                        OutputStream outputResult = socket.getOutputStream();
                        StringBuffer sb = new StringBuffer();
                        sb.append("HTTP/1.1 200 OK\r\n");
                        sb.append("Host: " + socket.getInetAddress().getHostName() + "\r\n");
                        sb.append("\r\n");
                        outputResult.write(sb.toString().getBytes());
                        outputResult.write("ok,received".getBytes());
                        outputResult.flush();
                        
                        bis.close();//关闭缓存输入流,注意,输入流input不需要关闭,因为它只是在Socket中得到输入流对象,并没有创建
                        
                        socket.close();//接收这个Socket的数据后释放资源,因为每一次客户端发送数据都会在服务端创建一个Socket对象,注意ServerSocket不应该关闭,因为这是服务器ServerSocket对象,关闭了客户端就不能发送数据了
                        socket = null;
                        
                    }
                    
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();
        
    }
}



Http报文解析类
/**
 * Class for HTTP request parsing as defined by RFC 2612:
 * 
 * Request = Request-Line ; Section 5.1 (( general-header ; Section 4.5 |
 * request-header ; Section 5.3 | entity-header ) CRLF) ; Section 7.1 CRLF [
 * message-body ] ; Section 4.3
 * 
 * @author izelaya
 *
 */
public class HttpRequestParser
{
    
    private String _requestLine;
    private HashMap<String, String> _requestHeaders;
    private StringBuffer _messagetBody;
    
    public HttpRequestParser() {
        _requestHeaders = new HashMap<String, String>();
        _messagetBody = new StringBuffer();
    }
    
    /**
     * Parse and HTTP request.
     * 
     * @param request
     *            String holding http request.
     * @throws IOException
     *             If an I/O error occurs reading the input stream.
     * @throws HttpFormatException
     *             If HTTP Request is malformed
     */
    public void parseRequest(String request) throws IOException, HttpFormatException {
        if (TextUtils.isEmpty(request)) {
            return;
        }
        BufferedReader reader = new BufferedReader(new StringReader(request));
        
        setRequestLine(reader.readLine()); // Request-Line ; Section 5.1
        
        String header = reader.readLine();
        while (header.length() > 0) {
            appendHeaderParameter(header);
            header = reader.readLine();
        }
        
        String bodyLine = reader.readLine();
        while (bodyLine != null) {
            appendMessageBody(bodyLine);
            bodyLine = reader.readLine();
        }
        
    }
    
    /**
     * 
     * 5.1 Request-Line The Request-Line begins with a method token, followed by
     * the Request-URI and the protocol version, and ending with CRLF. The
     * elements are separated by SP characters. No CR or LF is allowed except in
     * the final CRLF sequence.
     * 
     * @return String with Request-Line
     */
    public String getRequestLine() {
        return _requestLine;
    }
    
    private void setRequestLine(String requestLine) throws HttpFormatException {
        if (requestLine == null || requestLine.length() == 0) {
            throw new HttpFormatException("Invalid Request-Line: " + requestLine);
        }
        _requestLine = requestLine;
    }
    
    private void appendHeaderParameter(String header) throws HttpFormatException {
        int idx = header.indexOf(":");
        if (idx == -1) {
            throw new HttpFormatException("Invalid Header Parameter: " + header);
        }
        _requestHeaders.put(header.substring(0, idx), header.substring(idx + 1, header.length()));
    }
    
    /**
     * The message-body (if any) of an HTTP message is used to carry the
     * entity-body associated with the request or response. The message-body
     * differs from the entity-body only when a transfer-coding has been
     * applied, as indicated by the Transfer-Encoding header field (section
     * 14.41).
     * 
     * @return String with message-body
     */
    public String getMessageBody() {
        return _messagetBody.toString();
    }
    
    private void appendMessageBody(String bodyLine) {
        _messagetBody.append(bodyLine).append("\r\n");
    }
    
    /**
     * For list of available headers refer to sections: 4.5, 5.3, 7.1 of RFC
     * 2616
     * 
     * @param headerName
     *            Name of header
     * @return String with the value of the header or null if not found.
     */
    public String getHeaderParam(String headerName) {
        return _requestHeaders.get(headerName);
    }
    
    public class HttpFormatException extends Exception
    {
        
        private static final long serialVersionUID = 1L;
        
        public HttpFormatException(String string) {}
        
    }
}



© 著作权归作者所有

SuShine
粉丝 128
博文 590
码字总数 158440
作品 0
朝阳
后端工程师
私信 提问
柳大的Linux讲义·基础篇(4)网络编程基础

柳大的Linux游记·基础篇(4)网络编程基础 Author: 柳大·Poechant Blog: Blog.CSDN.net/Poechant Email:zhongchao.usytc#gmail.com (#->@) Date:March 11th, 2012 Copyright © 柳大·P......

晨曦之光
2012/04/24
89
0
详解如何使用koa实现socket.io官网的例子

socket.io官网中使用express实现了一个最简单的IM即时聊天,今天我们使用koa来实现一下 框架准备 1.确保你本地已经安装好了nodejs和npm,使用koa要求node版本>7.6 2.在你需要的位置新建一个文...

peakedness丶
01/07
496
1
Python学习之HTTP模块

我学习的习惯,除了学习如何使用,还喜欢研究源码,学习运行机制,这样用起来才会得心应手或者说,使用这些语言或框架,就和平时吃饭睡觉一样,非常自然;因为最近有接触到bottle和flask web...

天使爱美
2016/11/08
16
0
用Python脚本定制自己的Web服务器

标题很宏伟,实现很遥远。 首先要说明这其实是一个不可能完成的任务,至少不是一片博文就能完成的任务。避免浪费看到标题而满心期待同道的时间。 主要是想以Apache为蓝本,通过Python脚本的方...

散居江湖
2013/01/23
0
0
Java Socket编程(理论)

socket chat: http://www.cn-java.com/download/data/book/socket_chat.pdf 一、网络编程中的两个问题: 1.找到指定主机:IP层负责网络主机的定位; 2.可靠高效的传输数据:TCP层提供面向应用...

YuanyuanL
2015/08/20
33
0

没有更多内容

加载失败,请刷新页面

加载更多

OpenStack 简介和几种安装方式总结

OpenStack :是一个由NASA和Rackspace合作研发并发起的,以Apache许可证授权的自由软件和开放源代码项目。项目目标是提供实施简单、可大规模扩展、丰富、标准统一的云计算管理平台。OpenSta...

小海bug
昨天
6
0
DDD(五)

1、引言 之前学习了解了DDD中实体这一概念,那么接下来需要了解的就是值对象、唯一标识。值对象,值就是数字1、2、3,字符串“1”,“2”,“3”,值时对象的特征,对象是一个事物的具体描述...

MrYuZixian
昨天
6
0
数据库中间件MyCat

什么是MyCat? 查看官网的介绍是这样说的 一个彻底开源的,面向企业应用开发的大数据库集群 支持事务、ACID、可以替代MySQL的加强版数据库 一个可以视为MySQL集群的企业级数据库,用来替代昂贵...

沉浮_
昨天
6
0
解决Mac下VSCode打开zsh乱码

1.乱码问题 iTerm2终端使用Zsh,并且配置Zsh主题,该主题主题需要安装字体来支持箭头效果,在iTerm2中设置这个字体,但是VSCode里这个箭头还是显示乱码。 iTerm2展示如下: VSCode展示如下: 2...

HelloDeveloper
昨天
8
0
常用物流快递单号查询接口种类及对接方法

目前快递查询接口有两种方式可以对接,一是和顺丰、圆通、中通、天天、韵达、德邦这些快递公司一一对接接口,二是和快递鸟这样第三方集成接口一次性对接多家常用快递。第一种耗费时间长,但是...

程序的小猿
昨天
10
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部